2012-05-16 17:26:31 +00:00
/ * !
2011-09-01 22:21:09 +00:00
* jQuery UI Selectmenu @ VERSION
2012-07-16 18:36:01 +00:00
* http : //jqueryui.com
2011-09-01 22:21:09 +00:00
*
2014-12-21 18:27:43 +00:00
* Copyright jQuery Foundation and other contributors
2012-08-11 17:57:17 +00:00
* Released under the MIT license .
2011-09-01 22:21:09 +00:00
* http : //jquery.org/license
* /
2014-10-30 19:55:08 +00:00
//>>label: Selectmenu
//>>group: Widgets
//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
//>>docs: http://api.jqueryui.com/selectmenu/
//>>demos: http://jqueryui.com/selectmenu/
2015-10-21 23:08:44 +00:00
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
//>>css.theme: ../../themes/base/theme.css
2014-10-30 19:55:08 +00:00
2015-03-14 11:28:17 +00:00
( function ( factory ) {
2014-02-21 19:56:13 +00:00
if ( typeof define === "function" && define . amd ) {
// AMD. Register as an anonymous module.
2015-03-14 11:28:17 +00:00
define ( [
2014-02-21 19:56:13 +00:00
"jquery" ,
2015-07-15 02:06:31 +00:00
"./menu" ,
"../escape-selector" ,
2015-10-26 17:13:42 +00:00
"../form-reset-mixin" ,
2015-07-15 02:06:31 +00:00
"../keycode" ,
"../labels" ,
"../position" ,
"../unique-id" ,
"../version" ,
"../widget"
2015-07-15 22:14:26 +00:00
] , factory ) ;
2014-02-21 19:56:13 +00:00
} else {
// Browser globals
factory ( jQuery ) ;
}
2015-03-14 11:28:17 +00:00
} ( function ( $ ) {
2011-09-01 22:21:09 +00:00
2015-10-26 17:13:42 +00:00
return $ . widget ( "ui.selectmenu" , [ $ . ui . formResetMixin , {
2011-09-01 22:21:09 +00:00
version : "@VERSION" ,
defaultElement : "<select>" ,
options : {
2012-12-15 01:21:51 +00:00
appendTo : null ,
2014-12-03 16:26:46 +00:00
classes : {
"ui-selectmenu-button-open" : "ui-corner-top" ,
"ui-selectmenu-button-closed" : "ui-corner-all"
} ,
2014-04-21 14:32:49 +00:00
disabled : null ,
2012-12-19 23:10:06 +00:00
icons : {
button : "ui-icon-triangle-1-s"
} ,
2011-09-01 22:21:09 +00:00
position : {
my : "left top" ,
at : "left bottom" ,
collision : "none"
} ,
2015-03-04 19:27:10 +00:00
width : false ,
2012-11-29 19:23:30 +00:00
2015-08-21 04:06:35 +00:00
// Callbacks
2012-11-29 18:43:36 +00:00
change : null ,
2011-09-30 19:16:55 +00:00
close : null ,
2012-11-29 18:43:36 +00:00
focus : null ,
open : null ,
select : null
2011-09-01 22:21:09 +00:00
} ,
_create : function ( ) {
2012-11-12 22:06:05 +00:00
var selectmenuId = this . element . uniqueId ( ) . attr ( "id" ) ;
2013-04-29 20:19:53 +00:00
this . ids = {
element : selectmenuId ,
button : selectmenuId + "-button" ,
menu : selectmenuId + "-menu"
2013-04-29 19:54:36 +00:00
} ;
2011-11-18 16:14:38 +00:00
2011-10-11 23:38:30 +00:00
this . _drawButton ( ) ;
this . _drawMenu ( ) ;
2015-10-26 17:13:42 +00:00
this . _bindFormResetHandler ( ) ;
2012-01-27 22:11:31 +00:00
2015-01-12 16:23:08 +00:00
this . _rendered = false ;
this . menuItems = $ ( ) ;
2011-09-30 19:16:55 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-10-11 23:38:30 +00:00
_drawButton : function ( ) {
2014-08-22 20:40:09 +00:00
var icon , space ,
2014-12-03 16:26:46 +00:00
that = this ,
2014-07-28 17:09:41 +00:00
item = this . _parseOption (
this . element . find ( "option:selected" ) ,
this . element [ 0 ] . selectedIndex
) ;
2012-10-15 21:58:31 +00:00
2013-09-16 18:45:48 +00:00
// Associate existing label with the new button
2015-04-27 06:30:01 +00:00
this . labels = this . element . labels ( ) . attr ( "for" , this . ids . button ) ;
2015-04-27 03:38:21 +00:00
this . _on ( this . labels , {
2013-04-29 19:59:55 +00:00
click : function ( event ) {
2012-10-25 21:57:36 +00:00
this . button . focus ( ) ;
event . preventDefault ( ) ;
}
2015-03-14 11:28:17 +00:00
} ) ;
2011-11-18 16:14:38 +00:00
2013-09-16 18:45:48 +00:00
// Hide original select element
2011-10-11 23:24:04 +00:00
this . element . hide ( ) ;
2011-11-18 16:14:38 +00:00
2013-04-29 20:01:51 +00:00
// Create button
2013-03-07 22:23:10 +00:00
this . button = $ ( "<span>" , {
2014-10-22 16:27:37 +00:00
tabindex : this . options . disabled ? - 1 : 0 ,
2012-02-23 22:25:03 +00:00
id : this . ids . button ,
2012-11-12 22:06:05 +00:00
role : "combobox" ,
2013-04-29 20:07:41 +00:00
"aria-expanded" : "false" ,
2012-11-12 22:06:05 +00:00
"aria-autocomplete" : "list" ,
"aria-owns" : this . ids . menu ,
2014-07-31 10:35:42 +00:00
"aria-haspopup" : "true" ,
title : this . element . attr ( "title" )
2015-03-14 11:28:17 +00:00
} )
2014-04-08 15:17:32 +00:00
. insertAfter ( this . element ) ;
2012-02-23 22:32:17 +00:00
2014-12-03 16:26:46 +00:00
this . _addClass ( this . button , "ui-selectmenu-button ui-selectmenu-button-closed" ,
2014-08-22 20:40:09 +00:00
"ui-button ui-widget" ) ;
2014-12-03 16:26:46 +00:00
icon = $ ( "<span>" ) . prependTo ( this . button ) ;
2014-08-22 20:40:09 +00:00
space = $ ( "<span> </span>" ) ;
this . _addClass ( space , "ui-selectmenu-icon-space" ) ;
2014-12-03 16:26:46 +00:00
this . _addClass ( icon , null , "ui-icon " + this . options . icons . button ) ;
2014-08-22 20:40:09 +00:00
icon . after ( space ) ;
2012-02-23 22:32:17 +00:00
2014-07-28 17:09:41 +00:00
this . buttonItem = this . _renderButtonItem ( item )
2014-04-08 15:17:32 +00:00
. appendTo ( this . button ) ;
2013-09-29 13:33:14 +00:00
2015-03-04 19:27:10 +00:00
if ( this . options . width !== false ) {
this . _resizeButton ( ) ;
}
2011-11-18 16:14:38 +00:00
2012-11-29 18:54:10 +00:00
this . _on ( this . button , this . _buttonEvents ) ;
2013-10-29 20:49:17 +00:00
this . button . one ( "focusin" , function ( ) {
2014-04-08 15:17:32 +00:00
// Delay rendering the menu items until the button receives focus.
// The menu may have already been rendered via a programmatic open.
2015-01-12 16:23:08 +00:00
if ( ! that . _rendered ) {
2014-04-08 15:17:32 +00:00
that . _refreshMenu ( ) ;
}
2015-03-14 11:28:17 +00:00
} ) ;
2011-09-01 22:21:09 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-10-11 23:38:30 +00:00
_drawMenu : function ( ) {
2013-05-30 19:25:36 +00:00
var that = this ;
2011-11-18 16:14:38 +00:00
2013-09-16 18:45:48 +00:00
// Create menu
2012-11-29 19:10:05 +00:00
this . menu = $ ( "<ul>" , {
2013-04-29 20:07:41 +00:00
"aria-hidden" : "true" ,
2012-11-12 22:06:05 +00:00
"aria-labelledby" : this . ids . button ,
2011-10-12 20:06:18 +00:00
id : this . ids . menu
2015-03-14 11:28:17 +00:00
} ) ;
2011-11-18 16:14:38 +00:00
2013-04-29 20:01:51 +00:00
// Wrap menu
2014-12-03 16:26:46 +00:00
this . menuWrap = $ ( "<div>" ) . append ( this . menu ) ;
this . _addClass ( this . menuWrap , "ui-selectmenu-menu" , "ui-front" ) ;
this . menuWrap . appendTo ( this . _appendTo ( ) ) ;
2011-11-18 16:14:38 +00:00
2013-09-16 18:45:48 +00:00
// Initialize menu widget
2014-04-08 15:17:32 +00:00
this . menuInstance = this . menu
2015-03-14 11:28:17 +00:00
. menu ( {
2014-12-03 16:26:46 +00:00
classes : {
"ui-menu" : "ui-corner-bottom"
} ,
2014-04-08 15:17:32 +00:00
role : "listbox" ,
select : function ( event , ui ) {
event . preventDefault ( ) ;
2014-10-09 14:25:26 +00:00
2015-08-21 04:06:35 +00:00
// Support: IE8
2014-10-09 14:25:26 +00:00
// If the item was selected via a click, the text selection
// will be destroyed in IE
that . _setSelection ( ) ;
2014-04-08 15:17:32 +00:00
that . _select ( ui . item . data ( "ui-selectmenu-item" ) , event ) ;
} ,
focus : function ( event , ui ) {
var item = ui . item . data ( "ui-selectmenu-item" ) ;
// Prevent inital focus from firing and check if its a newly focused item
if ( that . focusIndex != null && item . index !== that . focusIndex ) {
that . _trigger ( "focus" , event , { item : item } ) ;
if ( ! that . isOpen ) {
that . _select ( item , event ) ;
}
2012-01-27 21:44:43 +00:00
}
2014-04-08 15:17:32 +00:00
that . focusIndex = item . index ;
2012-10-15 21:58:31 +00:00
2014-04-08 15:17:32 +00:00
that . button . attr ( "aria-activedescendant" ,
that . menuItems . eq ( item . index ) . attr ( "id" ) ) ;
}
2015-03-14 11:28:17 +00:00
} )
2014-04-08 15:17:32 +00:00
. menu ( "instance" ) ;
2012-01-27 22:11:31 +00:00
2014-04-08 15:17:32 +00:00
// Don't close the menu on mouseleave
2013-05-30 19:04:45 +00:00
this . menuInstance . _off ( this . menu , "mouseleave" ) ;
2013-08-02 01:41:58 +00:00
// Cancel the menu's collapseAll on document click
this . menuInstance . _closeOnDocumentClick = function ( ) {
return false ;
} ;
2013-12-18 18:30:48 +00:00
2014-04-08 15:17:32 +00:00
// Selects often contain empty items, but never contain dividers
2013-12-18 18:30:48 +00:00
this . menuInstance . _isDivider = function ( ) {
return false ;
2013-12-18 19:11:29 +00:00
} ;
2011-09-30 19:16:55 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-09-30 19:16:55 +00:00
refresh : function ( ) {
2013-09-25 23:10:16 +00:00
this . _refreshMenu ( ) ;
2014-07-28 17:09:41 +00:00
this . buttonItem . replaceWith (
this . buttonItem = this . _renderButtonItem (
2015-01-12 16:23:08 +00:00
// Fall back to an empty object in case there are no options
this . _getSelectedItem ( ) . data ( "ui-selectmenu-item" ) || { }
2014-07-28 17:09:41 +00:00
)
) ;
2015-03-04 19:27:10 +00:00
if ( this . options . width === null ) {
2014-07-29 14:40:02 +00:00
this . _resizeButton ( ) ;
}
2013-09-25 23:10:16 +00:00
} ,
_refreshMenu : function ( ) {
2012-05-24 16:30:39 +00:00
var item ,
2012-11-12 22:06:05 +00:00
options = this . element . find ( "option" ) ;
2013-04-29 21:05:07 +00:00
2015-01-12 16:23:08 +00:00
this . menu . empty ( ) ;
2013-04-29 21:05:07 +00:00
2014-04-08 15:17:32 +00:00
this . _parseOptions ( options ) ;
2013-04-29 20:23:11 +00:00
this . _renderMenu ( this . menu , this . items ) ;
2012-01-27 22:11:31 +00:00
2013-09-16 18:45:48 +00:00
this . menuInstance . refresh ( ) ;
2014-09-26 21:34:22 +00:00
this . menuItems = this . menu . find ( "li" )
. not ( ".ui-selectmenu-optgroup" )
. find ( ".ui-menu-item-wrapper" ) ;
2011-11-18 16:14:38 +00:00
2015-01-12 16:23:08 +00:00
this . _rendered = true ;
if ( ! options . length ) {
return ;
}
2013-04-29 20:23:11 +00:00
item = this . _getSelectedItem ( ) ;
2013-04-29 20:19:53 +00:00
2013-09-16 18:45:48 +00:00
// Update the menu to have the correct item focused
this . menuInstance . focus ( null , item ) ;
2013-04-29 20:23:11 +00:00
this . _setAria ( item . data ( "ui-selectmenu-item" ) ) ;
2013-08-31 09:50:53 +00:00
2013-04-29 20:23:11 +00:00
// Set disabled state
2013-09-16 18:45:48 +00:00
this . _setOption ( "disabled" , this . element . prop ( "disabled" ) ) ;
2011-11-18 16:14:38 +00:00
} ,
open : function ( event ) {
2012-11-29 19:23:30 +00:00
if ( this . options . disabled ) {
return ;
}
2013-08-02 01:41:58 +00:00
2013-09-16 18:45:48 +00:00
// If this is the first time the menu is being opened, render the items
2015-01-12 16:23:08 +00:00
if ( ! this . _rendered ) {
2013-09-25 23:10:16 +00:00
this . _refreshMenu ( ) ;
2013-08-02 01:41:58 +00:00
} else {
2014-04-08 15:19:26 +00:00
// Menu clears focus on close, reset focus to selected item
2014-12-03 16:26:46 +00:00
this . _removeClass ( this . menu . find ( ".ui-state-active" ) , null , "ui-state-active" ) ;
2013-09-16 18:45:48 +00:00
this . menuInstance . focus ( null , this . _getSelectedItem ( ) ) ;
2013-03-07 18:34:13 +00:00
}
2012-02-24 21:39:11 +00:00
2015-01-12 16:23:08 +00:00
// If there are no options, don't open the menu
if ( ! this . menuItems . length ) {
return ;
}
2012-11-29 19:23:30 +00:00
this . isOpen = true ;
this . _toggleAttr ( ) ;
2013-09-29 13:33:14 +00:00
this . _resizeMenu ( ) ;
2013-07-10 22:45:54 +00:00
this . _position ( ) ;
2012-11-29 19:23:30 +00:00
2013-05-15 19:04:10 +00:00
this . _on ( this . document , this . _documentClick ) ;
2012-11-29 19:23:30 +00:00
this . _trigger ( "open" , event ) ;
2011-11-18 16:14:38 +00:00
} ,
2013-08-02 01:41:58 +00:00
2013-07-10 22:45:54 +00:00
_position : function ( ) {
this . menuWrap . position ( $ . extend ( { of : this . button } , this . options . position ) ) ;
} ,
2011-11-18 16:14:38 +00:00
2012-01-27 22:06:53 +00:00
close : function ( event ) {
2012-12-03 21:58:07 +00:00
if ( ! this . isOpen ) {
2012-12-03 22:05:09 +00:00
return ;
2011-09-22 19:20:49 +00:00
}
2012-12-09 11:36:35 +00:00
2012-11-29 19:57:44 +00:00
this . isOpen = false ;
this . _toggleAttr ( ) ;
2012-12-13 00:12:52 +00:00
2014-10-09 14:25:26 +00:00
this . range = null ;
2013-05-15 19:04:10 +00:00
this . _off ( this . document ) ;
2012-11-29 19:57:44 +00:00
this . _trigger ( "close" , event ) ;
2011-09-01 22:21:09 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-10-17 20:13:36 +00:00
widget : function ( ) {
2012-02-21 19:22:13 +00:00
return this . button ;
} ,
menuWidget : function ( ) {
return this . menu ;
2011-10-17 20:13:36 +00:00
} ,
2011-11-18 16:14:38 +00:00
2014-07-28 17:09:41 +00:00
_renderButtonItem : function ( item ) {
2014-12-03 16:26:46 +00:00
var buttonItem = $ ( "<span>" ) ;
2014-07-28 17:09:41 +00:00
this . _setText ( buttonItem , item . label ) ;
2014-12-03 16:26:46 +00:00
this . _addClass ( buttonItem , "ui-selectmenu-text" ) ;
2014-07-28 17:09:41 +00:00
return buttonItem ;
} ,
2011-09-01 22:21:09 +00:00
_renderMenu : function ( ul , items ) {
2011-09-28 21:59:23 +00:00
var that = this ,
2011-09-01 22:21:09 +00:00
currentOptgroup = "" ;
2011-11-18 16:14:38 +00:00
2011-09-01 22:21:09 +00:00
$ . each ( items , function ( index , item ) {
2014-12-03 16:26:46 +00:00
var li ;
2012-05-24 16:30:39 +00:00
if ( item . optgroup !== currentOptgroup ) {
2014-12-03 16:26:46 +00:00
li = $ ( "<li>" , {
2012-12-03 22:07:30 +00:00
text : item . optgroup
2015-03-14 11:28:17 +00:00
} ) ;
2014-12-03 16:26:46 +00:00
that . _addClass ( li , "ui-selectmenu-optgroup" , "ui-menu-divider" +
( item . element . parent ( "optgroup" ) . prop ( "disabled" ) ?
" ui-state-disabled" :
"" ) ) ;
li . appendTo ( ul ) ;
2014-04-08 15:17:32 +00:00
2011-09-01 22:21:09 +00:00
currentOptgroup = item . optgroup ;
}
2014-04-08 15:17:32 +00:00
2013-04-29 21:05:07 +00:00
that . _renderItemData ( ul , item ) ;
2015-03-14 11:28:17 +00:00
} ) ;
2011-09-01 22:21:09 +00:00
} ,
2011-11-18 16:14:38 +00:00
2013-04-29 21:05:07 +00:00
_renderItemData : function ( ul , item ) {
return this . _renderItem ( ul , item ) . data ( "ui-selectmenu-item" , item ) ;
} ,
2012-10-19 22:22:12 +00:00
_renderItem : function ( ul , item ) {
2014-09-26 21:34:22 +00:00
var li = $ ( "<li>" ) ,
2014-07-31 10:35:42 +00:00
wrapper = $ ( "<div>" , {
title : item . element . attr ( "title" )
2015-03-14 11:28:17 +00:00
} ) ;
2012-12-14 17:03:49 +00:00
2011-09-28 22:11:18 +00:00
if ( item . disabled ) {
2014-12-03 16:26:46 +00:00
this . _addClass ( li , null , "ui-state-disabled" ) ;
2011-11-18 16:14:38 +00:00
}
2014-09-26 21:34:22 +00:00
this . _setText ( wrapper , item . label ) ;
2012-12-14 17:03:49 +00:00
2014-09-26 21:34:22 +00:00
return li . append ( wrapper ) . appendTo ( ul ) ;
2012-12-14 17:03:49 +00:00
} ,
2011-11-18 16:14:38 +00:00
2012-12-14 17:03:49 +00:00
_setText : function ( element , value ) {
if ( value ) {
element . text ( value ) ;
} else {
element . html ( " " ) ;
}
2011-09-01 22:21:09 +00:00
} ,
2011-11-18 16:14:38 +00:00
2012-01-27 22:11:31 +00:00
_move : function ( direction , event ) {
2014-04-08 15:17:32 +00:00
var item , next ,
filter = ".ui-menu-item" ;
2013-10-29 18:52:54 +00:00
if ( this . isOpen ) {
2014-09-26 21:34:22 +00:00
item = this . menuItems . eq ( this . focusIndex ) . parent ( "li" ) ;
2013-10-29 18:52:54 +00:00
} else {
2014-09-26 21:34:22 +00:00
item = this . menuItems . eq ( this . element [ 0 ] . selectedIndex ) . parent ( "li" ) ;
2013-10-29 18:52:54 +00:00
filter += ":not(.ui-state-disabled)" ;
}
2012-05-16 18:41:24 +00:00
if ( direction === "first" || direction === "last" ) {
2013-10-29 18:52:54 +00:00
next = item [ direction === "first" ? "prevAll" : "nextAll" ] ( filter ) . eq ( - 1 ) ;
2011-12-23 00:34:12 +00:00
} else {
2013-10-29 18:52:54 +00:00
next = item [ direction + "All" ] ( filter ) . eq ( 0 ) ;
}
2013-07-01 20:23:12 +00:00
2013-10-29 18:52:54 +00:00
if ( next . length ) {
2014-04-08 15:17:32 +00:00
this . menuInstance . focus ( event , next ) ;
2011-12-23 00:34:12 +00:00
}
2011-09-24 00:04:06 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-09-24 02:04:54 +00:00
_getSelectedItem : function ( ) {
2014-09-26 21:34:22 +00:00
return this . menuItems . eq ( this . element [ 0 ] . selectedIndex ) . parent ( "li" ) ;
2011-09-24 02:04:54 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-09-24 00:04:06 +00:00
_toggle : function ( event ) {
2014-04-08 15:17:32 +00:00
this [ this . isOpen ? "close" : "open" ] ( event ) ;
2011-09-24 00:04:06 +00:00
} ,
2011-11-18 16:14:38 +00:00
2014-10-09 14:25:26 +00:00
_setSelection : function ( ) {
var selection ;
if ( ! this . range ) {
return ;
}
if ( window . getSelection ) {
selection = window . getSelection ( ) ;
selection . removeAllRanges ( ) ;
selection . addRange ( this . range ) ;
2015-08-21 04:06:35 +00:00
// Support: IE8
2014-10-09 14:25:26 +00:00
} else {
this . range . select ( ) ;
}
2015-08-21 04:06:35 +00:00
// Support: IE
2014-10-09 14:25:26 +00:00
// Setting the text selection kills the button focus in IE, but
// restoring the focus doesn't kill the selection.
this . button . focus ( ) ;
} ,
2012-12-12 16:26:17 +00:00
_documentClick : {
2013-10-29 19:54:16 +00:00
mousedown : function ( event ) {
2014-04-08 15:17:32 +00:00
if ( ! this . isOpen ) {
return ;
}
2015-04-27 06:30:01 +00:00
if ( ! $ ( event . target ) . closest ( ".ui-selectmenu-menu, #" +
$ . ui . escapeSelector ( this . ids . button ) ) . length ) {
2012-12-12 16:26:17 +00:00
this . close ( event ) ;
}
}
} ,
2011-10-17 20:03:22 +00:00
_buttonEvents : {
2014-07-29 13:48:04 +00:00
// Prevent text selection from being reset when interacting with the selectmenu (#10144)
2014-10-09 14:25:26 +00:00
mousedown : function ( ) {
var selection ;
if ( window . getSelection ) {
selection = window . getSelection ( ) ;
if ( selection . rangeCount ) {
this . range = selection . getRangeAt ( 0 ) ;
}
2015-08-21 04:06:35 +00:00
// Support: IE8
2014-10-09 14:25:26 +00:00
} else {
this . range = document . selection . createRange ( ) ;
}
2014-07-29 13:48:04 +00:00
} ,
2014-10-09 14:25:26 +00:00
click : function ( event ) {
this . _setSelection ( ) ;
this . _toggle ( event ) ;
} ,
2014-07-29 13:48:04 +00:00
2011-09-30 19:16:55 +00:00
keydown : function ( event ) {
2013-09-16 18:45:48 +00:00
var preventDefault = true ;
2012-02-26 02:46:27 +00:00
switch ( event . keyCode ) {
2015-03-14 11:28:17 +00:00
case $ . ui . keyCode . TAB :
case $ . ui . keyCode . ESCAPE :
this . close ( event ) ;
preventDefault = false ;
break ;
case $ . ui . keyCode . ENTER :
if ( this . isOpen ) {
this . _selectFocusedItem ( event ) ;
}
break ;
case $ . ui . keyCode . UP :
if ( event . altKey ) {
this . _toggle ( event ) ;
} else {
2013-10-29 18:52:54 +00:00
this . _move ( "prev" , event ) ;
2015-03-14 11:28:17 +00:00
}
break ;
case $ . ui . keyCode . DOWN :
if ( event . altKey ) {
this . _toggle ( event ) ;
} else {
2011-12-23 00:34:12 +00:00
this . _move ( "next" , event ) ;
2015-03-14 11:28:17 +00:00
}
break ;
case $ . ui . keyCode . SPACE :
if ( this . isOpen ) {
this . _selectFocusedItem ( event ) ;
} else {
this . _toggle ( event ) ;
}
break ;
case $ . ui . keyCode . LEFT :
this . _move ( "prev" , event ) ;
break ;
case $ . ui . keyCode . RIGHT :
this . _move ( "next" , event ) ;
break ;
case $ . ui . keyCode . HOME :
case $ . ui . keyCode . PAGE _UP :
this . _move ( "first" , event ) ;
break ;
case $ . ui . keyCode . END :
case $ . ui . keyCode . PAGE _DOWN :
this . _move ( "last" , event ) ;
break ;
default :
this . menu . trigger ( event ) ;
preventDefault = false ;
2011-12-22 00:51:16 +00:00
}
2013-09-16 18:45:48 +00:00
if ( preventDefault ) {
2011-12-22 00:51:16 +00:00
event . preventDefault ( ) ;
2011-09-30 19:16:55 +00:00
}
}
2011-11-18 16:14:38 +00:00
} ,
2012-01-27 22:11:31 +00:00
2014-04-08 15:20:38 +00:00
_selectFocusedItem : function ( event ) {
2014-09-26 21:34:22 +00:00
var item = this . menuItems . eq ( this . focusIndex ) . parent ( "li" ) ;
2014-04-08 15:20:38 +00:00
if ( ! item . hasClass ( "ui-state-disabled" ) ) {
this . _select ( item . data ( "ui-selectmenu-item" ) , event ) ;
2013-10-29 18:52:54 +00:00
}
} ,
2012-01-27 22:11:31 +00:00
_select : function ( item , event ) {
2012-02-26 02:46:27 +00:00
var oldIndex = this . element [ 0 ] . selectedIndex ;
2013-09-16 18:45:48 +00:00
2013-04-29 20:01:51 +00:00
// Change native select element
2012-02-26 02:46:27 +00:00
this . element [ 0 ] . selectedIndex = item . index ;
2014-07-28 17:09:41 +00:00
this . buttonItem . replaceWith ( this . buttonItem = this . _renderButtonItem ( item ) ) ;
2013-02-09 02:24:50 +00:00
this . _setAria ( item ) ;
2012-01-26 22:10:35 +00:00
this . _trigger ( "select" , event , { item : item } ) ;
2012-05-16 18:41:24 +00:00
if ( item . index !== oldIndex ) {
2012-01-26 22:10:35 +00:00
this . _trigger ( "change" , event , { item : item } ) ;
}
2013-09-16 18:45:48 +00:00
this . close ( event ) ;
2012-01-26 22:10:35 +00:00
} ,
2012-01-27 22:11:31 +00:00
2013-02-09 02:24:50 +00:00
_setAria : function ( item ) {
2013-10-09 23:01:41 +00:00
var id = this . menuItems . eq ( item . index ) . attr ( "id" ) ;
2013-03-01 16:18:03 +00:00
2015-03-14 11:28:17 +00:00
this . button . attr ( {
2013-02-13 22:07:25 +00:00
"aria-labelledby" : id ,
"aria-activedescendant" : id
2015-03-14 11:28:17 +00:00
} ) ;
2013-02-13 22:07:25 +00:00
this . menu . attr ( "aria-activedescendant" , id ) ;
2012-01-12 21:01:49 +00:00
} ,
2011-11-18 16:14:38 +00:00
2011-09-01 22:21:09 +00:00
_setOption : function ( key , value ) {
2012-12-19 23:16:37 +00:00
if ( key === "icons" ) {
2014-12-03 16:26:46 +00:00
var icon = this . button . find ( "span.ui-icon" ) ;
this . _removeClass ( icon , null , this . options . icons . button )
. _addClass ( icon , null , value . button ) ;
2012-12-19 23:16:37 +00:00
}
2011-11-18 16:15:01 +00:00
this . _super ( key , value ) ;
2011-11-18 16:14:38 +00:00
2011-09-01 22:21:09 +00:00
if ( key === "appendTo" ) {
2012-12-15 01:21:51 +00:00
this . menuWrap . appendTo ( this . _appendTo ( ) ) ;
2011-09-01 22:21:09 +00:00
}
2014-04-08 15:17:32 +00:00
2013-10-23 22:11:10 +00:00
if ( key === "width" ) {
2014-07-29 14:40:02 +00:00
this . _resizeButton ( ) ;
2013-09-29 13:33:14 +00:00
}
2011-09-01 22:21:09 +00:00
} ,
2012-01-27 22:11:31 +00:00
2015-09-21 11:01:13 +00:00
_setOptionDisabled : function ( value ) {
this . _super ( value ) ;
this . menuInstance . option ( "disabled" , value ) ;
this . button . attr ( "aria-disabled" , value ) ;
this . _toggleClass ( this . button , null , "ui-state-disabled" , value ) ;
this . element . prop ( "disabled" , value ) ;
if ( value ) {
this . button . attr ( "tabindex" , - 1 ) ;
this . close ( ) ;
} else {
this . button . attr ( "tabindex" , 0 ) ;
}
} ,
2012-12-15 01:21:51 +00:00
_appendTo : function ( ) {
var element = this . options . appendTo ;
if ( element ) {
element = element . jquery || element . nodeType ?
$ ( element ) :
this . document . find ( element ) . eq ( 0 ) ;
}
2014-02-21 12:35:34 +00:00
if ( ! element || ! element [ 0 ] ) {
2015-03-23 23:11:37 +00:00
element = this . element . closest ( ".ui-front, dialog" ) ;
2012-12-15 01:21:51 +00:00
}
if ( ! element . length ) {
2013-04-29 20:36:37 +00:00
element = this . document [ 0 ] . body ;
2012-12-15 01:21:51 +00:00
}
return element ;
} ,
2013-11-13 20:26:48 +00:00
_toggleAttr : function ( ) {
2014-12-03 16:26:46 +00:00
this . button . attr ( "aria-expanded" , this . isOpen ) ;
// We can't use two _toggleClass() calls here, because we need to make sure
// we always remove classes first and add them second, otherwise if both classes have the
// same theme class, it will be removed after we add it.
this . _removeClass ( this . button , "ui-selectmenu-button-" +
2014-08-22 20:40:09 +00:00
( this . isOpen ? "closed" : "open" ) )
2014-12-03 16:26:46 +00:00
. _addClass ( this . button , "ui-selectmenu-button-" +
( this . isOpen ? "open" : "closed" ) )
. _toggleClass ( this . menuWrap , "ui-selectmenu-open" , null , this . isOpen ) ;
2013-09-16 18:45:48 +00:00
this . menu . attr ( "aria-hidden" , ! this . isOpen ) ;
2012-01-20 00:30:16 +00:00
} ,
2012-02-26 00:50:55 +00:00
2014-07-29 14:40:02 +00:00
_resizeButton : function ( ) {
var width = this . options . width ;
2015-03-04 19:27:10 +00:00
// For `width: false`, just remove inline style and stop
if ( width === false ) {
this . button . css ( "width" , "" ) ;
return ;
}
// For `width: null`, match the width of the original element
if ( width === null ) {
2014-07-29 14:40:02 +00:00
width = this . element . show ( ) . outerWidth ( ) ;
this . element . hide ( ) ;
}
this . button . outerWidth ( width ) ;
} ,
2013-09-29 13:33:14 +00:00
_resizeMenu : function ( ) {
2013-10-23 22:11:10 +00:00
this . menu . outerWidth ( Math . max (
2013-09-29 13:33:14 +00:00
this . button . outerWidth ( ) ,
2014-04-08 15:17:32 +00:00
2015-08-21 04:06:35 +00:00
// Support: IE10
2013-11-25 23:56:50 +00:00
// IE10 wraps long text (possibly a rounding bug)
// so we add 1px to avoid the wrapping
this . menu . width ( "" ) . outerWidth ( ) + 1
2013-09-29 13:33:14 +00:00
) ) ;
} ,
2012-01-22 12:38:34 +00:00
_getCreateOptions : function ( ) {
2015-09-16 16:54:12 +00:00
var options = this . _super ( ) ;
options . disabled = this . element . prop ( "disabled" ) ;
return options ;
2012-01-22 12:38:34 +00:00
} ,
2011-09-30 19:51:37 +00:00
2014-04-08 15:17:32 +00:00
_parseOptions : function ( options ) {
2014-07-28 17:09:41 +00:00
var that = this ,
data = [ ] ;
2015-03-14 11:28:17 +00:00
options . each ( function ( index , item ) {
2014-07-28 17:09:41 +00:00
data . push ( that . _parseOption ( $ ( item ) , index ) ) ;
2015-03-14 11:28:17 +00:00
} ) ;
2011-09-30 19:16:55 +00:00
this . items = data ;
2011-09-01 22:21:09 +00:00
} ,
2011-11-18 16:14:38 +00:00
2014-07-28 17:09:41 +00:00
_parseOption : function ( option , index ) {
var optgroup = option . parent ( "optgroup" ) ;
return {
element : option ,
index : index ,
2014-11-04 13:36:33 +00:00
value : option . val ( ) ,
2014-07-28 17:09:41 +00:00
label : option . text ( ) ,
optgroup : optgroup . attr ( "label" ) || "" ,
disabled : optgroup . prop ( "disabled" ) || option . prop ( "disabled" )
} ;
} ,
2011-09-24 00:04:06 +00:00
_destroy : function ( ) {
2015-10-26 17:13:42 +00:00
this . _unbindFormResetHandler ( ) ;
2011-10-11 23:38:30 +00:00
this . menuWrap . remove ( ) ;
2013-03-07 22:53:15 +00:00
this . button . remove ( ) ;
2011-10-10 18:08:47 +00:00
this . element . show ( ) ;
2012-10-25 18:55:48 +00:00
this . element . removeUniqueId ( ) ;
2015-04-27 03:38:21 +00:00
this . labels . attr ( "for" , this . ids . element ) ;
2011-09-22 22:17:24 +00:00
}
2015-10-26 17:13:42 +00:00
} ] ) ;
2011-09-01 22:21:09 +00:00
2015-03-14 11:28:17 +00:00
} ) ) ;