/* * jQuery UI Selectgroup @VERSION * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Depends: * jquery.ui.core.js * jquery.ui.widget.js * jquery.ui.position.js */ (function($, undefined) { $.widget('ui.selectgroup', { version: '@VERSION', options: { autoWidth: true, classInherit: { select: true, option: true, optionGroup: true }, positioning: { of: null, my: 'left top', at: 'left bottom', offset: null, collision: 'none' }, style: 'dropdown', handleWidth: 26 }, isOpen: false, isActive: false, position: 0, search: ['', '', 1, 1, 0], timer: null, _create: function() { var that = this, id = this.element.attr('id'); this.identifiers = ['ui-' + id, 'ui-' + id]; if ($.ui.selectgroup.group.initialised === false) { $('body').append($.ui.selectgroup.group); $.ui.selectgroup.group.hide(); } $.ui.selectgroup.group.initialised = true; if ($(this.element).find('option:selected').length) { this.copy = this.element.find('option:selected').text(); } else { this.copy = this.element.find('option').first().text(); } this.placeholder = $('' + ''+ this.copy +'' + ''); if (this.options.classInherit.select) { this.placeholder.addClass(this.element.attr('class')); } if (this.options.style === 'popup') { this.placeholder.addClass(this.widgetBaseClass + '-popup'); this.placeholder.find('.' + this.widgetBaseClass + '-icon').removeClass('ui-icon-triangle-1-s').addClass('ui-icon-triangle-2-n-s'); } this.element.after(this.placeholder).hide(); this._placeholderEvents(true); $('label[for="' + id + '"]').attr( 'for', this.identifiers[0] ) .bind('click.selectgroup', function(event) { event.preventDefault(); that.placeholder.focus(); }); $(document).bind('click.selectmenu', function(event) { if (that.isOpen && !($(event.target).closest('.ui-selectgroup').length || $(event.target).closest('.ui-selectgroup-group').length)) { window.setTimeout( function() { that.blur(); that.close(); $.ui.selectgroup.group.past = null; }, (100)); } }); }, _placeholderEvents: function(value) { var that = this; if (value === true) { this.placeholder.removeClass('ui-state-disabled') .bind('click.selectgroup', function(event) { event.preventDefault(); that._toggle(); }) .bind('keydown.selectgroup', function(event) { switch (event.keyCode) { case $.ui.keyCode.ENTER: event.preventDefault(); if (that.isOpen) { that.close(); } break; case $.ui.keyCode.ESCAPE: event.preventDefault(); if (that.isOpen) { that.blur(); that.close(); } break; case $.ui.keyCode.UP: case $.ui.keyCode.LEFT: event.preventDefault(); if (!that.isActive) { that.focus(); } that._traverse(-1); break; case $.ui.keyCode.DOWN: case $.ui.keyCode.RIGHT: event.preventDefault(); if (!that.isActive) { that.focus(); } that._traverse(1); break; case $.ui.keyCode.TAB: if (!that.isActive) { that.blur(); } if (that.isOpen) { that.close(); } break; default: event.preventDefault(); if (!that.isActive) { that.focus(); } that._typeahead(String.fromCharCode(event.keyCode).toLowerCase()); break; } }) .bind('mouseover.selectgroup', function(event) { $(this).addClass('ui-state-hover'); }) .bind('mouseout.selectgroup', function(event) { $(this).removeClass('ui-state-hover'); }); } else { this.placeholder.addClass('ui-state-disabled').unbind('.selectgroup'); this.placeholder.bind('click.selectgroup', function(event) { event.preventDefault(); }) .bind('keydown.selectgroup', function(event) { event.preventDefault(); }); } }, _index: function() { this.selectors = $.map($('option', this.element), function(value) { return { element: $(value), text: $(value).text(), classname: $(value).attr('class'), optgroup: $(value).parent('optgroup'), optgroupClassname: $(value).parent('optgroup').attr('class'), optDisabled: $(value).parent('optgroup').attr('disabled'), value: $(value).attr('value'), selected: $(value).attr('selected'), disabled: $(value).attr('disabled') }; }); }, _renderGroup: function() { var that = this, hidden = false; this.group = $(''); if (this.options.autoWidth) { if (this.options.style === 'dropdown') { $.ui.selectgroup.group.width(this.placeholder.width()); } else { $.ui.selectgroup.group.width(this.placeholder.width() - this.options.handleWidth); } } if (this.options.style === 'popup') { this.group.addClass(this.widgetBaseClass + '-popup'); } this._renderOption(); this.group.attr('aria-labelledby', this.identifiers[0]); $($.ui.selectgroup.group).html(this.group); }, _renderOption: function() { var that = this; $.each(this.selectors, function(index) { var self = this; var list = $('
  • '+ this.text +'
  • ') .bind('click.selectgroup', function(event) { event.preventDefault(); if (!(self.disabled === 'disabled' || self.optDisabled === 'disabled')) { that.copy = that.selectors[index].text; that.placeholder.find('.ui-selectgroup-copy').text(that.copy); that.element.find('option:selected').removeAttr("selected"); //console.log('render option'); $(that.selectors[index].element).attr('selected', 'selected').trigger("change"); that.position = index; that._toggle(); } }) .bind('mouseover.selectgroup', function() { if (!(self.disabled === 'disabled' || self.optDisabled === 'disabled')) { $(this).addClass('ui-state-hover'); } }) .bind('mouseout.selectmenu', function() { $(this).removeClass('ui-state-hover'); }); if (that.options.classInherit.option) { list.addClass(this.classname); } if (typeof this.selected !== "undefined" && this.selected === 'selected') { list.addClass('ui-state-active'); that.position = index; } if (typeof this.disabled !== "undefined" && this.disabled === 'disabled') { list.addClass('ui-state-disabled'); } if (this.optgroup.length) { var name = that.widgetBaseClass + '-optgroup-' + that.element.find('optgroup').index(this.optgroup); if (that.group.find('li.' + name).length ) { that.group.find('li.' + name + ' ul').append(list); } else { var opt = $('
  • '+ this.optgroup.attr('label') +'
  • '); if (that.options.classInherit.optionGroup) { opt.addClass(this.optgroupClassname); } if (typeof this.optDisabled !== "undefined" && this.optDisabled === 'disabled') { opt.addClass('ui-state-disabled').appendTo(that.group).find('ul').append(list); } else { opt.appendTo(that.group).find('ul').append(list); } } } else { list.appendTo(that.group); } }); }, _position: function() { var options = this.options, local = this.group.find('li').not('.ui-selectgroup-optgroup'), instance = local.get(this.position); $($.ui.selectgroup.group).css({'top': 0, 'left': 0}); $($.ui.selectgroup.group).show() if (this.options.style === 'popup' && !this.options.positioning.offset) { var adjust = '0 -' + ($(instance).outerHeight() + $(instance).offset().top); } $($.ui.selectgroup.group).position({ of: options.positioning.of || this.placeholder, my: options.positioning.my, at: options.positioning.at, offset: options.positioning.offset || adjust, collision: options.positioning.collision }); }, _toggle: function() { if ($.ui.selectgroup.group.past !== null) { if ($.ui.selectgroup.group.past.element !== this.element) { this.focus(); this.close(); } } $.ui.selectgroup.group.past = this; if (!this.isActive) { this.focus(); if (!this.isOpen) { this.open(); } return; } if (!this.isOpen) { this.open(); return; } if (this.isActive) { this.blur(); if (this.isOpen) { this.close(); } return; } if (this.isOpen) { this.close(); return; } }, _traverse: function(value, record) { var local = this.group.find('li').not('.ui-selectgroup-optgroup'), maximum = local.length - 1, position = this.position, instance = null; position = this.position + value; if (position < 0) { position = 0; } if (position > maximum) { position = maximum; } if (position === record) { return; } if (this.selectors[position].disabled === 'disabled' || this.selectors[position].optDisabled === 'disabled') { if (value > 0) { ++value; } else { --value; } this._traverse(value, position); } else { this.position = position; instance = local.get(this.position); this.copy = $(instance).find('a').text(); local.removeClass('ui-state-hover'); $(instance).addClass('ui-state-hover'); this.placeholder.find('.ui-selectgroup-copy').text(this.copy); this.element.find('option:selected').removeAttr('selected'); //console.log('traverse'); $(this.selectors[this.position].element).attr('selected', 'selected').trigger("change"); } $.ui.selectgroup.group.position = value; }, _typeahead: function(character) { //console.log(character.charCodeAt(0)); character_code = character.charCodeAt(0); if ((character_code < 65 ) || (character_code > 90 && character_code < 97) || (character_code > 122 )) return false; var that = this, options = this.options, local = this.group.find('li').not('.ui-selectgroup-optgroup'), instance = null, found = false; character = character.toLowerCase(); this.search[1] += character; window.clearTimeout(this.timer); function focusOption(index) { that.position = index; instance = local.get(that.position); local.removeClass('ui-state-hover'); $(instance).addClass('ui-state-hover'); if (typeof that.selectors[index] != 'undefined') that.placeholder.find('.ui-selectgroup-copy').text(that.selectors[index].text); that.element.find('option:selected').removeAttr('selected'); //console.log('typeahead'); $(that.selectors[index].element).attr('selected', 'selected').trigger("change"); found = true; that.search[3] = index; }; if (this.search[0] === this.search[1][0]) { if (this.search[1].length < 2) { $.each(this.selectors, function(index) { if (!found) { if (that.selectors[index].text.toLowerCase().indexOf(that.search[1][0]) === 0) { if (that.search[0] == that.search[1][0]) { if (that.search[3] < index) { focusOption(index); } } } } }); this.search[0] = this.search[1][0]; } else { $.each(this.selectors, function(index) { if (!found) { if (that.selectors[index].text.toLowerCase().indexOf(that.search[1]) === 0) { if (that.search[0][0] == that.search[1][0]) { if (that.search[3] < index) { focusOption(index); } } } } }); this.search[0] = this.search[1][0]; } } else { $.each(this.selectors, function(index) { if (!found) { if (that.search[1] === that.selectors[index].text.substring(0, that.search[1].length).toLowerCase()) { that.search[2] = index; focusOption(index); } } }); this.search[0] = this.search[1][0]; } if (that.search[4] === that.search[3]) { that.search[3] = that.search[2]; focusOption(that.search[3]); } this.search[4] = this.search[3]; this.timer = window.setTimeout(function() {that.search[1] = '';}, (1000)); }, destroy: function() { var id = this.identifiers[0].split('ui-') if (this.isOpen) { this.close(); } this.placeholder.remove(); $(document).unbind('.selectgroup'); $('label[for="' + this.identifiers[0] + '"]') .attr( 'for', id[1] ) .unbind( '.selectmenu'); this.element.show(); }, enable: function(index, type) { if (this.isOpen) { this.close(); } if (typeof (index) == 'undefined') { this._placeholderEvents(true); } else { if ( type == 'optgroup' ) { this.element.find('optgroup').eq(index).removeAttr('disabled'); } else { this.element.find('option').eq(index).removeAttr('disabled'); } } }, disable: function(index, type) { if (this.isOpen) { this.close(); } if (typeof (index) == 'undefined') { this._placeholderEvents(false); } else { if ( type == 'optgroup' ) { this.element.find('optgroup').eq(index).attr('disabled', 'disabled'); } else { this.element.find('option').eq(index).attr('disabled', 'disabled'); } } }, focus: function() { this._index(); this._renderGroup(); this.isActive = true; }, blur: function() { this.isActive = false; }, change: function() { this._index(); this._renderGroup(); }, refresh: function() { if ($(this.element).find('option:selected').length) { this.copy = this.element.find('option:selected').text(); } else { this.copy = this.element.find('option').first().text(); } this.placeholder.find('.ui-selectgroup-copy').text(this.copy); }, open: function() { if (this.options.style === 'dropdown') { $.ui.selectgroup.group.removeClass('ui-corner-all').addClass('ui-corner-bottom'); this.placeholder.removeClass('ui-corner-all').addClass('ui-state-active ui-corner-top'); } else { $.ui.selectgroup.group.removeClass('ui-corner-bottom').addClass('ui-corner-all'); this.placeholder.addClass('ui-state-active'); } this._position(); this.group.attr('aria-hidden', 'false'); this.isOpen = true; }, close: function() { if ($.ui.selectgroup.group.past !== null) { $.ui.selectgroup.group.past.placeholder.removeClass('ui-state-active'); } if (this.options.style === 'dropdown') { this.placeholder.addClass('ui-corner-all').removeClass('ui-state-active'); } else { this.placeholder.removeClass('ui-state-active'); } $.ui.selectgroup.group.hide(); this.group.attr('aria-hidden', 'true'); this.isOpen = false; } }) $.ui.selectgroup.group = $('
    '); $.ui.selectgroup.group.initialised = false; $.ui.selectgroup.group.past = null; })(jQuery);