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