diff --git a/index.js b/index.js
index fbb7a3bdc..ed871679c 100644
--- a/index.js
+++ b/index.js
@@ -12,8 +12,8 @@ define(function (require) {
};
// programmatically injecting this is so much easier than writing the html by hand 376 times...
- $('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id], dt[id]').each(function (i) {
- $(this).prepend([' '].join(''));
+ $('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id], dt[id], section[id]').each(function (i) {
+ $(this).children('h2:first').prepend([' '].join(''));
});
// load fuel controls
@@ -945,13 +945,11 @@ define(function (require) {
$('#mySpinbox1').spinbox();
});
-
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TREE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- $('#myTree1').tree({
- dataSource: function (parentData, callback) {
+ var treeDataSource = function (parentData, callback) {
log("Opening branch data: ", parentData);
setTimeout(function () {
@@ -1018,7 +1016,10 @@ define(function (require) {
]
});
}, 400);
- },
+ }
+
+ $('#myTree1').tree({
+ dataSource: treeDataSource,
cacheItems: true,
folderSelect: true,
multiSelect: true
@@ -1226,6 +1227,51 @@ define(function (require) {
log('Disclosed All, this many recursions: ', data.disclosures);
});
+ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ SUPERPICKER
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+ $('#btnPickerEnable').click(function () {
+ $('#mypicker').picker('enable');
+ });
+ $('#btnPickerDisable').click(function () {
+ $('#mypicker').picker('disable');
+ });
+ $('#btnPickerDestroy').click(function () {
+ var $container = $('#mypicker').parent();
+ var markup = $('#mypicker').picker('destroy');
+ log(markup);
+ $container.append(markup);
+ $('#mypicker').picker({
+ edit: true
+ });
+ });
+
+ $('#mypicker').on('accepted.fu.picker', function() {
+ console.log('accepted.fu.picker');
+ });
+ $('#mypicker').on('cancelled.fu.picker', function() {
+ console.log('cancelled.fu.picker');
+ });
+ $('#mypicker').on('exited.fu.picker', function() {
+ console.log('exited.fu.picker');
+ });
+ $('#mypicker').on('shown.fu.picker', function() {
+ console.log('shown.fu.picker');
+ });
+
+ $('#myPickerTree1').tree({
+ dataSource: treeDataSource,
+ cacheItems: true,
+ folderSelect: true,
+ multiSelect: true
+ });
+
+ // requires https://github.com/exacttarget/get-list-item-path
+ // $('#mypicker2').on('accepted.fu.picker', function(o){
+ // var selected = $('#myPickerTree1').find('.tree-selected');
+ // var selectedPaths = getListItemPaths('#myPickerTree1', selected, '.tree-label', '/', ', ');
+ // $('#mypicker2').picker('setValue', selectedPaths);
+ // });
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WIZARD
diff --git a/js/all.js b/js/all.js
index 70a760f92..665b9e6d3 100644
--- a/js/all.js
+++ b/js/all.js
@@ -39,6 +39,7 @@
require('fuelux/search');
require('fuelux/spinbox');
require('fuelux/selectlist');
+ require('fuelux/picker');
require('fuelux/tree');
require('fuelux/wizard');
diff --git a/js/picker.js b/js/picker.js
new file mode 100644
index 000000000..e3274ef52
--- /dev/null
+++ b/js/picker.js
@@ -0,0 +1,293 @@
+/*
+ * Fuel UX Picker
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2014 ExactTarget
+ * Licensed under the BSD New license.
+ */
+
+// -- BEGIN UMD WRAPPER PREFACE --
+
+// For more information on UMD visit:
+// https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
+
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // if AMD loader is available, register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS
+ module.exports = factory(require('jquery'));
+ } else {
+ // OR use browser globals if AMD is not present
+ factory(jQuery);
+ }
+}(function ($) {
+ // -- END UMD WRAPPER PREFACE --
+
+ // -- BEGIN MODULE CODE HERE --
+
+ var old = $.fn.picker;
+
+ // PLACARD CONSTRUCTOR AND PROTOTYPE
+
+ var Picker = function Picker(element, options) {
+ var self = this;
+ this.$element = $(element);
+ this.options = $.extend({}, $.fn.picker.defaults, options);
+
+ this.$accept = this.$element.find('.picker-accept');
+ this.$cancel = this.$element.find('.picker-cancel');
+ this.$trigger = this.$element.find('.picker-trigger');
+ this.$footer = this.$element.find('.picker-footer');
+ this.$header = this.$element.find('.picker-header');
+ this.$popup = this.$element.find('.picker-popup');
+ this.$body = this.$element.find('.picker-body');
+
+ this.clickStamp = '_';
+
+ this.isInput = this.$trigger.is('input');
+
+ this.$trigger.on('keydown.fu.picker', $.proxy(this.keyComplete, this));
+ this.$trigger.on('focus.fu.picker', $.proxy(function inputFocus(e){
+ if(typeof e === "undefined" || $(e.target).is('input[type=text]')){
+ $.proxy(this.show(), this);
+ }
+ }, this));
+ this.$trigger.on('click.fu.picker', $.proxy(function triggerClick(e){
+ if(!$(e.target).is('input[type=text]')){
+ $.proxy(this.toggle(), this);
+ }else{
+ $.proxy(this.show(), this);
+ }
+ }, this));
+ this.$accept.on('click.fu.picker', $.proxy(this.complete, this, 'accepted'));
+ this.$cancel.on('click.fu.picker', function (e) {
+ e.preventDefault(); self.complete('cancelled');
+ });
+
+
+ };
+
+ var _isOffscreen = function _isOffscreen(picker) {
+ var windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+ var scrollTop = $(document).scrollTop();
+ var popupTop = picker.$popup.offset();
+ var popupBottom = popupTop.top + picker.$popup.outerHeight(true);
+
+ //if the bottom of the popup goes off the page, but the top does not, dropup.
+ if (popupBottom > windowHeight + scrollTop || popupTop.top < scrollTop){
+ return true;
+ }else{//otherwise, prefer showing the top of the popup only vs the bottom
+ return false;
+ }
+ };
+
+ var _display = function _display(picker) {
+ picker.$popup.css('visibility', 'hidden');
+
+ _showBelow(picker);
+
+ //if part of the popup is offscreen try to show it above
+ if(_isOffscreen(picker)){
+ _showAbove(picker);
+
+ //if part of the popup is still offscreen, prefer cutting off the bottom
+ if(_isOffscreen(picker)){
+ _showBelow(picker);
+ }
+ }
+
+ picker.$popup.css('visibility', 'visible');
+ };
+
+ var _showAbove = function _showAbove(picker) {
+ picker.$popup.css('top', - picker.$popup.outerHeight(true) + 'px');
+ };
+
+ var _showBelow = function _showBelow(picker) {
+ picker.$popup.css('top', picker.$trigger.outerHeight(true) + 'px');
+ };
+
+ Picker.prototype = {
+ constructor: Picker,
+
+ complete: function complete(action) {
+ var EVENT_CALLBACK_MAP = {
+ 'accepted': 'onAccept',
+ 'cancelled': 'onCancel',
+ 'exited': 'onExit'
+ };
+ var func = this.options[ EVENT_CALLBACK_MAP[action] ];
+
+ var obj = {
+ contents: this.$body
+ };
+
+ if (func) {
+ func(obj);
+ this.$element.trigger(action + '.fu.picker', obj);
+ } else {
+ this.$element.trigger(action + '.fu.picker', obj);
+ this.hide();
+ }
+ },
+
+ keyComplete: function keyComplete(e) {
+ if (this.isInput && e.keyCode === 13) {
+ this.complete('accepted');
+ this.$trigger.blur();
+ } else if (e.keyCode === 27) {
+ this.complete('exited');
+ this.$trigger.blur();
+ }
+ },
+
+ destroy: function destroy() {
+ this.$element.remove();
+ // remove any external bindings
+ $(document).off('click.fu.picker.externalClick.' + this.clickStamp);
+ // empty elements to return to original markup
+ // [none]
+ // return string of markup
+ return this.$element[0].outerHTML;
+ },
+
+ disable: function disable() {
+ this.$element.addClass('disabled');
+ this.$trigger.attr('disabled', 'disabled');
+ },
+
+ enable: function enable() {
+ this.$element.removeClass('disabled');
+ this.$trigger.removeAttr('disabled');
+ },
+
+ toggle: function toggle() {
+ if (this.$element.hasClass('showing')) {
+ this.hide();
+ }else{
+ this.show();
+ }
+ },
+
+ hide: function hide() {
+ if (!this.$element.hasClass('showing')) {
+ return;
+ }
+
+ this.$element.removeClass('showing');
+ $(document).off('click.fu.picker.externalClick.' + this.clickStamp);
+ this.$element.trigger('hidden.fu.picker');
+ },
+
+ externalClickListener: function externalClickListener(e, force) {
+ if (force === true || this.isExternalClick(e)) {
+ this.complete('exited');
+ }
+ },
+
+ isExternalClick: function isExternalClick(e) {
+ var el = this.$element.get(0);
+ var exceptions = this.options.externalClickExceptions || [];
+ var $originEl = $(e.target);
+ var i, l;
+
+ if (e.target === el || $originEl.parents('.picker:first').get(0) === el) {
+ return false;
+ } else {
+ for (i = 0, l = exceptions.length; i < l; i++) {
+ if ($originEl.is(exceptions[i]) || $originEl.parents(exceptions[i]).length > 0) {
+ return false;
+ }
+
+ }
+ }
+
+ return true;
+ },
+
+ show: function show() {
+ var other;
+
+ other = $(document).find('.picker.showing');
+ if (other.length > 0) {
+ if (other.data('fu.picker') && other.data('fu.picker').options.explicit) {
+ return;
+ }
+
+ other.picker('externalClickListener', {}, true);
+ }
+
+ this.$element.addClass('showing');
+
+ _display(this);
+
+ this.$element.trigger('shown.fu.picker');
+
+ this.clickStamp = new Date().getTime() + (Math.floor(Math.random() * 100) + 1);
+ if (!this.options.explicit) {
+ $(document).on('click.fu.picker.externalClick.' + this.clickStamp, $.proxy(this.externalClickListener, this));
+ }
+ }
+ };
+
+ // PLACARD PLUGIN DEFINITION
+
+ $.fn.picker = function picker(option) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var methodReturn;
+
+ var $set = this.each(function () {
+ var $this = $(this);
+ var data = $this.data('fu.picker');
+ var options = typeof option === 'object' && option;
+
+ if (!data) {
+ $this.data('fu.picker', (data = new Picker(this, options)));
+ }
+
+ if (typeof option === 'string') {
+ methodReturn = data[option].apply(data, args);
+ }
+ });
+
+ return (methodReturn === undefined) ? $set : methodReturn;
+ };
+
+ $.fn.picker.defaults = {
+ onAccept: undefined,
+ onCancel: undefined,
+ onExit: undefined,
+ externalClickExceptions: [],
+ explicit: false
+ };
+
+ $.fn.picker.Constructor = Picker;
+
+ $.fn.picker.noConflict = function noConflict() {
+ $.fn.picker = old;
+ return this;
+ };
+
+ // DATA-API
+
+ $(document).on('focus.fu.picker.data-api', '[data-initialize=picker]', function (e) {
+ var $control = $(e.target).closest('.picker');
+ if (!$control.data('fu.picker')) {
+ $control.picker($control.data());
+ }
+ });
+
+ // Must be domReady for AMD compatibility
+ $(function () {
+ $('[data-initialize=picker]').each(function () {
+ var $this = $(this);
+ if ($this.data('fu.picker')) return;
+ $this.picker($this.data());
+ });
+ });
+
+ // -- BEGIN UMD WRAPPER AFTERWORD --
+}));
+// -- END UMD WRAPPER AFTERWORD --
diff --git a/js/placard.js b/js/placard.js
index 6e67451be..605f5c7fa 100644
--- a/js/placard.js
+++ b/js/placard.js
@@ -242,7 +242,7 @@
this.$field.val(val);
- if (!suppressEllipsis && !_isShown) {
+ if (!suppressEllipsis && !_isShown(this)) {
this.applyEllipsis();
}
diff --git a/less/fuelux.less b/less/fuelux.less
index ea152566b..1e6d781de 100644
--- a/less/fuelux.less
+++ b/less/fuelux.less
@@ -26,6 +26,7 @@
@import "scheduler.less";
@import "search.less";
@import "selectlist.less";
+@import "picker.less";
@import "tree.less";
@import "wizard.less";
@import "utility.less";
diff --git a/less/picker.less b/less/picker.less
new file mode 100644
index 000000000..807b6c6c5
--- /dev/null
+++ b/less/picker.less
@@ -0,0 +1,166 @@
+.fuelux {
+
+ .picker {
+ display: inline-block;
+ position: relative;
+
+ &[data-ellipsis="true"] {
+ &.showing {
+ input.picker-field {
+ overflow: visible;
+ text-overflow: clip;
+ white-space: normal;
+ }
+ }
+
+ input.picker-field {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ &::-ms-clear {
+ display:none;
+ }
+ }
+
+ textarea.picker-field {
+ &[readonly] {
+ overflow: hidden;
+ }
+ }
+ }
+
+ &.showing {
+ .picker-footer,
+ .picker-header,
+ .picker-popup {
+ display: block;
+ z-index: 1;
+ }
+
+ input.picker-field, textarea.picker-field {
+ background: @true-white;
+ border: 1px solid @gray80;
+ box-shadow: none;
+ position: relative;
+ z-index: 1;
+ }
+ }
+
+ input.picker-field, textarea.picker-field {
+ resize: none;
+
+ &[readonly] {
+ background: @true-white;
+ cursor: auto;
+
+ &.glass {
+ background: none;
+
+ &:hover {
+ background: @infoBackground;
+ cursor: pointer;
+ }
+ }
+ }
+
+ &:focus {
+ border: 1px solid @gray80;
+ box-shadow: none;
+ }
+ }
+
+ &-cancel {
+ font-size: 12px;
+ margin-right: 4px;
+ vertical-align: middle;
+ }
+
+ &-footer,
+ &-header {
+ display: none;
+ left: 0;
+ line-height: 1;
+ right: 0;
+ }
+
+ &-footer {
+ padding: 8px 10px 8px 0;
+ text-align: right;
+ bottom: 0;
+ position: absolute;
+ }
+
+ &-header {
+ height: 31px;
+ padding: 8px 0 0px 10px;
+
+ h1, h2, h3, h4, h5, h6 {
+ margin: 0;
+ }
+ }
+
+ &-popup {
+ background: @infoBackground;
+ background-clip: padding-box;
+ border: 1px solid @gray80;
+ border-radius: 4px;
+ box-shadow: 0 0 0 1px @true-white inset;
+ display: none;
+ position: absolute;
+ padding-left: 6px;
+ padding-right: 6px;
+ height: 234px;
+ width: 350px;
+ margin: 4px 0;
+
+ }
+
+ .picker-body.well {
+ background-color: #fff;
+ overflow: scroll;
+ padding: 0;
+ height: 165px;
+ }
+
+ .tree {
+ border: none;
+ }
+
+ .glass {
+ background: transparent;
+ border: 1px solid @true-white;
+ box-shadow: none;
+
+ &:hover {
+ background: @infoBackground;
+ border-color: @focusColor;
+ cursor: pointer;
+
+ &[disabled] {
+ background: transparent;
+ border-color: @true-white;
+ cursor: not-allowed;
+ }
+ }
+
+ &:focus {
+ background: @true-white;
+ border-color: @focusColor;
+ box-shadow: inset 0 1px 1px fade(@true-black, 75%), 0 0 8px fade(@focusColor, 60%);
+ cursor: auto;
+
+ &[disabled] {
+ background: transparent;
+ border-color: @true-white;
+ cursor: not-allowed;
+ }
+ }
+
+ &[disabled] {
+ cursor: not-allowed;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/test/markup/picker-markup.html b/test/markup/picker-markup.html
new file mode 100644
index 000000000..fdf4654ba
--- /dev/null
+++ b/test/markup/picker-markup.html
@@ -0,0 +1,51 @@
+
+
+
Sample Markup
+
+
+
+
\ No newline at end of file
diff --git a/test/picker-test.js b/test/picker-test.js
new file mode 100644
index 000000000..308b581d3
--- /dev/null
+++ b/test/picker-test.js
@@ -0,0 +1,306 @@
+/*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/
+/*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/
+/*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/
+
+define(function(require){
+ var $ = require('jquery');
+ var html = require('text!test/markup/picker-markup.html!strip');
+
+ require('bootstrap');
+ require('fuelux/picker');
+
+ module('Fuel UX Picker');
+
+ test('should be defined on jquery object', function () {
+ ok($().find('#picker1').picker(), 'picker method is defined');
+ });
+
+ test('should return element', function () {
+ var $picker = $(html).find('#picker1');
+ ok($picker.picker() === $picker, 'picker should be initialized');
+ });
+
+ test('should show and hide as expected - input', function(assert){
+ var $picker = $(html).find('#picker1');
+
+ $('body').append($picker);
+ $picker.picker();
+
+ var cancelledDone = assert.async();
+ var allDone = assert.async();
+
+ var $textInputTrigger = $($picker.find('.picker-trigger')[0]);
+ var $otherTrigger = $($picker.find('.picker-trigger')[1]);
+ $textInputTrigger.focus().focus();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+
+ $picker.one('exited.fu.picker', function(e, helpers){
+ ok(1===1, 'default action event (exited) triggered upon external click');
+ cancelledDone();
+ });
+
+ $('body').click();
+
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+
+ $textInputTrigger.click();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+
+ $textInputTrigger.click();
+ equal($picker.hasClass('showing'), true, 'picker continues showing when text input clicked and picker is already showing');
+
+ $otherTrigger.click();
+ equal($picker.hasClass('showing'), false, 'picker hides when non-text input clicked and picker is already showing');
+
+ $picker.remove();
+ allDone();
+ });
+
+ test('should behave as expected - button', function(assert){
+ var $picker = $(html).find('#picker2');
+ $('body').append($picker);
+ $picker.picker();
+
+ var cancelledDone = assert.async();
+ var allDone = assert.async();
+ $picker.one('exited.fu.picker', function(e, helpers){
+ ok(1===1, 'default action event (exited) triggered upon external click');
+ cancelledDone();
+ });
+
+ $($picker.find('.picker-trigger')[1]).click();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+
+ $('body').click();
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+ $picker.remove();
+
+ allDone();
+ });
+
+ test('show/hide functions should behave as expected', function(assert){
+ var $picker = $(html).find('#picker1');
+ $('body').append($picker);
+ $picker.picker();
+
+ var shownDone = assert.async();
+ var hiddenDone = assert.async();
+ var allDone = assert.async();
+
+ $picker.one('shown.fu.picker', function(e){
+ ok(1===1, 'shown event triggers on show');
+ equal(typeof e, 'object', 'event object passed in shown event');
+ shownDone();
+ });
+ $picker.one('hidden.fu.picker', function(e, helpers){
+ ok(1===1, 'hidden event triggers on hide');
+ equal(typeof e, 'object', 'event object passed in hidden event');
+ hiddenDone();
+ });
+
+ $picker.picker('show');
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+
+ $picker.picker('hide');
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+
+ allDone();
+
+ $picker.remove();
+ });
+
+ test('trigger events should fire as expected', function(assert){
+ var $picker = $(html).find('#picker1');
+
+ $('body').append($picker);
+ $picker.picker();
+
+
+ var acceptedDone = assert.async();
+ var cancelledDone = assert.async();
+ var exitedDone = assert.async();
+ var allDone = assert.async();
+
+ $picker.one('accepted.fu.picker', function(e, helpers){
+ ok(1===1, 'accept event triggers on accept');
+ equal(typeof e, 'object', 'event object passed in accept event');
+ equal(typeof helpers, 'object', 'helpers object passed in accept event');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ acceptedDone();
+ });
+ $picker.one('cancelled.fu.picker', function(e, helpers){
+ ok(1===1, 'cancel event triggers on cancel');
+ equal(typeof e, 'object', 'event object passed in cancel event');
+ equal(typeof helpers, 'object', 'helpers object passed in cancel event');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ cancelledDone();
+ });
+ $picker.on('exited.fu.picker', function(e, helpers){
+ ok(1===1, 'exit event triggers on exit');
+ equal(typeof e, 'object', 'event object passed in exit event');
+ equal(typeof helpers, 'object', 'helpers object passed in exit event');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ exitedDone();
+ });
+
+
+ $picker.find('.picker-trigger')[0].click();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+ $picker.find('.picker-cancel').click();
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+ $picker.find('.picker-trigger')[0].click();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+ $picker.find('.picker-accept').click();
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+ $picker.find('.picker-trigger')[0].click();
+ equal($picker.hasClass('showing'), true, 'picker shows when appropriate');
+ $('body').click();
+ equal($picker.hasClass('showing'), false, 'picker hides when appropriate');
+ allDone();
+
+ $picker.remove();
+ });
+
+ test('onAccept function should be called as expected', function(assert){
+ var $picker = $(html).find('#picker1');
+
+ var acceptedDone = assert.async();
+ $picker.picker({
+ onAccept: function(helpers){
+ ok(1===1, 'onAccept function called on accept');
+ equal(typeof helpers, 'object', 'helpers object passed to onAccept function');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ $picker.picker('hide');
+ acceptedDone();
+ }
+ });
+
+ $picker.find('.picker-trigger')[0].click();
+ $picker.find('.picker-accept').click();
+ });
+
+ test('onCancel function should be called as expected', function(assert){
+ var $picker = $(html).find('#picker1');
+
+ var cancelledDone = assert.async();
+ $picker.picker({
+ onCancel: function(helpers){
+ ok(1===1, 'onCancel function called on cancel');
+ equal(typeof helpers, 'object', 'helpers object passed to onCancel function');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ $picker.picker('hide');
+ cancelledDone();
+ }
+ });
+
+ $picker.find('.picker-trigger')[0].click();
+ $picker.find('.picker-cancel').click();
+ });
+
+ test('onExit function should be called as expected', function(assert){
+ var $picker = $(html).find('#picker1');
+ $('body').append($picker);
+
+ var exitedDone = assert.async();
+ $picker.picker({
+ onExit: function(helpers){
+ ok(1===1, 'onExit function called on exit');
+ equal(typeof helpers, 'object', 'helpers object passed to onExit function');
+ equal((helpers.contents!==undefined), true, 'helpers object contains correct attributes');
+ $picker.picker('hide');
+ exitedDone();
+ }
+ });
+
+ $picker.find('.picker-trigger')[0].click();
+ $('body').click();
+ });
+
+ test('Enter and exit keys should trigger appropriate response', function(assert){
+ var $picker = $(html).find('#picker1');
+ $('body').append($picker);
+
+ var $input = $($picker.find('input')[0]);
+ var e = $.Event("keydown");
+
+ var acceptedDone = assert.async();
+ var exitedDone = assert.async();
+ $picker.picker({
+ onAccept: function(e){
+ ok(1===1, 'onAccept function called when enter keypress');
+ acceptedDone();
+ },
+ onExit: function(){
+ ok(1===1, 'onExit function called when exit keypress');
+ exitedDone();
+ }
+ });
+
+ e.keyCode = 13;
+ $input.trigger(e);
+ e.keyCode = 27;
+ $input.trigger(e);
+
+ $picker.remove();
+ });
+
+
+ test('externalClickExceptions option should work as expected', function(){
+ var $picker = $(html).find('#picker1');
+
+ $('body').append('
');
+ $('body').append($picker);
+ $picker.picker({
+ externalClickExceptions: ['.test', '#test']
+ });
+
+ $picker.find('.picker-trigger')[0].click();
+ $('#test').click();
+ equal($picker.hasClass('showing'), true, 'externalClick ignored for specified id');
+ $('.test').click();
+ equal($picker.hasClass('showing'), true, 'externalClick ignored for specified class');
+ $('.innerTest').click();
+ equal($picker.hasClass('showing'), true, 'externalClick ignored for child of specified selector');
+
+ $picker.remove();
+ $('.test,#test').remove();
+ });
+
+ test('explicit option should work as expected', function(){
+ var $picker = $(html).find('#picker1');
+
+ $('body').append($picker);
+ $picker.picker({
+ explicit: true
+ });
+
+ $picker.find('.picker-trigger')[0].click();
+ $('body').click();
+ equal($picker.hasClass('showing'), true, 'externalClick ignored due to not being an explicit accept/cancel action');
+ $picker.find('.picker-accept').click();
+ equal($picker.hasClass('showing'), false, 'picker not showing after explicit action');
+
+ $picker.remove();
+ });
+
+ test('should disable/enable as expected', function(){
+ var $picker = $(html).find('#picker1');
+ var $trigger = $picker.find('.picker-trigger');
+
+ $picker.picker('disable');
+ equal($picker.hasClass('disabled'), true, 'disabled class properly added to element');
+ equal($trigger.attr('disabled'), 'disabled', 'disabled attribute properly added to trigger');
+
+ $picker.picker('enable');
+ equal($picker.hasClass('disabled'), false, 'disabled class properly removed from element');
+ equal($trigger.attr('disabled'), undefined, 'disabled attribute properly removed from trigger');
+ });
+
+ test("should destroy control", function () {
+ var $el = $(html).find('#picker1');
+
+ equal(typeof( $el.picker('destroy')) , 'string', 'returns string (markup)');
+ equal( $el.parent().length, false, 'control has been removed from DOM');
+ });
+
+});
diff --git a/test/tests.html b/test/tests.html
index 1ebda4a85..35ee2b179 100644
--- a/test/tests.html
+++ b/test/tests.html
@@ -96,6 +96,7 @@
'fuelux/search': 'dist/js/fuelux',
'fuelux/selectlist': 'dist/js/fuelux',
'fuelux/spinbox': 'dist/js/fuelux',
+ 'fuelux/picker': 'dist/js/fuelux',
'fuelux/tree': 'dist/js/fuelux',
'fuelux/wizard': 'dist/js/fuelux'
}
diff --git a/test/tests.js b/test/tests.js
index 3b96e441e..d311c26dd 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -6,7 +6,7 @@ define(function(require){
var $ = require('jquery');
QUnit.start(); // starting qunit, or phantom js will have a problem
-
+
// Needed for saucelab testing
var log = [];
var testName;
@@ -58,6 +58,7 @@ define(function(require){
require('./test/search-test');
require('./test/selectlist-test');
require('./test/spinbox-test');
+ require('./test/picker-test');
require('./test/tree-test');
require('./test/wizard-test');