2010-04-21 19:01:08 +00:00
/ *
* jQuery UI Menu @ VERSION
2011-06-10 10:20:45 +00:00
*
2011-01-17 14:13:18 +00:00
* Copyright 2011 , AUTHORS . txt ( http : //jqueryui.com/about)
2010-07-09 13:31:53 +00:00
* Dual licensed under the MIT or GPL Version 2 licenses .
* http : //jquery.org/license
2010-04-21 19:01:08 +00:00
*
* http : //docs.jquery.com/UI/Menu
*
* Depends :
* jquery . ui . core . js
2010-07-09 13:31:53 +00:00
* jquery . ui . widget . js
2010-04-21 19:01:08 +00:00
* /
( function ( $ ) {
2011-06-10 10:20:45 +00:00
2010-11-16 19:35:08 +00:00
var idIncrement = 0 ;
2010-04-21 19:01:08 +00:00
2011-06-10 12:23:01 +00:00
$ . widget ( "ui.menu" , {
2011-05-28 19:39:55 +00:00
version : "@VERSION" ,
2011-01-23 22:55:53 +00:00
defaultElement : "<ul>" ,
2011-03-17 09:37:37 +00:00
delay : 150 ,
2011-02-24 11:05:20 +00:00
options : {
2011-09-14 15:29:36 +00:00
items : "ul" ,
2011-02-24 11:05:20 +00:00
position : {
my : "left top" ,
at : "right top"
2011-10-19 09:41:33 +00:00
} ,
trigger : null
2011-02-24 11:05:20 +00:00
} ,
2010-04-21 19:01:08 +00:00
_create : function ( ) {
2011-02-24 14:51:51 +00:00
this . activeMenu = this . element ;
2011-10-12 18:01:19 +00:00
this . isScrolling = false ;
2010-11-16 19:35:08 +00:00
this . menuId = this . element . attr ( "id" ) || "ui-menu-" + idIncrement ++ ;
2011-06-10 12:23:01 +00:00
if ( this . element . find ( ".ui-icon" ) . length ) {
this . element . addClass ( "ui-menu-icons" ) ;
2011-04-20 15:18:15 +00:00
}
2010-04-21 19:01:08 +00:00
this . element
2010-10-28 16:12:52 +00:00
. addClass ( "ui-menu ui-widget ui-widget-content ui-corner-all" )
2010-04-21 19:01:08 +00:00
. attr ( {
2010-11-16 19:35:08 +00:00
id : this . menuId ,
2011-04-15 17:18:38 +00:00
role : "menu"
2011-07-28 13:55:56 +00:00
} )
// need to catch all clicks on disabled menu
// not possible through _bind
2011-09-12 21:52:17 +00:00
. bind ( "click.menu" , $ . proxy ( function ( event ) {
if ( this . options . disabled ) {
2011-07-28 13:55:56 +00:00
event . preventDefault ( ) ;
}
2011-09-12 21:52:17 +00:00
} , this ) ) ;
2011-07-28 13:47:32 +00:00
this . _bind ( {
2011-11-24 04:37:55 +00:00
// Prevent focus from sticking to links inside menu after clicking
// them (focus should always stay on UL during navigation).
"mousedown .ui-menu-item > a" : function ( event ) {
event . preventDefault ( ) ;
} ,
2011-07-28 13:47:32 +00:00
"click .ui-menu-item:has(a)" : function ( event ) {
event . stopImmediatePropagation ( ) ;
var target = $ ( event . currentTarget ) ;
2011-03-15 18:02:18 +00:00
// it's possible to click an item without hovering it (#7085)
2011-07-28 13:47:32 +00:00
if ( ! this . active || ( this . active [ 0 ] !== target [ 0 ] ) ) {
this . focus ( event , target ) ;
2010-10-28 16:11:55 +00:00
}
2011-07-28 13:47:32 +00:00
this . select ( event ) ;
2011-11-24 04:37:55 +00:00
// Redirect focus to the menu.
this . element . focus ( ) ;
2011-07-28 13:47:32 +00:00
} ,
"mouseover .ui-menu-item" : function ( event ) {
event . stopImmediatePropagation ( ) ;
2011-10-12 18:01:19 +00:00
if ( ! this . isScrolling ) {
var target = $ ( event . currentTarget ) ;
// Remove ui-state-active class from siblings of the newly focused menu item to avoid a jump caused by adjacent elements both having a class with a border
target . siblings ( ) . children ( ".ui-state-active" ) . removeClass ( "ui-state-active" ) ;
this . focus ( event , target ) ;
}
this . isScrolling = false ;
2011-07-28 13:47:32 +00:00
} ,
2011-09-22 18:56:53 +00:00
"mouseleave" : "collapseAll" ,
"mouseleave .ui-menu" : "collapseAll" ,
2011-07-28 13:52:52 +00:00
"mouseout .ui-menu-item" : "blur" ,
2011-07-28 13:47:32 +00:00
"focus" : function ( event ) {
this . focus ( event , $ ( event . target ) . children ( ".ui-menu-item:first" ) ) ;
} ,
2011-09-22 18:56:53 +00:00
blur : function ( event ) {
this . _delay ( function ( ) {
2011-10-20 20:57:47 +00:00
if ( ! $ . contains ( this . element [ 0 ] , this . document [ 0 ] . activeElement ) ) {
2011-09-22 18:56:53 +00:00
this . collapseAll ( event ) ;
}
} , 0 ) ;
2011-10-12 18:01:19 +00:00
} ,
scroll : function ( event ) {
// Keep track of scrolling to prevent mouseover from firing inadvertently when scrolling the menu
this . isScrolling = true ;
2011-09-22 18:56:53 +00:00
}
2011-07-28 13:47:32 +00:00
} ) ;
2010-04-21 19:01:08 +00:00
this . refresh ( ) ;
2011-06-10 10:20:45 +00:00
2011-09-12 21:19:19 +00:00
this . element . attr ( "tabIndex" , 0 ) ;
this . _bind ( {
"keydown" : function ( event ) {
switch ( event . keyCode ) {
case $ . ui . keyCode . PAGE _UP :
2011-09-12 21:52:17 +00:00
this . previousPage ( event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
2011-02-24 14:51:51 +00:00
event . stopImmediatePropagation ( ) ;
2011-09-12 21:19:19 +00:00
break ;
case $ . ui . keyCode . PAGE _DOWN :
2011-09-12 21:52:17 +00:00
this . nextPage ( event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
2011-02-24 14:51:51 +00:00
event . stopImmediatePropagation ( ) ;
2011-09-12 21:19:19 +00:00
break ;
case $ . ui . keyCode . HOME :
2011-09-12 21:52:17 +00:00
this . _move ( "first" , "first" , event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
2011-04-22 18:22:56 +00:00
event . stopImmediatePropagation ( ) ;
2011-09-12 21:19:19 +00:00
break ;
case $ . ui . keyCode . END :
2011-09-12 21:52:17 +00:00
this . _move ( "last" , "last" , event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
2011-03-17 16:43:11 +00:00
event . stopImmediatePropagation ( ) ;
2011-09-12 21:19:19 +00:00
break ;
case $ . ui . keyCode . UP :
2011-09-12 21:52:17 +00:00
this . previous ( event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
event . stopImmediatePropagation ( ) ;
break ;
case $ . ui . keyCode . DOWN :
2011-09-12 21:52:17 +00:00
this . next ( event ) ;
2011-09-12 21:19:19 +00:00
event . preventDefault ( ) ;
event . stopImmediatePropagation ( ) ;
break ;
case $ . ui . keyCode . LEFT :
2011-09-12 21:52:17 +00:00
if ( this . collapse ( event ) ) {
2011-09-12 21:19:19 +00:00
event . stopImmediatePropagation ( ) ;
}
event . preventDefault ( ) ;
break ;
case $ . ui . keyCode . RIGHT :
2011-09-12 21:52:17 +00:00
if ( this . expand ( event ) ) {
2011-09-12 21:19:19 +00:00
event . stopImmediatePropagation ( ) ;
}
event . preventDefault ( ) ;
break ;
case $ . ui . keyCode . ENTER :
2011-09-12 21:52:17 +00:00
if ( this . active . children ( "a[aria-haspopup='true']" ) . length ) {
if ( this . expand ( event ) ) {
2011-09-12 21:19:19 +00:00
event . stopImmediatePropagation ( ) ;
}
}
else {
2011-09-12 21:52:17 +00:00
this . select ( event ) ;
2011-09-12 21:19:19 +00:00
event . stopImmediatePropagation ( ) ;
}
event . preventDefault ( ) ;
break ;
case $ . ui . keyCode . ESCAPE :
2011-09-12 21:52:17 +00:00
if ( this . collapse ( event ) ) {
2011-09-12 21:19:19 +00:00
event . stopImmediatePropagation ( ) ;
}
event . preventDefault ( ) ;
break ;
default :
event . stopPropagation ( ) ;
2011-09-12 21:52:17 +00:00
clearTimeout ( this . filterTimer ) ;
2011-09-12 21:19:19 +00:00
var match ,
2011-09-12 21:52:17 +00:00
prev = this . previousFilter || "" ,
2011-09-12 21:19:19 +00:00
character = String . fromCharCode ( event . keyCode ) ,
skip = false ;
2011-06-10 10:20:45 +00:00
2011-09-12 21:19:19 +00:00
if ( character == prev ) {
skip = true ;
} else {
character = prev + character ;
}
function escape ( value ) {
return value . replace ( /[-[\]{}()*+?.,\\^$|#\s]/g , "\\$&" ) ;
}
2011-09-12 21:52:17 +00:00
match = this . activeMenu . children ( ".ui-menu-item" ) . filter ( function ( ) {
2011-06-10 12:23:01 +00:00
return new RegExp ( "^" + escape ( character ) , "i" )
. test ( $ ( this ) . children ( "a" ) . text ( ) ) ;
2011-02-24 09:40:12 +00:00
} ) ;
2011-09-12 21:52:17 +00:00
match = skip && match . index ( this . active . next ( ) ) != - 1 ? this . active . nextAll ( ".ui-menu-item" ) : match ;
2011-09-12 21:19:19 +00:00
if ( ! match . length ) {
character = String . fromCharCode ( event . keyCode ) ;
2011-09-12 21:52:17 +00:00
match = this . activeMenu . children ( ".ui-menu-item" ) . filter ( function ( ) {
2011-09-12 21:19:19 +00:00
return new RegExp ( "^" + escape ( character ) , "i" )
. test ( $ ( this ) . children ( "a" ) . text ( ) ) ;
} ) ;
}
if ( match . length ) {
2011-09-12 21:52:17 +00:00
this . focus ( event , match ) ;
2011-09-12 21:19:19 +00:00
if ( match . length > 1 ) {
2011-09-12 21:52:17 +00:00
this . previousFilter = character ;
this . filterTimer = this . _delay ( function ( ) {
delete this . previousFilter ;
2011-09-12 21:19:19 +00:00
} , 1000 ) ;
} else {
2011-09-12 21:52:17 +00:00
delete this . previousFilter ;
2011-09-12 21:19:19 +00:00
}
2011-02-24 09:40:12 +00:00
} else {
2011-09-12 21:52:17 +00:00
delete this . previousFilter ;
2011-02-24 09:40:12 +00:00
}
}
2010-04-30 11:04:09 +00:00
}
} ) ;
2011-07-10 04:30:35 +00:00
2011-10-20 20:57:47 +00:00
this . _bind ( this . document , {
2011-07-10 04:30:35 +00:00
click : function ( event ) {
if ( ! $ ( event . target ) . closest ( ".ui-menu" ) . length ) {
2011-07-19 21:15:59 +00:00
this . collapseAll ( event ) ;
2011-07-10 04:30:35 +00:00
}
}
} ) ;
2011-10-19 09:41:33 +00:00
if ( this . options . trigger ) {
this . element . popup ( {
trigger : this . options . trigger ,
managed : true ,
focusPopup : $ . proxy ( function ( event , ui ) {
this . focus ( event , this . element . children ( ".ui-menu-item" ) . first ( ) ) ;
this . element . focus ( 1 ) ;
} , this )
} ) ;
}
2010-04-21 19:01:08 +00:00
} ,
2011-06-10 10:20:45 +00:00
2011-01-14 22:11:22 +00:00
_destroy : function ( ) {
2011-04-15 17:18:38 +00:00
//destroy (sub)menus
2011-10-19 09:41:33 +00:00
if ( this . options . trigger ) {
this . element . popup ( "destroy" ) ;
}
2010-06-18 08:57:20 +00:00
this . element
2011-04-15 17:18:38 +00:00
. removeAttr ( "aria-activedescendant" )
2011-09-14 15:29:36 +00:00
. find ( ".ui-menu" )
2011-04-15 17:18:38 +00:00
. andSelf ( )
2010-10-28 16:12:52 +00:00
. removeClass ( "ui-menu ui-widget ui-widget-content ui-corner-all" )
. removeAttr ( "role" )
2011-06-10 12:23:01 +00:00
. removeAttr ( "tabIndex" )
2011-04-15 17:18:38 +00:00
. removeAttr ( "aria-labelledby" )
2011-07-12 15:36:34 +00:00
. removeAttr ( "aria-expanded" )
. removeAttr ( "aria-hidden" )
2011-04-15 17:18:38 +00:00
. show ( ) ;
2011-06-10 10:20:45 +00:00
2011-04-15 17:18:38 +00:00
//destroy menu items
this . element . find ( ".ui-menu-item" )
. unbind ( ".menu" )
2010-10-28 16:12:52 +00:00
. removeClass ( "ui-menu-item" )
. removeAttr ( "role" )
. children ( "a" )
2011-02-14 11:06:04 +00:00
. removeClass ( "ui-corner-all ui-state-hover" )
2010-10-28 16:12:52 +00:00
. removeAttr ( "tabIndex" )
2011-04-15 17:18:38 +00:00
. removeAttr ( "role" )
2011-07-12 15:36:34 +00:00
. removeAttr ( "aria-haspopup" )
2011-04-15 17:18:38 +00:00
. removeAttr ( "id" )
2011-06-10 12:23:01 +00:00
. children ( ".ui-icon" )
. remove ( ) ;
2010-04-30 08:21:40 +00:00
} ,
2011-06-10 10:20:45 +00:00
2010-04-21 19:01:08 +00:00
refresh : function ( ) {
2011-09-12 22:24:43 +00:00
// initialize nested menus
2011-09-14 15:29:36 +00:00
var submenus = this . element . find ( this . options . items + ":not( .ui-menu )" )
2011-09-12 22:24:43 +00:00
. addClass ( "ui-menu ui-widget ui-widget-content ui-corner-all" )
. attr ( "role" , "menu" )
. hide ( )
. attr ( "aria-hidden" , "true" )
. attr ( "aria-expanded" , "false" ) ;
2011-06-10 10:20:45 +00:00
2010-04-21 19:01:08 +00:00
// don't refresh list items that are already adapted
2011-09-12 22:24:43 +00:00
var menuId = this . menuId ;
2011-09-14 15:29:36 +00:00
submenus . add ( this . element ) . children ( ":not( .ui-menu-item ):has( a )" )
2011-09-12 22:24:43 +00:00
. addClass ( "ui-menu-item" )
. attr ( "role" , "presentation" )
. children ( "a" )
. addClass ( "ui-corner-all" )
. attr ( "tabIndex" , - 1 )
. attr ( "role" , "menuitem" )
. attr ( "id" , function ( i ) {
return menuId + "-" + i ;
} ) ;
2011-06-10 10:20:45 +00:00
submenus . each ( function ( ) {
var menu = $ ( this ) ,
item = menu . prev ( "a" ) ;
item . attr ( "aria-haspopup" , "true" )
2011-09-12 22:24:43 +00:00
. prepend ( '<span class="ui-menu-icon ui-icon ui-icon-carat-1-e"></span>' ) ;
2011-06-10 10:20:45 +00:00
menu . attr ( "aria-labelledby" , item . attr ( "id" ) ) ;
2011-04-15 17:18:38 +00:00
} ) ;
2010-04-21 19:01:08 +00:00
} ,
2011-02-24 09:06:08 +00:00
focus : function ( event , item ) {
2011-07-19 21:15:59 +00:00
this . blur ( event ) ;
2011-06-10 10:20:45 +00:00
2010-10-28 16:12:52 +00:00
if ( this . _hasScroll ( ) ) {
2011-07-25 14:13:13 +00:00
var borderTop = parseFloat ( $ . curCSS ( this . activeMenu [ 0 ] , "borderTopWidth" , true ) ) || 0 ,
paddingTop = parseFloat ( $ . curCSS ( this . activeMenu [ 0 ] , "paddingTop" , true ) ) || 0 ,
offset = item . offset ( ) . top - this . activeMenu . offset ( ) . top - borderTop - paddingTop ,
scroll = this . activeMenu . scrollTop ( ) ,
elementHeight = this . activeMenu . height ( ) ,
2010-10-28 17:15:27 +00:00
itemHeight = item . height ( ) ;
2011-06-10 12:23:01 +00:00
2010-10-28 17:15:27 +00:00
if ( offset < 0 ) {
2011-07-25 14:13:13 +00:00
this . activeMenu . scrollTop ( scroll + offset ) ;
2010-10-28 17:15:27 +00:00
} else if ( offset + itemHeight > elementHeight ) {
2011-07-25 14:13:13 +00:00
this . activeMenu . scrollTop ( scroll + offset - elementHeight + itemHeight ) ;
2010-04-21 19:01:08 +00:00
}
}
2011-06-10 10:20:45 +00:00
2010-10-28 16:38:40 +00:00
this . active = item . first ( )
2010-10-28 16:12:52 +00:00
. children ( "a" )
2011-02-24 09:12:20 +00:00
. addClass ( "ui-state-focus" )
2010-04-21 19:01:08 +00:00
. end ( ) ;
2011-09-14 15:29:36 +00:00
this . element . attr ( "aria-activedescendant" , this . active . children ( "a" ) . attr ( "id" ) ) ;
2011-04-23 15:36:52 +00:00
// highlight active parent menu item, if any
2011-09-14 15:29:36 +00:00
this . active . parent ( ) . closest ( ".ui-menu-item" ) . children ( "a:first" ) . addClass ( "ui-state-active" ) ;
2011-06-10 10:20:45 +00:00
2011-09-12 21:52:17 +00:00
this . timer = this . _delay ( function ( ) {
this . _close ( ) ;
} , this . delay ) ;
2011-06-10 10:20:45 +00:00
2011-09-14 15:29:36 +00:00
var nested = $ ( "> .ui-menu" , item ) ;
2011-06-10 10:20:45 +00:00
if ( nested . length && ( /^mouse/ . test ( event . type ) ) ) {
2011-09-12 21:52:17 +00:00
this . _startOpening ( nested ) ;
2011-02-24 14:51:51 +00:00
}
this . activeMenu = item . parent ( ) ;
2011-06-10 10:20:45 +00:00
2010-10-28 16:12:52 +00:00
this . _trigger ( "focus" , event , { item : item } ) ;
2010-04-21 19:01:08 +00:00
} ,
2011-06-10 12:23:01 +00:00
blur : function ( event ) {
if ( ! this . active ) {
2010-11-16 19:35:08 +00:00
return ;
}
2011-06-10 10:20:45 +00:00
2011-06-10 12:23:01 +00:00
clearTimeout ( this . timer ) ;
2011-06-10 10:20:45 +00:00
2011-02-24 09:12:20 +00:00
this . active . children ( "a" ) . removeClass ( "ui-state-focus" ) ;
2010-04-21 19:01:08 +00:00
this . active = null ;
2011-07-19 21:15:59 +00:00
this . _trigger ( "blur" , event , { item : this . active } ) ;
2010-04-21 19:01:08 +00:00
} ,
2011-06-10 12:23:01 +00:00
_startOpening : function ( submenu ) {
clearTimeout ( this . timer ) ;
2011-07-14 15:10:28 +00:00
// Don't open if already open fixes a Firefox bug that caused a .5 pixel
// shift in the submenu position when mousing over the carat icon
if ( submenu . attr ( "aria-hidden" ) !== "true" ) {
return ;
}
2011-09-12 21:52:17 +00:00
this . timer = this . _delay ( function ( ) {
this . _close ( ) ;
this . _open ( submenu ) ;
} , this . delay ) ;
2011-03-17 09:37:37 +00:00
} ,
2011-06-10 10:20:45 +00:00
2011-06-10 12:23:01 +00:00
_open : function ( submenu ) {
clearTimeout ( this . timer ) ;
this . element
. find ( ".ui-menu" )
. not ( submenu . parents ( ) )
. hide ( )
. attr ( "aria-hidden" , "true" ) ;
2011-02-24 14:51:51 +00:00
var position = $ . extend ( { } , {
2011-06-10 12:23:01 +00:00
of : this . active
} , $ . type ( this . options . position ) == "function"
? this . options . position ( this . active )
: this . options . position
) ;
submenu . show ( )
. removeAttr ( "aria-hidden" )
. attr ( "aria-expanded" , "true" )
. position ( position ) ;
2011-02-24 14:51:51 +00:00
} ,
2011-06-10 10:20:45 +00:00
2011-09-22 18:56:53 +00:00
collapseAll : function ( event , all ) {
// if we were passed an event, look for the submenu that contains the event
var currentMenu = all ? this . element :
$ ( event && event . target ) . closest ( this . element . find ( ".ui-menu" ) ) ;
// if we found no valid submenu ancestor, use the main menu to close all sub menus anyway
if ( ! currentMenu . length ) {
currentMenu = this . element ;
2011-09-12 13:43:49 +00:00
}
2011-06-10 12:23:01 +00:00
2011-09-12 13:43:49 +00:00
this . _close ( currentMenu ) ;
2011-09-22 18:56:53 +00:00
this . blur ( event ) ;
this . activeMenu = currentMenu ;
2011-02-24 14:51:51 +00:00
} ,
2011-06-10 10:20:45 +00:00
2011-09-22 18:56:53 +00:00
// With no arguments, closes the currently active menu - if nothing is active
// it closes all menus. If passed an argument, it will search for menus BELOW
2011-09-12 13:43:49 +00:00
_close : function ( startMenu ) {
2011-09-14 15:29:36 +00:00
if ( ! startMenu ) {
2011-09-12 13:43:49 +00:00
startMenu = this . active ? this . active . parent ( ) : this . element ;
}
startMenu
2011-09-14 15:29:36 +00:00
. find ( ".ui-menu" )
2011-06-10 12:23:01 +00:00
. hide ( )
. attr ( "aria-hidden" , "true" )
. attr ( "aria-expanded" , "false" )
. end ( )
. find ( "a.ui-state-active" )
. removeClass ( "ui-state-active" ) ;
2011-02-24 14:51:51 +00:00
} ,
2011-07-05 15:02:33 +00:00
collapse : function ( event ) {
2011-09-14 15:29:36 +00:00
var newItem = this . active && this . active . parent ( ) . closest ( ".ui-menu-item" , this . element ) ;
2011-06-10 12:23:01 +00:00
if ( newItem && newItem . length ) {
2011-09-12 13:43:49 +00:00
this . _close ( ) ;
2011-06-10 12:23:01 +00:00
this . focus ( event , newItem ) ;
2011-02-24 14:51:51 +00:00
return true ;
}
} ,
2011-07-05 15:02:33 +00:00
expand : function ( event ) {
2011-09-14 15:29:36 +00:00
var newItem = this . active && this . active . children ( ".ui-menu " ) . children ( ".ui-menu-item" ) . first ( ) ;
2011-06-10 12:23:01 +00:00
if ( newItem && newItem . length ) {
this . _open ( newItem . parent ( ) ) ;
2011-06-10 10:20:45 +00:00
2011-04-18 21:05:50 +00:00
//timeout so Firefox will not hide activedescendant change in expanding submenu from AT
2011-09-12 21:52:17 +00:00
this . _delay ( function ( ) {
this . focus ( event , newItem ) ;
2011-06-10 10:20:45 +00:00
} , 20 ) ;
2011-02-24 14:51:51 +00:00
return true ;
}
} ,
2010-04-21 19:01:08 +00:00
next : function ( event ) {
2011-07-25 14:13:13 +00:00
this . _move ( "next" , "first" , event ) ;
2010-04-21 19:01:08 +00:00
} ,
previous : function ( event ) {
2011-07-25 14:13:13 +00:00
this . _move ( "prev" , "last" , event ) ;
2010-04-21 19:01:08 +00:00
} ,
first : function ( ) {
2010-10-28 16:12:52 +00:00
return this . active && ! this . active . prevAll ( ".ui-menu-item" ) . length ;
2010-04-21 19:01:08 +00:00
} ,
last : function ( ) {
2010-10-28 16:12:52 +00:00
return this . active && ! this . active . nextAll ( ".ui-menu-item" ) . length ;
2010-04-21 19:01:08 +00:00
} ,
2011-07-25 14:13:13 +00:00
_move : function ( direction , filter , event ) {
2010-10-28 16:12:52 +00:00
if ( ! this . active ) {
2011-07-25 14:13:13 +00:00
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" ) [ filter ] ( ) ) ;
2010-04-21 19:01:08 +00:00
return ;
}
2011-07-25 14:13:13 +00:00
var next ;
if ( direction === "first" || direction === "last" ) {
next = this . active [ direction === "first" ? "prevAll" : "nextAll" ] ( ".ui-menu-item" ) . eq ( - 1 ) ;
} else {
next = this . active [ direction + "All" ] ( ".ui-menu-item" ) . eq ( 0 ) ;
}
2010-10-28 16:12:52 +00:00
if ( next . length ) {
2011-02-24 09:06:08 +00:00
this . focus ( event , next ) ;
2010-04-21 19:01:08 +00:00
} else {
2011-07-25 14:13:13 +00:00
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" ) [ filter ] ( ) ) ;
2010-04-21 19:01:08 +00:00
}
} ,
2011-06-10 10:20:45 +00:00
2010-10-28 16:12:52 +00:00
nextPage : function ( event ) {
if ( this . _hasScroll ( ) ) {
2011-07-25 14:13:13 +00:00
if ( ! this . active ) {
2011-02-24 14:51:51 +00:00
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" ) . first ( ) ) ;
2010-04-21 19:01:08 +00:00
return ;
}
2011-07-25 14:13:13 +00:00
if ( this . last ( ) ) {
return ;
}
2010-04-21 19:01:08 +00:00
var base = this . active . offset ( ) . top ,
height = this . element . height ( ) ,
2010-10-28 17:15:27 +00:00
result ;
this . active . nextAll ( ".ui-menu-item" ) . each ( function ( ) {
2010-10-28 17:22:57 +00:00
result = $ ( this ) ;
return $ ( this ) . offset ( ) . top - base - height < 0 ;
2010-10-28 17:15:27 +00:00
} ) ;
2011-02-24 09:06:08 +00:00
this . focus ( event , result ) ;
2010-04-21 19:01:08 +00:00
} else {
2011-02-24 14:51:51 +00:00
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" )
2011-07-25 14:13:13 +00:00
[ ! this . active ? "first" : "last" ] ( ) ) ;
2010-04-21 19:01:08 +00:00
}
} ,
2010-10-28 16:12:52 +00:00
previousPage : function ( event ) {
if ( this . _hasScroll ( ) ) {
2011-07-25 14:13:13 +00:00
if ( ! this . active ) {
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" ) . first ( ) ) ;
return ;
}
if ( this . first ( ) ) {
2010-04-21 19:01:08 +00:00
return ;
}
var base = this . active . offset ( ) . top ,
2010-10-28 17:15:27 +00:00
height = this . element . height ( ) ,
result ;
this . active . prevAll ( ".ui-menu-item" ) . each ( function ( ) {
2010-10-28 17:22:57 +00:00
result = $ ( this ) ;
return $ ( this ) . offset ( ) . top - base + height > 0 ;
2010-10-28 17:15:27 +00:00
} ) ;
2011-02-24 09:06:08 +00:00
this . focus ( event , result ) ;
2010-04-21 19:01:08 +00:00
} else {
2011-07-25 14:13:13 +00:00
this . focus ( event , this . activeMenu . children ( ".ui-menu-item" ) . first ( ) ) ;
2010-04-21 19:01:08 +00:00
}
} ,
2010-06-19 14:59:27 +00:00
_hasScroll : function ( ) {
2011-06-08 21:02:57 +00:00
return this . element . height ( ) < this . element . prop ( "scrollHeight" ) ;
2010-04-21 19:01:08 +00:00
} ,
select : function ( event ) {
2011-09-22 18:56:53 +00:00
2011-07-14 15:20:47 +00:00
// save active reference before collapseAll triggers blur
2011-02-24 14:51:51 +00:00
var ui = {
item : this . active
} ;
2011-09-22 18:56:53 +00:00
this . collapseAll ( event , true ) ;
2011-10-19 09:41:33 +00:00
if ( this . options . trigger ) {
$ ( this . options . trigger ) . focus ( 1 ) ;
this . element . popup ( "close" ) ;
}
2011-02-24 14:51:51 +00:00
this . _trigger ( "select" , event , ui ) ;
2010-04-21 19:01:08 +00:00
}
} ) ;
2010-10-28 16:12:52 +00:00
} ( jQuery ) ) ;