vendor/assets/javascripts/xooie/widgets/dropdown.js in xooie-1.0.4 vs vendor/assets/javascripts/xooie/widgets/dropdown.js in xooie-1.0.5

- old
+ new

@@ -19,265 +19,300 @@ * * A widget used to hide and show content. * As of v1.0 this widget has been deprecated. Use the more semantically appropriate * [[Xooie.Tooltip]], [[Xooie.Menu]], [[Xooie.Tab]], or [[Xooie.Accordion]] classes instead. **/ -define('xooie/widgets/dropdown', ['jquery', 'xooie/widgets/base'], function($, Base) { +define('xooie/widgets/dropdown', ['jquery', 'xooie/widgets/base', 'xooie/helpers'], function ($, Base, helpers) { + 'use strict'; + function parseWhich(which) { + if (typeof which === 'string') { + which = which.split(','); + return which.map(function (string) { return parseInt(string, 10); }); + } - var parseWhich = function(which) { - if (typeof which === 'string') { - which = which.split(','); - return which.map(function(string){ return parseInt(string, 10); }); - } else if (typeof which === 'number') { - return [which]; - } + if (typeof which === 'number') { + return [which]; + } - return which; - }; + return which; + } /** - * Xooie.Dropdown(element[, addons]) - * - element (Element | String): A jQuery-selected element or string selector for the root element of this widget - * - addons (Array): An optional collection of [[Xooie.Addon]] classes to be instantiated with this widget - * - * Instantiates a new Dropdown widget. Creates event handlers to manage activating and deactivating the expanders. - * Also adds methods to manipulate aria roles. - **/ - var Dropdown = Base.extend(function() { - var self = this, - handles = self.getHandle(), - expanders = self.getExpander(); +* Xooie.Dropdown(element[, addons]) +* - element (Element | String): A jQuery-selected element or string selector for the root element of this widget +* - addons (Array): An optional collection of [[Xooie.Addon]] classes to be instantiated with this widget +* +* Instantiates a new Dropdown widget. Creates event handlers to manage activating and deactivating the expanders. +* Also adds methods to manipulate aria roles. +**/ + var Dropdown = Base.extend(function () { + var self, handles, expanders; - this.handlers = { - off: function(event){ - if ((typeof event.data.not !== 'undefined' && ($(event.data.not).is($(this)) || $(event.target).parents(event.data.not).length > 0)) || (typeof event.data.which !== 'undefined' && event.data.which.indexOf(event.which) === -1) || ($(event.target).is(self.getExpander(event.data.index)) || $(event.target).parents(self.dropdownExpanderSelector()).length > 0) && !$(event.target).is($(this))) { - return true; - } + self = this; + handles = self.getHandle(); + expanders = self.getExpander(); - event.preventDefault(); + this.handlers = { + off: function (event) { + var check = false; - self.collapse(event.data.index, event.data); - }, + if (!helpers.isUndefined(event.data.not)) { + check = $(event.data.not).is($(this)) || $(event.target).parents(event.data.not).length > 0; + } - on: function(event){ - var index = event.data.index || parseInt($(this).attr('data-dropdown-index'), 10), - delay = event.data.delay, - handle = $(this); + if (!helpers.isUndefined(event.data.which)) { + check = check || event.data.which.indexOf(event.which) === -1; + } - if ((typeof event.data.not !== 'undefined' && ($(event.data.not).is($(this)) || $(event.target).parents(event.data.not).length > 0)) || typeof event.data.which !== 'undefined' && event.data.which.indexOf(event.which) === -1) { - return true; - } + check = check || ($(event.target).is(self.getExpander(event.data.index)) || $(event.target).parents(self.dropdownExpanderSelector()).length > 0); + check = check && !$(event.target).is($(this)); - event.preventDefault(); + if (check) { + return true; + } - self.expand(index, event.data); - } - }; + event.preventDefault(); - this.timers = { - expand: [], - collapse: [], - throttle: [] - }; + self.collapse(event.data.index, event.data); + }, - this.addHandlers('on'); + on: function (event) { + var index, check; - this.root().on({ - dropdownExpand: function(event, index){ - self.removeHandlers('on', index); + index = event.data.index || parseInt($(this).attr('data-dropdown-index'), 10); - self.addHandlers('off', index); + if (!helpers.isUndefined(event.data.not)) { + check = $(event.data.not).is($(this)); + check = check || $(event.target).parents(event.data.not).length > 0; + } - $(this).attr('aria-selected', true); - self.getExpander(index).attr('aria-hidden', false); - }, + check = check || (!helpers.isUndefined(event.data.which) && event.data.which.indexOf(event.which) === -1); - dropdownCollapse: function(event, index){ - self.removeHandlers('off', index); + if (check) { + return true; + } - self.addHandlers('on', index); + event.preventDefault(); - $(this).attr('aria-selected', false); - self.getExpander(index).attr('aria-hidden', true); - } - }, this.dropdownHandleSelector()); + self.expand(index, event.data); + } + }; - this.root().on('xooie-init.dropdown xooie-refresh.dropdown', function(){ - handles.each(function(index){ - var handle = $(this), - expander = expanders.eq(index); + this.timers = { + expand: [], + collapse: [], + throttle: [] + }; + this.addHandlers('on'); - handle.attr({ - 'data-dropdown-index': index, - 'aria-selected': false - }); - expander.attr({ - 'data-dropdown-index': index, - 'aria-hidden': true - }); - }); - }); + this.root().on({ + dropdownExpand: function (event, index) { + self.removeHandlers('on', index); - expanders.on('mouseover focus', function(){ - var index = parseInt($(this).attr('data-dropdown-index'), 10); + self.addHandlers('off', index); - if (self.timers.collapse[index]){ - self.timers.collapse[index] = clearTimeout(self.timers.collapse[index]); + $(this).attr('aria-selected', true); + self.getExpander(index).attr('aria-hidden', false); - $(this).on('mouseleave blur', {index: index}, function(event){ - self.collapse(event.data.index, 0); - $(this).unbind(event); - }); - } - }); + event.preventDefault(); + }, - }); + dropdownCollapse: function (event, index) { + self.removeHandlers('off', index); - Dropdown.define('namespace', 'dropdown'); + self.addHandlers('on', index); - Dropdown.define('throttleDelay', 300); + $(this).attr('aria-selected', false); + self.getExpander(index).attr('aria-hidden', true); - Dropdown.define('triggers', { - on: { - focus: { - delay: 0 - } - }, - off: { - blur: { - delay: 0 - } - } + event.preventDefault(); + } + }, this.dropdownHandleSelector()); + + this.root().on('xooie-init.dropdown xooie-refresh.dropdown', function () { + handles.each(function (index) { + var handle, expander; + + handle = $(this); + expander = expanders.eq(index); + + handle.attr({ + 'data-dropdown-index': index, + 'aria-selected': false + }); + expander.attr({ + 'data-dropdown-index': index, + 'aria-hidden': true + }); + }); }); - Dropdown.defineReadOnly('dropdownHandleSelector', '[data-role="dropdown-handle"]'); + expanders.on('mouseover focus', function () { + var index = parseInt($(this).attr('data-dropdown-index'), 10); - Dropdown.defineReadOnly('dropdownExpanderSelector', '[data-role="dropdown-content"]'); + if (self.timers.collapse[index]) { + self.timers.collapse[index] = clearTimeout(self.timers.collapse[index]); - Dropdown.defineReadOnly('activeDropdownClass', 'is-dropdown-active'); + $(this).on('mouseleave blur', {index: index}, function (event) { + self.collapse(event.data.index, 0); + $(this).unbind(event); + }); + } + }); + }); - Dropdown.prototype.getTriggerHandle = function(triggerData, index){ - var handles = this.getHandle(index); + Dropdown.define('namespace', 'dropdown'); - if (triggerData.selector) { - return triggerData.selector === 'document' ? $(document) : $(triggerData.selector); - } else { - return handles; - } - }; + Dropdown.define('throttleDelay', 300); - Dropdown.prototype.addHandlers = function(state, index){ - var trigger, handle, triggerData, countName; + Dropdown.define('triggers', { + on: { + focus: { + delay: 0 + } + }, + off: { + blur: { + delay: 0 + } + } + }); - triggerData = this.triggers()[state]; + Dropdown.defineReadOnly('dropdownHandleSelector', '[data-role="dropdown-handle"]'); - for (trigger in triggerData) { - if (typeof triggerData[trigger].which !== 'undefined') { - triggerData[trigger].which = parseWhich(triggerData[trigger].which); - } + Dropdown.defineReadOnly('dropdownExpanderSelector', '[data-role="dropdown-content"]'); - countName = [trigger,state,'count'].join('-'); + Dropdown.defineReadOnly('activeDropdownClass', 'is-dropdown-active'); - handle = this.getTriggerHandle(triggerData[trigger], index); + Dropdown.prototype.getTriggerHandle = function (triggerData, index) { + var handles = this.getHandle(index); - handle.data(countName, handle.data(countName) + 1 || 1); + if (triggerData.selector) { + return triggerData.selector === 'document' ? $(document) : $(triggerData.selector); + } + return handles; + }; - handle.on(trigger, $.extend({delay: 0, index: index}, triggerData[trigger]), this.handlers[state]); + Dropdown.prototype.addHandlers = function (state, index) { + var trigger, handle, triggerData, countName; + + triggerData = this.triggers()[state]; + + for (trigger in triggerData) { + if (triggerData.hasOwnProperty(trigger)) { + if (!helpers.isUndefined(triggerData[trigger].which)) { + triggerData[trigger].which = parseWhich(triggerData[trigger].which); } - }; - Dropdown.prototype.removeHandlers = function(state, index){ - var trigger, handle, triggerData, countName, eventCount; + countName = [trigger, state, 'count'].join('-'); - triggerData = this.triggers()[state]; + handle = this.getTriggerHandle(triggerData[trigger], index); - for (trigger in triggerData) { - handle = this.getTriggerHandle(triggerData[trigger], index); + handle.data(countName, handle.data(countName) + 1 || 1); - countName = [trigger,state,'count'].join('-'); + handle.on(trigger, $.extend({delay: 0, index: index}, triggerData[trigger]), this.handlers[state]); + } + } + }; - eventCount = handle.data(countName) - 1; + Dropdown.prototype.removeHandlers = function (state, index) { + var trigger, handle, triggerData, countName, eventCount; - if (eventCount <= 0) { - handle.unbind(trigger, this.handlers[state]); + triggerData = this.triggers()[state]; - handle.data(countName, 0); - } else { - handle.data(countName, eventCount); - } - } - }; + for (trigger in triggerData) { + if (triggerData.hasOwnProperty(trigger)) { + handle = this.getTriggerHandle(triggerData[trigger], index); - Dropdown.prototype.getHandle = function(index){ - var handles = this.root().find(this.dropdownHandleSelector()); + countName = [trigger, state, 'count'].join('-'); - return (typeof index !== 'undefined' && index >= 0) ? handles.eq(index) : handles; - }; + eventCount = handle.data(countName) - 1; - Dropdown.prototype.getExpander = function(index){ - var selectorString; + if (eventCount <= 0) { + handle.unbind(trigger, this.handlers[state]); - if (typeof index === 'undefined' || isNaN(index)) { - selectorString = this.dropdownExpanderSelector(); + handle.data(countName, 0); } else { - selectorString = this.dropdownExpanderSelector() + '[data-dropdown-index="' + index + '"]'; + handle.data(countName, eventCount); } + } + } + }; - return this.root().find(selectorString); - }; + Dropdown.prototype.getHandle = function (index) { + var handles = this.root().find(this.dropdownHandleSelector()); - Dropdown.prototype.setState = function(index, data, active){ - if (typeof index === 'undefined' || isNaN(index)) { - return; - } + return (!helpers.isUndefined(index) && index >= 0) ? handles.eq(index) : handles; + }; - var state = active ? 'expand' : 'collapse', - counterState = active ? 'collapse' : 'expand', - delay = data.delay; + Dropdown.prototype.getExpander = function (index) { + var selectorString; - this.timers[counterState][index] = clearTimeout(this.timers[counterState][index]); + if (helpers.isUndefined(index) || isNaN(index)) { + selectorString = this.dropdownExpanderSelector(); + } else { + selectorString = this.dropdownExpanderSelector() + '[data-dropdown-index="' + index + '"]'; + } - if (this.timers.throttle[index] || this.timers[state][index]) { - return; - } + return this.root().find(selectorString); + }; - this.timers[state][index] = setTimeout(function(i, _state, _active, _data) { - var expander = this.getExpander(i), - handle = this.getHandle(i), - self = this; + Dropdown.prototype.setState = function (index, data, active) { + if (helpers.isUndefined(index) || isNaN(index)) { + return; + } - this.timers[_state][i] = clearTimeout(this.timers[_state][i]); + var state, counterState, delay; - expander.toggleClass(this.activeDropdownClass(), _active); - this.getHandle(i).toggleClass(this.activeDropdownClass(), _active); + state = active ? 'expand' : 'collapse'; + counterState = active ? 'collapse' : 'expand'; + delay = data.delay; - if (_active){ - handle.trigger('dropdownExpand', [i, _data]); - } else { - handle.trigger('dropdownCollapse', [i, _data]); - } + this.timers[counterState][index] = clearTimeout(this.timers[counterState][index]); - if (this.throttleDelay() > 0){ - this.timers.throttle[i] = setTimeout(function(){ - self.timers.throttle[i] = clearTimeout(self.timers.throttle[i]); - }, this.throttleDelay()); - } + if (this.timers.throttle[index] || this.timers[state][index]) { + return; + } - }.bind(this, index, state, active, data), delay); - }; + this.timers[state][index] = setTimeout(function (i, _state, _active, _data) { + var expander, handle, self; - Dropdown.prototype.expand = function(index, data) { - if (!this.getHandle(index).hasClass(this.activeDropdownClass())) { - this.setState(index, data, true); - } - }; + expander = this.getExpander(i); + handle = this.getHandle(i); + self = this; - Dropdown.prototype.collapse = function(index, data) { - if (this.getHandle(index).hasClass(this.activeDropdownClass())) { - this.setState(index, data, false); - } - }; + this.timers[_state][i] = clearTimeout(this.timers[_state][i]); - return Dropdown; + expander.toggleClass(this.activeDropdownClass(), _active); + this.getHandle(i).toggleClass(this.activeDropdownClass(), _active); + + if (_active) { + handle.trigger('dropdownExpand', [i, _data]); + } else { + handle.trigger('dropdownCollapse', [i, _data]); + } + + if (this.throttleDelay() > 0) { + this.timers.throttle[i] = setTimeout(function () { + self.timers.throttle[i] = clearTimeout(self.timers.throttle[i]); + }, this.throttleDelay()); + } + + }.bind(this, index, state, active, data), delay); + }; + + Dropdown.prototype.expand = function (index, data) { + if (!this.getHandle(index).hasClass(this.activeDropdownClass())) { + this.setState(index, data, true); + } + }; + + Dropdown.prototype.collapse = function (index, data) { + if (this.getHandle(index).hasClass(this.activeDropdownClass())) { + this.setState(index, data, false); + } + }; + + return Dropdown; }); \ No newline at end of file