diff --git a/ui/jquery.ui.selectmenu.js b/ui/jquery.ui.selectmenu.js
index 773d49f88fc..5eea5841dd7 100644
--- a/ui/jquery.ui.selectmenu.js
+++ b/ui/jquery.ui.selectmenu.js
@@ -1,835 +1,829 @@
- /*
- * jQuery UI Selectmenu version 1.5.0pre
- *
- * Copyright (c) 2009-2010 filament group, http://filamentgroup.com
- * Copyright (c) 2010-2013 Felix Nagel, http://www.felixnagel.com
- * Licensed under the MIT (MIT-LICENSE.txt)
- *
- * https://github.com/fnagel/jquery-ui/wiki/Selectmenu
- */
-
-(function( $ ) {
-
-$.widget("ui.selectmenu", {
- options: {
- appendTo: "body",
- typeAhead: 1000,
- style: 'dropdown',
- positionOptions: null,
- width: null,
- menuWidth: null,
- handleWidth: 26,
- maxHeight: null,
- icons: null,
- format: null,
- escapeHtml: false,
- bgImage: function() {}
- },
-
- _create: function() {
- var self = this, o = this.options;
-
- // make / set unique id
- var selectmenuId = this.element.uniqueId().attr( "id" );
-
- // quick array of button and menu id's
- this.ids = [ selectmenuId, selectmenuId + '-button', selectmenuId + '-menu' ];
-
- // define safe mouseup for future toggling
- this._safemouseup = true;
- this.isOpen = false;
-
- // create menu button wrapper
- this.newelement = $( '', {
- 'class': 'ui-selectmenu ui-widget ui-state-default ui-corner-all',
- 'id' : this.ids[ 1 ],
- 'role': 'button',
- 'href': '#nogo',
- 'tabindex': this.element.attr( 'disabled' ) ? 1 : 0,
- 'aria-haspopup': true,
- 'aria-owns': this.ids[ 2 ]
- });
- this.newelementWrap = $( "" )
- .append( this.newelement )
- .insertAfter( this.element );
-
- // transfer tabindex
- var tabindex = this.element.attr( 'tabindex' );
- if ( tabindex ) {
- this.newelement.attr( 'tabindex', tabindex );
- }
-
- // save reference to select in data for ease in calling methods
- this.newelement.data( 'selectelement', this.element );
-
- // menu icon
- this.selectmenuIcon = $( '' )
- .prependTo( this.newelement );
-
- // append status span to button
- this.newelement.prepend( '' );
-
- // make associated form label trigger focus
- this.element.bind({
- 'click.selectmenu': function( event ) {
- self.newelement.focus();
- event.preventDefault();
- }
- });
-
- // click toggle for menu visibility
- this.newelement
- .bind( 'mousedown.selectmenu', function( event ) {
- self._toggle( event, true );
- // make sure a click won't open/close instantly
- if ( o.style == "popup" ) {
- self._safemouseup = false;
- setTimeout( function() { self._safemouseup = true; }, 300 );
- }
-
- event.preventDefault();
- })
- .bind( 'click.selectmenu', function( event ) {
- event.preventDefault();
- })
- .bind( "keydown.selectmenu", function( event ) {
- var ret = false;
- switch ( event.keyCode ) {
- case $.ui.keyCode.ENTER:
- ret = true;
- break;
- case $.ui.keyCode.SPACE:
- self._toggle( event );
- break;
- case $.ui.keyCode.UP:
- if ( event.altKey ) {
- self.open( event );
- } else {
- self._moveSelection( -1 );
- }
- break;
- case $.ui.keyCode.DOWN:
- if ( event.altKey ) {
- self.open( event );
- } else {
- self._moveSelection( 1 );
- }
- break;
- case $.ui.keyCode.LEFT:
- self._moveSelection( -1 );
- break;
- case $.ui.keyCode.RIGHT:
- self._moveSelection( 1 );
- break;
- case $.ui.keyCode.TAB:
- ret = true;
- break;
- case $.ui.keyCode.PAGE_UP:
- case $.ui.keyCode.HOME:
- self.index( 0 );
- break;
- case $.ui.keyCode.PAGE_DOWN:
- case $.ui.keyCode.END:
- self.index( self._optionLis.length );
- break;
- default:
- ret = true;
- }
- return ret;
- })
- .bind( 'keypress.selectmenu', function( event ) {
- if ( event.which > 0 ) {
- self._typeAhead( event.which, 'mouseup' );
- }
- return true;
- })
- .bind( 'mouseover.selectmenu', function() {
- if ( !o.disabled ) $( this ).addClass( 'ui-state-hover' );
- })
- .bind( 'mouseout.selectmenu', function() {
- if ( !o.disabled ) $( this ).removeClass( 'ui-state-hover' );
- })
- .bind( 'focus.selectmenu', function() {
- if ( !o.disabled ) $( this ).addClass( 'ui-state-focus' );
- })
- .bind( 'blur.selectmenu', function() {
- if (!o.disabled) $( this ).removeClass( 'ui-state-focus' );
- });
-
- // document click closes menu
- $( document ).bind( "mousedown.selectmenu-" + this.ids[ 0 ], function( event ) {
- //check if open and if the clicket targes parent is the same
- if ( self.isOpen && !$( event.target ).closest( "#" + self.ids[ 1 ] ).length ) {
- self.close( event );
- }
- });
-
- // change event on original selectmenu
- this.element
- .bind( "click.selectmenu", function() {
- self._refreshValue();
- })
- // FIXME: newelement can be null under unclear circumstances in IE8
- // TODO not sure if this is still a problem (fnagel 20.03.11)
- .bind( "focus.selectmenu", function() {
- if ( self.newelement ) {
- self.newelement[ 0 ].focus();
- }
- });
-
- // set width when not set via options
- if ( !o.width ) {
- o.width = this.element.outerWidth();
- }
- // set menu button width
- this.newelement.width( o.width );
-
- // hide original selectmenu element
- this.element.hide();
-
- // create menu portion, append to body
- this.list = $( '
', {
- 'class': 'ui-widget ui-widget-content',
- 'aria-hidden': true,
- 'role': 'listbox',
- 'aria-labelledby': this.ids[ 1 ],
- 'id': this.ids[ 2 ]
- });
- this.listWrap = $( "", {
- 'class': 'ui-selectmenu-menu'
- }).append( this.list ).appendTo( o.appendTo );
-
- // transfer menu click to menu button
- this.list
- .bind("keydown.selectmenu", function(event) {
- var ret = false;
- switch ( event.keyCode ) {
- case $.ui.keyCode.UP:
- if ( event.altKey ) {
- self.close( event, true );
- } else {
- self._moveFocus( -1 );
- }
- break;
- case $.ui.keyCode.DOWN:
- if ( event.altKey ) {
- self.close( event, true );
- } else {
- self._moveFocus( 1 );
- }
- break;
- case $.ui.keyCode.LEFT:
- self._moveFocus( -1 );
- break;
- case $.ui.keyCode.RIGHT:
- self._moveFocus( 1 );
- break;
- case $.ui.keyCode.HOME:
- self._moveFocus( ':first' );
- break;
- case $.ui.keyCode.PAGE_UP:
- self._scrollPage( 'up' );
- break;
- case $.ui.keyCode.PAGE_DOWN:
- self._scrollPage( 'down' );
- break;
- case $.ui.keyCode.END:
- self._moveFocus( ':last' );
- break;
- case $.ui.keyCode.ENTER:
- case $.ui.keyCode.SPACE:
- self.close( event, true);
- $( event.target ).parents( 'li:eq(0)' ).trigger( 'mouseup' );
- break;
- case $.ui.keyCode.TAB:
- ret = true;
- self.close( event, true );
- $( event.target ).parents( 'li:eq(0)' ).trigger( 'mouseup' );
- break;
- case $.ui.keyCode.ESCAPE:
- self.close( event, true );
- break;
- default:
- ret = true;
- }
- return ret;
- })
- .bind( 'keypress.selectmenu', function( event ) {
- if ( event.which > 0 ) {
- self._typeAhead( event.which, 'focus' );
- }
- return true;
- })
- // this allows for using the scrollbar in an overflowed list
- .bind( 'mousedown.selectmenu mouseup.selectmenu', function() { return false; });
-
- // needed when window is resized
- $( window ).bind( "resize.selectmenu-" + this.ids[ 0 ], $.proxy( self.close, this ) );
- },
-
- _init: function() {
- var self = this, o = this.options;
-
- // serialize selectmenu element options
- var selectOptionData = [];
- this.element.find( 'option' ).each( function() {
- var opt = $( this );
- selectOptionData.push({
- value: opt.attr( 'value' ),
- text: self._formatText( opt.text(), opt ),
- selected: opt.attr( 'selected' ),
- disabled: opt.attr( 'disabled' ),
- classes: opt.attr( 'class' ),
- typeahead: opt.attr( 'typeahead'),
- parentOptGroup: opt.parent( 'optgroup' ),
- bgImage: o.bgImage.call( opt )
- });
- });
-
- // active state class is only used in popup style
- var activeClass = ( self.options.style == "popup" ) ? " ui-state-active" : "";
-
- // empty list so we can refresh the selectmenu via selectmenu()
- this.list.html( "" );
-
- // write li's
- if ( selectOptionData.length ) {
- for ( var i = 0; i < selectOptionData.length; i++ ) {
- var thisLiAttr = { role : 'presentation' };
- if ( selectOptionData[ i ].disabled ) {
- thisLiAttr[ 'class' ] = 'ui-state-disabled';
- }
- var thisAAttr = {
- html: selectOptionData[ i ].text || ' ',
- href: '#nogo',
- tabindex : -1,
- role: 'option',
- 'aria-selected' : false
- };
- if ( selectOptionData[ i ].disabled ) {
- thisAAttr[ 'aria-disabled' ] = true;
- }
- if ( selectOptionData[ i ].typeahead ) {
- thisAAttr[ 'typeahead' ] = selectOptionData[ i ].typeahead;
- }
- var thisA = $( '', thisAAttr )
- .bind( 'focus.selectmenu', function() {
- $( this ).parent().mouseover();
- })
- .bind( 'blur.selectmenu', function() {
- $( this ).parent().mouseout();
- });
- var thisLi = $( '', thisLiAttr )
- .append( thisA )
- .data( 'index', i )
- .addClass( selectOptionData[ i ].classes )
- .data( 'optionClasses', selectOptionData[ i ].classes || '' )
- .bind( "mouseup.selectmenu", function( event ) {
- if ( self._safemouseup && !self._disabled( event.currentTarget ) && !self._disabled( $( event.currentTarget ).parents( "ul > li.ui-selectmenu-group " ) ) ) {
- self.index( $( this ).data( 'index' ) );
- self.select( event );
- self.close( event, true );
- }
- return false;
- })
- .bind( "click.selectmenu", function() {
- return false;
- })
- .bind('mouseover.selectmenu', function( e ) {
- // no hover if diabled
- if ( !$( this ).hasClass( 'ui-state-disabled' ) && !$( this ).parent( "ul" ).parent( "li" ).hasClass( 'ui-state-disabled' ) ) {
- e.optionValue = self.element[ 0 ].options[ $( this ).data( 'index' ) ].value;
- self._trigger( "hover", e, self._uiHash() );
- self._selectedOptionLi().addClass( activeClass );
- self._focusedOptionLi().removeClass( 'ui-selectmenu-item-focus ui-state-hover' );
- $( this ).removeClass( 'ui-state-active' ).addClass( 'ui-selectmenu-item-focus ui-state-hover' );
- }
- })
- .bind( 'mouseout.selectmenu', function( e ) {
- if ( $( this ).is( self._selectedOptionLi() ) ) {
- $( this ).addClass( activeClass );
- }
- e.optionValue = self.element[ 0 ].options[ $( this ).data( 'index' ) ].value;
- self._trigger( "blur", e, self._uiHash() );
- $( this ).removeClass( 'ui-selectmenu-item-focus ui-state-hover' );
- });
-
- // optgroup or not...
- if ( selectOptionData[ i ].parentOptGroup.length ) {
- var optGroupName = 'ui-selectmenu-group-' + this.element.find( 'optgroup' ).index( selectOptionData[ i ].parentOptGroup );
- if ( this.list.find( 'li.' + optGroupName ).length ) {
- this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi );
- } else {
- $( '' )
- .appendTo( this.list )
- .find( 'ul' )
- .append( thisLi );
- }
- } else {
- thisLi.appendTo( this.list );
- }
-
- // append icon if option is specified
- if ( o.icons ) {
- for ( var j in o.icons ) {
- if (thisLi.is(o.icons[ j ].find)) {
- thisLi
- .data( 'optionClasses', selectOptionData[ i ].classes + ' ui-selectmenu-hasIcon' )
- .addClass( 'ui-selectmenu-hasIcon' );
- var iconClass = o.icons[ j ].icon || "";
- thisLi
- .find( 'a:eq(0)' )
- .prepend( '' );
- if ( selectOptionData[ i ].bgImage ) {
- thisLi.find( 'span' ).css( 'background-image', selectOptionData[ i ].bgImage );
- }
- }
- }
- }
- }
- } else {
- $('' ).appendTo( this.list );
- }
- // we need to set and unset the CSS classes for dropdown and popup style
- var isDropDown = ( o.style == 'dropdown' );
- this.newelement
- .toggleClass( 'ui-selectmenu-dropdown', isDropDown )
- .toggleClass( 'ui-selectmenu-popup', !isDropDown );
- this.list
- .toggleClass( 'ui-selectmenu-menu-dropdown ui-corner-bottom', isDropDown )
- .toggleClass( 'ui-selectmenu-menu-popup ui-corner-all', !isDropDown )
- // add corners to top and bottom menu items
- .find( 'li:first' )
- .toggleClass( 'ui-corner-top', !isDropDown )
- .end().find( 'li:last' )
- .addClass( 'ui-corner-bottom' );
- this.selectmenuIcon
- .toggleClass( 'ui-icon-triangle-1-s', isDropDown )
- .toggleClass( 'ui-icon-triangle-2-n-s', !isDropDown );
-
- // set menu width to either menuWidth option value, width option value, or select width
- if ( o.style == 'dropdown' ) {
- this.list.width( o.menuWidth ? o.menuWidth : o.width );
- } else {
- this.list.width( o.menuWidth ? o.menuWidth : o.width - o.handleWidth );
- }
-
- // Android 2 (Gingerbread) doesn't support internal scrollable divs.
- // Don't limit the menu height for that browser.
- if ( !navigator.userAgent.match( /Android 2/ ) ) {
- var listH = this.listWrap.height();
- var winH = $( window ).height();
- // calculate default max height
- var maxH = o.maxHeight ? Math.min( o.maxHeight, winH ) : winH / 3;
- if ( listH > maxH ) this.list.height( maxH );
- }
-
- // save reference to actionable li's (not group label li's)
- this._optionLis = this.list.find( 'li:not(.ui-selectmenu-group)' );
-
- // transfer disabled state
- if ( this.element.attr( 'disabled' ) ) {
- this.disable();
- } else {
- this.enable();
- }
-
- // update value
- this._refreshValue();
-
- // set selected item so movefocus has intial state
- this._selectedOptionLi().addClass( 'ui-selectmenu-item-focus' );
-
- // needed when selectmenu is placed at the very bottom / top of the page
- clearTimeout( this.refreshTimeout );
- this.refreshTimeout = window.setTimeout( function () {
- self._refreshPosition();
- }, 200 );
- },
-
- destroy: function() {
- this.element.removeData( this.widgetName )
- .removeClass( 'ui-selectmenu-disabled' + ' ' + 'ui-state-disabled' )
- .removeAttr( 'aria-disabled' )
- .unbind( ".selectmenu" );
-
- $( window ).unbind( ".selectmenu-" + this.ids[ 0 ] );
- $( document ).unbind( ".selectmenu-" + this.ids[ 0 ] );
-
- this.newelementWrap.remove();
- this.listWrap.remove();
-
- // unbind click event and show original select
- this.element
- .unbind( ".selectmenu" )
- .show();
-
- // call widget destroy function
- $.Widget.prototype.destroy.apply( this, arguments );
- },
-
- _typeAhead: function( code, eventType ) {
- var self = this,
- c = String.fromCharCode( code ).toLowerCase(),
- matchee = null,
- nextIndex = null;
-
- // Clear any previous timer if present
- if ( self._typeAhead_timer ) {
- window.clearTimeout( self._typeAhead_timer );
- self._typeAhead_timer = undefined;
- }
- // Store the character typed
- self._typeAhead_chars = ( self._typeAhead_chars === undefined ? "" : self._typeAhead_chars ).concat( c );
- // Detect if we are in cyciling mode or direct selection mode
- if ( self._typeAhead_chars.length < 2 || ( self._typeAhead_chars.substr( -2, 1 ) === c && self._typeAhead_cycling ) ) {
- self._typeAhead_cycling = true;
- // Match only the first character and loop
- matchee = c;
- } else {
- // We won't be cycling anymore until the timer expires
- self._typeAhead_cycling = false;
- // Match all the characters typed
- matchee = self._typeAhead_chars;
- }
-
- // We need to determine the currently active index, but it depends on
- // the used context: if it's in the element, we want the actual
- // selected index, if it's in the menu, just the focused one
- var selectedIndex = ( eventType !== 'focus' ? this._selectedOptionLi().data( 'index' ) : this._focusedOptionLi().data( 'index' )) || 0;
- for ( var i = 0; i < this._optionLis.length; i++ ) {
- var thisText = this._optionLis.eq( i ).text().substr( 0, matchee.length ).toLowerCase();
- if ( thisText === matchee ) {
- if ( self._typeAhead_cycling ) {
- if ( nextIndex === null )
- nextIndex = i;
- if ( i > selectedIndex ) {
- nextIndex = i;
- break;
- }
- } else {
- nextIndex = i;
- }
- }
- }
-
- if ( nextIndex !== null ) {
- // Why using trigger() instead of a direct method to select the index? Because we don't what is the exact action to do,
- // it depends if the user is typing on the element or on the popped up menu
- this._optionLis.eq( nextIndex ).find( "a" ).trigger( eventType );
- }
-
- self._typeAhead_timer = window.setTimeout( function() {
- self._typeAhead_timer = undefined;
- self._typeAhead_chars = undefined;
- self._typeAhead_cycling = undefined;
- }, self.options.typeAhead );
- },
-
- // returns some usefull information, called by callbacks only
- _uiHash: function() {
- var index = this.index();
- return {
- index: index,
- option: $( "option", this.element ).get( index ),
- value: this.element[ 0 ].value
- };
- },
-
- open: function( event ) {
- if ( this.newelement.attr( "aria-disabled" ) != 'true' ) {
- var self = this,
- o = this.options,
- selected = this._selectedOptionLi(),
- link = selected.find("a");
-
- self._closeOthers( event );
- self.newelement.addClass( 'ui-state-active' );
- self.list.attr( 'aria-hidden', false );
- self.listWrap.addClass( 'ui-selectmenu-open' );
-
- if ( o.style == "dropdown" ) {
- self.newelement.removeClass( 'ui-corner-all' ).addClass( 'ui-corner-top' );
- } else {
- // center overflow and avoid flickering
- this.list
- .css( "left", -5000 )
- .scrollTop( this.list.scrollTop() + selected.position().top - this.list.outerHeight() / 2 + selected.outerHeight() / 2 )
- .css( "left", "auto" );
- }
-
- self._refreshPosition();
-
- if ( link.length ) {
- link[ 0 ].focus();
- }
-
- self.isOpen = true;
- self._trigger( "open", event, self._uiHash() );
- }
- },
-
- close: function( event, retainFocus ) {
- if ( this.newelement.is( '.ui-state-active') ) {
- this.newelement.removeClass( 'ui-state-active' );
- this.listWrap.removeClass( 'ui-selectmenu-open' );
- this.list.attr( 'aria-hidden', true );
- if ( this.options.style == "dropdown" ) {
- this.newelement.removeClass( 'ui-corner-top' ).addClass( 'ui-corner-all' );
- }
- if ( retainFocus ) {
- this.newelement.focus();
- }
- this.isOpen = false;
- this._trigger( "close", event, this._uiHash() );
- }
- },
-
- change: function( event ) {
- this.element.trigger( "change" );
- this._trigger( "change", event, this._uiHash() );
- },
-
- select: function( event ) {
- if ( this._disabled( event.currentTarget ) ) { return false; }
- this._trigger( "select", event, this._uiHash() );
- },
-
- widget: function() {
- return this.listWrap.add( this.newelementWrap );
- },
-
- _closeOthers: function( event ) {
- $( '.ui-selectmenu.ui-state-active' ).not( this.newelement ).each( function() {
- $( this ).data( 'selectelement' ).selectmenu( 'close', event );
- });
- $( '.ui-selectmenu.ui-state-hover' ).trigger( 'mouseout' );
- },
-
- _toggle: function( event, retainFocus ) {
- if ( this.isOpen ) {
- this.close( event, retainFocus );
- } else {
- this.open( event );
- }
- },
-
- _formatText: function( text, opt ) {
- if ( this.options.format ) {
- text = this.options.format( text, opt );
- } else if ( this.options.escapeHtml ) {
- text = $( '' ).text( text ).html();
- }
- return text;
- },
-
- _selectedIndex: function() {
- return this.element[ 0 ].selectedIndex;
- },
-
- _selectedOptionLi: function() {
- return this._optionLis.eq( this._selectedIndex() );
- },
-
- _focusedOptionLi: function() {
- return this.list.find( '.ui-selectmenu-item-focus' );
- },
-
- _moveSelection: function( amt, recIndex ) {
- // do nothing if disabled
- if ( !this.options.disabled ) {
- var currIndex = parseInt( this._selectedOptionLi().data( 'index' ) || 0, 10 );
- var newIndex = currIndex + amt;
- // do not loop when using up key
- if ( newIndex < 0 ) {
- newIndex = 0;
- }
- if ( newIndex > this._optionLis.size() - 1 ) {
- newIndex = this._optionLis.size() - 1;
- }
- // Occurs when a full loop has been made
- if ( newIndex === recIndex ) {
- return false;
- }
-
- if ( this._optionLis.eq( newIndex ).hasClass( 'ui-state-disabled' ) ) {
- // if option at newIndex is disabled, call _moveFocus, incrementing amt by one
- ( amt > 0 ) ? ++amt : --amt;
- this._moveSelection( amt, newIndex );
- } else {
- this._optionLis.eq( newIndex ).trigger( 'mouseover' ).trigger( 'mouseup' );
- }
- }
- },
-
- _moveFocus: function( amt, recIndex ) {
- if ( !isNaN( amt ) ) {
- var currIndex = parseInt( this._focusedOptionLi().data( 'index' ) || 0, 10 );
- var newIndex = currIndex + amt;
- } else {
- var newIndex = parseInt( this._optionLis.filter( amt ).data( 'index' ), 10 );
- }
-
- if ( newIndex < 0 ) {
- newIndex = 0;
- }
- if ( newIndex > this._optionLis.size() - 1 ) {
- newIndex = this._optionLis.size() - 1;
- }
-
- //Occurs when a full loop has been made
- if ( newIndex === recIndex ) {
- return false;
- }
-
- var activeID = 'ui-selectmenu-item-' + Math.round( Math.random() * 1000 );
-
- this._focusedOptionLi().find( 'a:eq(0)' ).attr( 'id', '' );
-
- if ( this._optionLis.eq( newIndex ).hasClass( 'ui-state-disabled' ) ) {
- // if option at newIndex is disabled, call _moveFocus, incrementing amt by one
- ( amt > 0 ) ? ++amt : --amt;
- this._moveFocus( amt, newIndex );
- } else {
- this._optionLis.eq( newIndex ).find( 'a:eq(0)' ).attr( 'id',activeID ).focus();
- }
-
- this.list.attr( 'aria-activedescendant', activeID );
- },
-
- _scrollPage: function( direction ) {
- var numPerPage = Math.floor( this.list.outerHeight() / this._optionLis.first().outerHeight() );
- numPerPage = ( direction == 'up' ? -numPerPage : numPerPage );
- this._moveFocus( numPerPage );
- },
-
- _setOption: function( key, value ) {
- this.options[ key ] = value;
- if ( key == 'disabled' ) {
- if ( value ) this.close();
- this.element
- .add( this.newelement )
- .add( this.list )[ value ? 'addClass' : 'removeClass' ]( 'ui-selectmenu-disabled ' + 'ui-state-disabled' )
- .attr( "aria-disabled" , value )
- .attr( "tabindex" , value ? 1 : 0 );
- }
- },
-
- disable: function( index, type ){
- // if options is not provided, call the parents disable function
- if ( typeof( index ) == 'undefined' ) {
- this._setOption( 'disabled', true );
- } else {
- this._toggleEnabled( ( type || "option" ), index, false );
- }
- },
-
- enable: function( index, type ) {
- // if options is not provided, call the parents enable function
- if ( typeof( index ) == 'undefined' ) {
- this._setOption( 'disabled', false );
- } else {
- this._toggleEnabled( ( type || "option" ), index, true );
- }
- },
-
- _disabled: function( elem ) {
- return $( elem ).hasClass( 'ui-state-disabled' );
- },
-
- // true = enabled, false = disabled
- _toggleEnabled: function( type, index, flag ) {
- var element = this.element.find( type ).eq( index ),
- elements = ( type === "optgroup" ) ? this.list.find( 'li.ui-selectmenu-group-' + index ) : this._optionLis.eq( index );
-
- if ( elements ) {
- elements
- .toggleClass( 'ui-state-disabled', !flag )
- .attr( "aria-disabled", !flag );
-
- if ( flag ) {
- element.removeAttr( "disabled" );
- } else {
- element.attr( "disabled", "disabled" );
- }
- }
- },
-
- index: function( newIndex ) {
- if ( arguments.length ) {
- if ( !this._disabled( $( this._optionLis[ newIndex ] ) ) && newIndex != this._selectedIndex() ) {
- this.element[ 0 ].selectedIndex = newIndex;
- this._refreshValue();
- this.change();
- } else {
- return false;
- }
- } else {
- return this._selectedIndex();
- }
- },
-
- value: function( newValue ) {
- if ( arguments.length && newValue != this.element[ 0 ].value ) {
- this.element[ 0 ].value = newValue;
- this._refreshValue();
- this.change();
- } else {
- return this.element[ 0 ].value;
- }
- },
-
- _refreshValue: function() {
- var activeClass = ( this.options.style == "popup" ) ? " ui-state-active" : "";
- var activeID = 'ui-selectmenu-item-' + Math.round( Math.random() * 1000 );
- // deselect previous
- this.list
- .find( '.ui-selectmenu-item-selected' )
- .removeClass( "ui-selectmenu-item-selected" + activeClass )
- .find('a')
- .attr( 'aria-selected', 'false' )
- .attr( 'id', '' );
- // select new
- this._selectedOptionLi()
- .addClass( "ui-selectmenu-item-selected" + activeClass )
- .find( 'a' )
- .attr( 'aria-selected', 'true' )
- .attr( 'id', activeID );
-
- // toggle any class brought in from option
- var currentOptionClasses = ( this.newelement.data( 'optionClasses' ) ? this.newelement.data( 'optionClasses' ) : "" );
- var newOptionClasses = ( this._selectedOptionLi().data( 'optionClasses' ) ? this._selectedOptionLi().data( 'optionClasses' ) : "" );
- this.newelement
- .removeClass( currentOptionClasses )
- .data( 'optionClasses', newOptionClasses )
- .addClass( newOptionClasses )
- .find( '.ui-selectmenu-status' )
- .html( this._selectedOptionLi().find( 'a:eq(0)' ).html() );
-
- this.list.attr( 'aria-activedescendant', activeID );
- },
-
- _refreshPosition: function() {
- var o = this.options,
- positionDefault = {
- of: this.newelement,
- my: "left top",
- at: "left bottom",
- collision: 'flip'
- };
-
- // if its a pop-up we need to calculate the position of the selected li
- if ( o.style == "popup" ) {
- var selected = this._selectedOptionLi();
- positionDefault.my = "left top" + ( this.list.offset().top - selected.offset().top - ( this.newelement.outerHeight() + selected.outerHeight() ) / 2 );
- positionDefault.collision = "fit";
- }
-
- this.listWrap
- .removeAttr( 'style' )
- .zIndex( this.element.zIndex() + 2 )
- .position( $.extend( positionDefault, o.positionOptions ) );
- }
-});
-
-})( jQuery );
+/*
+ * jQuery UI Selectmenu version 1.4.0
+ *
+* Copyright (c) 2009-2010 filament group, http://filamentgroup.com
+* Copyright (c) 2010-2013 Felix Nagel, http://www.felixnagel.com
+* Licensed under the MIT (MIT-LICENSE.txt)
+*
+* https://github.com/fnagel/jquery-ui/wiki/Selectmenu
+*/
+
+(function ($) {
+
+ $.widget("ui.selectmenu", {
+ options: {
+ appendTo: "body",
+ typeAhead: 1000,
+ style: 'dropdown',
+ positionOptions: null,
+ width: null,
+ menuWidth: null,
+ handleWidth: 26,
+ maxHeight: null,
+ icons: null,
+ format: null,
+ escapeHtml: false,
+ bgImage: function () { }
+ },
+
+ _create: function () {
+ var self = this, o = this.options;
+
+ // make / set unique id
+ var selectmenuId = this.element.uniqueId().prop("id");
+
+ // quick array of button and menu id's
+ this.ids = [selectmenuId, selectmenuId + '-button', selectmenuId + '-menu'];
+
+ // define safe mouseup for future toggling
+ this._safemouseup = true;
+ this.isOpen = false;
+
+ // create menu button wrapper
+ this.newelement = $('', {
+ 'class': 'ui-selectmenu ui-widget ui-state-default ui-corner-all',
+ 'id': this.ids[1],
+ 'role': 'button',
+ 'href': '#nogo',
+ 'tabindex': this.element.prop('disabled') ? 1 : 0,
+ 'aria-haspopup': true,
+ 'aria-owns': this.ids[2]
+ });
+ this.newelementWrap = $("")
+ .append(this.newelement)
+ .insertAfter(this.element);
+
+ // transfer tabindex
+ var tabindex = this.element.prop('tabindex');
+ if (tabindex) {
+ this.newelement.prop('tabindex', tabindex);
+ }
+
+ // save reference to select in data for ease in calling methods
+ this.newelement.data('selectelement', this.element);
+
+ // menu icon
+ this.selectmenuIcon = $('')
+ .prependTo(this.newelement);
+
+ // append status span to button
+ this.newelement.prepend('');
+
+ // make associated form label trigger focus
+ this.element.bind({
+ 'click.selectmenu': function (event) {
+ self.newelement.focus();
+ event.preventDefault();
+ }
+ });
+
+ // click toggle for menu visibility
+ this.newelement
+ .bind('mousedown.selectmenu', function (event) {
+ self._toggle(event, true);
+ // make sure a click won't open/close instantly
+ if (o.style == "popup") {
+ self._safemouseup = false;
+ setTimeout(function () { self._safemouseup = true; }, 300);
+ }
+
+ event.preventDefault();
+ })
+ .bind('click.selectmenu', function (event) {
+ event.preventDefault();
+ })
+ .bind("keydown.selectmenu", function (event) {
+ var ret = false;
+ switch (event.keyCode) {
+ case $.ui.keyCode.ENTER:
+ ret = true;
+ break;
+ case $.ui.keyCode.SPACE:
+ self._toggle(event);
+ break;
+ case $.ui.keyCode.UP:
+ if (event.altKey) {
+ self.open(event);
+ } else {
+ self._moveSelection(-1);
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ if (event.altKey) {
+ self.open(event);
+ } else {
+ self._moveSelection(1);
+ }
+ break;
+ case $.ui.keyCode.LEFT:
+ self._moveSelection(-1);
+ break;
+ case $.ui.keyCode.RIGHT:
+ self._moveSelection(1);
+ break;
+ case $.ui.keyCode.TAB:
+ ret = true;
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.HOME:
+ self.index(0);
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.END:
+ self.index(self._optionLis.length);
+ break;
+ default:
+ ret = true;
+ }
+ return ret;
+ })
+ .bind('keypress.selectmenu', function (event) {
+ if (event.which > 0) {
+ self._typeAhead(event.which, 'mouseup');
+ }
+ return true;
+ })
+ .bind('mouseover.selectmenu', function () {
+ if (!o.disabled) $(this).addClass('ui-state-hover');
+ })
+ .bind('mouseout.selectmenu', function () {
+ if (!o.disabled) $(this).removeClass('ui-state-hover');
+ })
+ .bind('focus.selectmenu', function () {
+ if (!o.disabled) $(this).addClass('ui-state-focus');
+ })
+ .bind('blur.selectmenu', function () {
+ if (!o.disabled) $(this).removeClass('ui-state-focus');
+ });
+
+ // document click closes menu
+ $(document).bind("mousedown.selectmenu-" + this.ids[0], function (event) {
+ //check if open and if the clicket targes parent is the same
+ if (self.isOpen && !$(event.target).closest("#" + self.ids[1]).length) {
+ self.close(event);
+ }
+ });
+
+ // change event on original selectmenu
+ this.element
+ .bind("click.selectmenu", function () {
+ self._refreshValue();
+ })
+ // FIXME: newelement can be null under unclear circumstances in IE8
+ // TODO not sure if this is still a problem (fnagel 20.03.11)
+ .bind("focus.selectmenu", function () {
+ if (self.newelement) {
+ self.newelement[0].focus();
+ }
+ });
+
+ // set width when not set via options
+ if (!o.width) {
+ o.width = this.element.outerWidth();
+ }
+ // set menu button width
+ this.newelement.width(o.width);
+
+ // hide original selectmenu element
+ this.element.hide();
+
+ // create menu portion, append to body
+ this.list = $('', {
+ 'class': 'ui-widget ui-widget-content',
+ 'aria-hidden': true,
+ 'role': 'listbox',
+ 'aria-labelledby': this.ids[1],
+ 'id': this.ids[2]
+ });
+ this.listWrap = $("", {
+ 'class': 'ui-selectmenu-menu'
+ }).append(this.list).appendTo(o.appendTo);
+
+ // transfer menu click to menu button
+ this.list
+ .bind("keydown.selectmenu", function (event) {
+ var ret = false;
+ switch (event.keyCode) {
+ case $.ui.keyCode.UP:
+ if (event.altKey) {
+ self.close(event, true);
+ } else {
+ self._moveFocus(-1);
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ if (event.altKey) {
+ self.close(event, true);
+ } else {
+ self._moveFocus(1);
+ }
+ break;
+ case $.ui.keyCode.LEFT:
+ self._moveFocus(-1);
+ break;
+ case $.ui.keyCode.RIGHT:
+ self._moveFocus(1);
+ break;
+ case $.ui.keyCode.HOME:
+ self._moveFocus(':first');
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ self._scrollPage('up');
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ self._scrollPage('down');
+ break;
+ case $.ui.keyCode.END:
+ self._moveFocus(':last');
+ break;
+ case $.ui.keyCode.ENTER:
+ case $.ui.keyCode.SPACE:
+ self.close(event, true);
+ $(event.target).parents('li:eq(0)').trigger('mouseup');
+ break;
+ case $.ui.keyCode.TAB:
+ ret = true;
+ self.close(event, true);
+ $(event.target).parents('li:eq(0)').trigger('mouseup');
+ break;
+ case $.ui.keyCode.ESCAPE:
+ self.close(event, true);
+ break;
+ default:
+ ret = true;
+ }
+ return ret;
+ })
+ .bind('keypress.selectmenu', function (event) {
+ if (event.which > 0) {
+ self._typeAhead(event.which, 'focus');
+ }
+ return true;
+ })
+ // this allows for using the scrollbar in an overflowed list
+ .bind('mousedown.selectmenu mouseup.selectmenu', function () { return false; });
+
+ // needed when window is resized
+ $(window).bind("resize.selectmenu-" + this.ids[0], $.proxy(self.close, this));
+ },
+
+ _init: function () {
+ var self = this, o = this.options;
+
+ // serialize selectmenu element options
+ var selectOptionData = [];
+ this.element.find('option').each(function () {
+ var opt = $(this);
+ selectOptionData.push({
+ value: opt.prop('value'),
+ text: self._formatText(opt.html(), opt),
+ selected: opt.prop('selected'),
+ disabled: opt.prop('disabled'),
+ classes: opt.prop('class'),
+ typeahead: opt.prop('typeahead'),
+ parentOptGroup: opt.parent('optgroup'),
+ bgImage: o.bgImage.call(opt)
+ });
+ });
+
+ // active state class is only used in popup style
+ var activeClass = (self.options.style == "popup") ? " ui-state-active" : "";
+
+ // empty list so we can refresh the selectmenu via selectmenu()
+ this.list.html("");
+
+ // write li's
+ if (selectOptionData.length) {
+ for (var i = 0; i < selectOptionData.length; i++) {
+ var thisLiAttr = { role: 'presentation' };
+ if (selectOptionData[i].disabled) {
+ thisLiAttr['class'] = 'ui-state-disabled';
+ }
+ var thisAAttr = {
+ html: selectOptionData[i].text || ' ',
+ href: '#nogo',
+ tabindex: -1,
+ role: 'option',
+ 'aria-selected': false
+ };
+ if (selectOptionData[i].disabled) {
+ thisAAttr['aria-disabled'] = true;
+ }
+ if (selectOptionData[i].typeahead) {
+ thisAAttr['typeahead'] = selectOptionData[i].typeahead;
+ }
+ var thisA = $('', thisAAttr)
+ .bind('focus.selectmenu', function () {
+ $(this).parent().mouseover();
+ })
+ .bind('blur.selectmenu', function () {
+ $(this).parent().mouseout();
+ });
+ var thisLi = $('', thisLiAttr)
+ .append(thisA)
+ .data('index', i)
+ .addClass(selectOptionData[i].classes)
+ .data('optionClasses', selectOptionData[i].classes || '')
+ .bind("mouseup.selectmenu", function (event) {
+ if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($(event.currentTarget).parents("ul > li.ui-selectmenu-group "))) {
+ self.index($(this).data('index'));
+ self.select(event);
+ self.close(event, true);
+ }
+ return false;
+ })
+ .bind("click.selectmenu", function () {
+ return false;
+ })
+ .bind('mouseover.selectmenu', function (e) {
+ // no hover if diabled
+ if (!$(this).hasClass('ui-state-disabled') && !$(this).parent("ul").parent("li").hasClass('ui-state-disabled')) {
+ e.optionValue = self.element[0].options[$(this).data('index')].value;
+ self._trigger("hover", e, self._uiHash());
+ self._selectedOptionLi().addClass(activeClass);
+ self._focusedOptionLi().removeClass('ui-selectmenu-item-focus ui-state-hover');
+ $(this).removeClass('ui-state-active').addClass('ui-selectmenu-item-focus ui-state-hover');
+ }
+ })
+ .bind('mouseout.selectmenu', function (e) {
+ if ($(this).is(self._selectedOptionLi())) {
+ $(this).addClass(activeClass);
+ }
+ e.optionValue = self.element[0].options[$(this).data('index')].value;
+ self._trigger("blur", e, self._uiHash());
+ $(this).removeClass('ui-selectmenu-item-focus ui-state-hover');
+ });
+
+ // optgroup or not...
+ if (selectOptionData[i].parentOptGroup.length) {
+ var optGroupName = 'ui-selectmenu-group-' + this.element.find('optgroup').index(selectOptionData[i].parentOptGroup);
+ if (this.list.find('li.' + optGroupName).length) {
+ this.list.find('li.' + optGroupName + ':last ul').append(thisLi);
+ } else {
+ $('')
+ .appendTo(this.list)
+ .find('ul')
+ .append(thisLi);
+ }
+ } else {
+ thisLi.appendTo(this.list);
+ }
+
+ // append icon if option is specified
+ if (o.icons) {
+ for (var j in o.icons) {
+ if (thisLi.is(o.icons[j].find)) {
+ thisLi
+ .data('optionClasses', selectOptionData[i].classes + ' ui-selectmenu-hasIcon')
+ .addClass('ui-selectmenu-hasIcon');
+ var iconClass = o.icons[j].icon || "";
+ thisLi
+ .find('a:eq(0)')
+ .prepend('');
+ if (selectOptionData[i].bgImage) {
+ thisLi.find('span').css('background-image', selectOptionData[i].bgImage);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $(' ').appendTo(this.list);
+ }
+ // we need to set and unset the CSS classes for dropdown and popup style
+ var isDropDown = (o.style == 'dropdown');
+ this.newelement
+ .toggleClass('ui-selectmenu-dropdown', isDropDown)
+ .toggleClass('ui-selectmenu-popup', !isDropDown);
+ this.list
+ .toggleClass('ui-selectmenu-menu-dropdown ui-corner-bottom', isDropDown)
+ .toggleClass('ui-selectmenu-menu-popup ui-corner-all', !isDropDown)
+ // add corners to top and bottom menu items
+ .find('li:first')
+ .toggleClass('ui-corner-top', !isDropDown)
+ .end().find('li:last')
+ .addClass('ui-corner-bottom');
+ this.selectmenuIcon
+ .toggleClass('ui-icon-triangle-1-s', isDropDown)
+ .toggleClass('ui-icon-triangle-2-n-s', !isDropDown);
+
+ // set menu width to either menuWidth option value, width option value, or select width
+ if (o.style == 'dropdown') {
+ this.list.width(o.menuWidth ? o.menuWidth : o.width);
+ } else {
+ this.list.width(o.menuWidth ? o.menuWidth : o.width - o.handleWidth);
+ }
+
+ // reset height to auto
+ this.list.css('height', 'auto');
+ var listH = this.listWrap.height();
+ var winH = $(window).height();
+ // calculate default max height
+ var maxH = o.maxHeight ? Math.min(o.maxHeight, winH) : winH / 3;
+ if (listH > maxH) this.list.height(maxH);
+
+ // save reference to actionable li's (not group label li's)
+ this._optionLis = this.list.find('li:not(.ui-selectmenu-group)');
+
+ // transfer disabled state
+ if (this.element.prop('disabled')) {
+ this.disable();
+ } else {
+ this.enable();
+ }
+
+ // update value
+ this._refreshValue();
+
+ // set selected item so movefocus has intial state
+ this._selectedOptionLi().addClass('ui-selectmenu-item-focus');
+
+ // needed when selectmenu is placed at the very bottom / top of the page
+ clearTimeout(this.refreshTimeout);
+ this.refreshTimeout = window.setTimeout(function () {
+ self._refreshPosition();
+ }, 200);
+ },
+
+ destroy: function () {
+ this.element.removeData(this.widgetName)
+ .removeClass('ui-selectmenu-disabled' + ' ' + 'ui-state-disabled')
+ .removeAttr('aria-disabled')
+ .unbind(".selectmenu");
+
+ $(window).unbind(".selectmenu-" + this.ids[0]);
+ $(document).unbind(".selectmenu-" + this.ids[0]);
+
+ this.newelementWrap.remove();
+ this.listWrap.remove();
+
+ // unbind click event and show original select
+ this.element
+ .unbind(".selectmenu")
+ .show();
+
+ // call widget destroy function
+ $.Widget.prototype.destroy.apply(this, arguments);
+ },
+
+ _typeAhead: function (code, eventType) {
+ var self = this,
+ c = String.fromCharCode(code).toLowerCase(),
+ matchee = null,
+ nextIndex = null;
+
+ // Clear any previous timer if present
+ if (self._typeAhead_timer) {
+ window.clearTimeout(self._typeAhead_timer);
+ self._typeAhead_timer = undefined;
+ }
+ // Store the character typed
+ self._typeAhead_chars = (self._typeAhead_chars === undefined ? "" : self._typeAhead_chars).concat(c);
+ // Detect if we are in cyciling mode or direct selection mode
+ if (self._typeAhead_chars.length < 2 || (self._typeAhead_chars.substr(-2, 1) === c && self._typeAhead_cycling)) {
+ self._typeAhead_cycling = true;
+ // Match only the first character and loop
+ matchee = c;
+ } else {
+ // We won't be cycling anymore until the timer expires
+ self._typeAhead_cycling = false;
+ // Match all the characters typed
+ matchee = self._typeAhead_chars;
+ }
+
+ // We need to determine the currently active index, but it depends on
+ // the used context: if it's in the element, we want the actual
+ // selected index, if it's in the menu, just the focused one
+ var selectedIndex = (eventType !== 'focus' ? this._selectedOptionLi().data('index') : this._focusedOptionLi().data('index')) || 0;
+ for (var i = 0; i < this._optionLis.length; i++) {
+ var thisText = this._optionLis.eq(i).text().substr(0, matchee.length).toLowerCase();
+ if (thisText === matchee) {
+ if (self._typeAhead_cycling) {
+ if (nextIndex === null)
+ nextIndex = i;
+ if (i > selectedIndex) {
+ nextIndex = i;
+ break;
+ }
+ } else {
+ nextIndex = i;
+ }
+ }
+ }
+
+ if (nextIndex !== null) {
+ // Why using trigger() instead of a direct method to select the index? Because we don't what is the exact action to do,
+ // it depends if the user is typing on the element or on the popped up menu
+ this._optionLis.eq(nextIndex).find("a").trigger(eventType);
+ }
+
+ self._typeAhead_timer = window.setTimeout(function () {
+ self._typeAhead_timer = undefined;
+ self._typeAhead_chars = undefined;
+ self._typeAhead_cycling = undefined;
+ }, self.options.typeAhead);
+ },
+
+ // returns some usefull information, called by callbacks only
+ _uiHash: function () {
+ var index = this.index();
+ return {
+ index: index,
+ option: $("option", this.element).get(index),
+ value: this.element[0].value
+ };
+ },
+
+ open: function (event) {
+ if (!this.newelement.prop("aria-disabled")) {
+ var self = this,
+ o = this.options,
+ selected = this._selectedOptionLi(),
+ link = selected.find("a");
+
+ self._closeOthers(event);
+ self.newelement.addClass('ui-state-active');
+ self.list.prop('aria-hidden', false);
+ self.listWrap.addClass('ui-selectmenu-open');
+
+ if (o.style == "dropdown") {
+ self.newelement.removeClass('ui-corner-all').addClass('ui-corner-top');
+ } else {
+ // center overflow and avoid flickering
+ this.list
+ .css("left", -5000)
+ .scrollTop(this.list.scrollTop() + selected.position().top - this.list.outerHeight() / 2 + selected.outerHeight() / 2)
+ .css("left", "auto");
+ }
+
+ self._refreshPosition();
+
+ if (link.length) {
+ link[0].focus();
+ }
+
+ self.isOpen = true;
+ self._trigger("open", event, self._uiHash());
+ }
+ },
+
+ close: function (event, retainFocus) {
+ if (this.newelement.is('.ui-state-active')) {
+ this.newelement.removeClass('ui-state-active');
+ this.listWrap.removeClass('ui-selectmenu-open');
+ this.list.prop('aria-hidden', true);
+ if (this.options.style == "dropdown") {
+ this.newelement.removeClass('ui-corner-top').addClass('ui-corner-all');
+ }
+ if (retainFocus) {
+ this.newelement.focus();
+ }
+ this.isOpen = false;
+ this._trigger("close", event, this._uiHash());
+ }
+ },
+
+ change: function (event) {
+ this.element.trigger("change");
+ this._trigger("change", event, this._uiHash());
+ },
+
+ select: function (event) {
+ if (this._disabled(event.currentTarget)) { return false; }
+ this._trigger("select", event, this._uiHash());
+ },
+
+ widget: function () {
+ return this.listWrap.add(this.newelementWrap);
+ },
+
+ _closeOthers: function (event) {
+ $('.ui-selectmenu.ui-state-active').not(this.newelement).each(function () {
+ $(this).data('selectelement').selectmenu('close', event);
+ });
+ $('.ui-selectmenu.ui-state-hover').trigger('mouseout');
+ },
+
+ _toggle: function (event, retainFocus) {
+ if (this.isOpen) {
+ this.close(event, retainFocus);
+ } else {
+ this.open(event);
+ }
+ },
+
+ _formatText: function (text, opt) {
+ if (this.options.format) {
+ text = this.options.format(text, opt);
+ } else if (this.options.escapeHtml) {
+ text = $('').text(text).html();
+ }
+ return text;
+ },
+
+ _selectedIndex: function () {
+ return this.element[0].selectedIndex;
+ },
+
+ _selectedOptionLi: function () {
+ return this._optionLis.eq(this._selectedIndex());
+ },
+
+ _focusedOptionLi: function () {
+ return this.list.find('.ui-selectmenu-item-focus');
+ },
+
+ _moveSelection: function (amt, recIndex) {
+ // do nothing if disabled
+ if (!this.options.disabled) {
+ var currIndex = parseInt(this._selectedOptionLi().data('index') || 0, 10);
+ var newIndex = currIndex + amt;
+ // do not loop when using up key
+ if (newIndex < 0) {
+ newIndex = 0;
+ }
+ if (newIndex > this._optionLis.size() - 1) {
+ newIndex = this._optionLis.size() - 1;
+ }
+ // Occurs when a full loop has been made
+ if (newIndex === recIndex) {
+ return false;
+ }
+
+ if (this._optionLis.eq(newIndex).hasClass('ui-state-disabled')) {
+ // if option at newIndex is disabled, call _moveFocus, incrementing amt by one
+ (amt > 0) ? ++amt : --amt;
+ this._moveSelection(amt, newIndex);
+ } else {
+ this._optionLis.eq(newIndex).trigger('mouseover').trigger('mouseup');
+ }
+ }
+ },
+
+ _moveFocus: function (amt, recIndex) {
+ if (!isNaN(amt)) {
+ var currIndex = parseInt(this._focusedOptionLi().data('index') || 0, 10);
+ var newIndex = currIndex + amt;
+ } else {
+ var newIndex = parseInt(this._optionLis.filter(amt).data('index'), 10);
+ }
+
+ if (newIndex < 0) {
+ newIndex = 0;
+ }
+ if (newIndex > this._optionLis.size() - 1) {
+ newIndex = this._optionLis.size() - 1;
+ }
+
+ //Occurs when a full loop has been made
+ if (newIndex === recIndex) {
+ return false;
+ }
+
+ var activeID = 'ui-selectmenu-item-' + Math.round(Math.random() * 1000);
+
+ this._focusedOptionLi().find('a:eq(0)').prop('id', '');
+
+ if (this._optionLis.eq(newIndex).hasClass('ui-state-disabled')) {
+ // if option at newIndex is disabled, call _moveFocus, incrementing amt by one
+ (amt > 0) ? ++amt : --amt;
+ this._moveFocus(amt, newIndex);
+ } else {
+ this._optionLis.eq(newIndex).find('a:eq(0)').prop('id', activeID).focus();
+ }
+
+ this.list.prop('aria-activedescendant', activeID);
+ },
+
+ _scrollPage: function (direction) {
+ var numPerPage = Math.floor(this.list.outerHeight() / this._optionLis.first().outerHeight());
+ numPerPage = (direction == 'up' ? -numPerPage : numPerPage);
+ this._moveFocus(numPerPage);
+ },
+
+ _setOption: function (key, value) {
+ this.options[key] = value;
+ if (key == 'disabled') {
+ if (value) this.close();
+ this.element
+ .add(this.newelement)
+ .add(this.list)[value ? 'addClass' : 'removeClass']('ui-selectmenu-disabled ' + 'ui-state-disabled')
+ .prop("aria-disabled", value)
+ .prop("tabindex", value ? 1 : 0);
+ }
+ },
+
+ disable: function (index, type) {
+ // if options is not provided, call the parents disable function
+ if (typeof (index) == 'undefined') {
+ this._setOption('disabled', true);
+ } else {
+ this._toggleEnabled((type || "option"), index, false);
+ }
+ },
+
+ enable: function (index, type) {
+ // if options is not provided, call the parents enable function
+ if (typeof (index) == 'undefined') {
+ this._setOption('disabled', false);
+ } else {
+ this._toggleEnabled((type || "option"), index, true);
+ }
+ },
+
+ _disabled: function (elem) {
+ return $(elem).hasClass('ui-state-disabled');
+ },
+
+ // true = enabled, false = disabled
+ _toggleEnabled: function (type, index, flag) {
+ var element = this.element.find(type).eq(index),
+ elements = (type === "optgroup") ? this.list.find('li.ui-selectmenu-group-' + index) : this._optionLis.eq(index);
+
+ if (elements) {
+ elements
+ .toggleClass('ui-state-disabled', !flag)
+ .prop("aria-disabled", !flag);
+
+ element.prop("disabled", !flag);
+ }
+ },
+
+ index: function (newIndex) {
+ if (arguments.length) {
+ if (!this._disabled($(this._optionLis[newIndex])) && newIndex != this._selectedIndex()) {
+ this.element[0].selectedIndex = newIndex;
+ this._refreshValue();
+ this.change();
+ } else {
+ return false;
+ }
+ } else {
+ return this._selectedIndex();
+ }
+ },
+
+ value: function (newValue) {
+ if (arguments.length && newValue != this.element[0].value) {
+ this.element[0].value = newValue;
+ this._refreshValue();
+ this.change();
+ } else {
+ return this.element[0].value;
+ }
+ },
+
+ _refreshValue: function () {
+ var activeClass = (this.options.style == "popup") ? " ui-state-active" : "";
+ var activeID = 'ui-selectmenu-item-' + Math.round(Math.random() * 1000);
+ // deselect previous
+ this.list
+ .find('.ui-selectmenu-item-selected')
+ .removeClass("ui-selectmenu-item-selected" + activeClass)
+ .find('a')
+ .prop('aria-selected', false)
+ .prop('id', '');
+ // select new
+ this._selectedOptionLi()
+ .addClass("ui-selectmenu-item-selected" + activeClass)
+ .find('a')
+ .prop('aria-selected', true)
+ .prop('id', activeID);
+
+ // toggle any class brought in from option
+ var currentOptionClasses = (this.newelement.data('optionClasses') ? this.newelement.data('optionClasses') : "");
+ var newOptionClasses = (this._selectedOptionLi().data('optionClasses') ? this._selectedOptionLi().data('optionClasses') : "");
+ this.newelement
+ .removeClass(currentOptionClasses)
+ .data('optionClasses', newOptionClasses)
+ .addClass(newOptionClasses)
+ .find('.ui-selectmenu-status')
+ .html(this._selectedOptionLi().find('a:eq(0)').html());
+
+ this.list.prop('aria-activedescendant', activeID);
+ },
+
+ _refreshPosition: function () {
+ var o = this.options,
+ positionDefault = {
+ of: this.newelement,
+ my: "left top",
+ at: "left bottom",
+ collision: 'flip'
+ };
+
+ // if its a pop-up we need to calculate the position of the selected li
+ if (o.style == "popup") {
+ var selected = this._selectedOptionLi();
+ positionDefault.my = "left top" + (this.list.offset().top - selected.offset().top - (this.newelement.outerHeight() + selected.outerHeight()) / 2);
+ positionDefault.collision = "fit";
+ }
+
+ this.listWrap
+ .removeAttr('style')
+ .zIndex(this.element.zIndex() + 2)
+ .position($.extend(positionDefault, o.positionOptions));
+ }
+ });
+
+})(jQuery);
\ No newline at end of file