From 26d6952bd2b81de2ad2adb0bb77c1be6f2d717c2 Mon Sep 17 00:00:00 2001 From: kborchers Date: Sat, 14 Apr 2012 15:33:48 -0400 Subject: Menu: Remove most event.stopImmediatePropagation() to allow proper event bubbling --- ui/jquery.ui.menu.js | 61 +++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 6982da3c3..01b7d0992 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -13,7 +13,8 @@ */ (function($) { -var idIncrement = 0; +var idIncrement = 0, + currentEventTarget; $.widget( "ui.menu", { version: "@VERSION", @@ -66,16 +67,22 @@ $.widget( "ui.menu", { event.preventDefault(); }, "click .ui-menu-item:has(a)": function( event ) { - event.stopImmediatePropagation(); - // Don't select disabled menu items - if ( !$( event.target ).closest( ".ui-menu-item" ).is( ".ui-state-disabled" ) ) { - this.select( event ); - // Redirect focus to the menu with a delay for firefox - this._delay(function() { - if ( !this.element.is(":focus") ) { - this.element.focus(); - } - }, 20 ); + var target = $( event.target ); + if ( target[0] != currentEventTarget ) { + currentEventTarget = target[0]; + target.one( "click", function( event ) { + currentEventTarget = ""; + }); + // Don't select disabled menu items + if ( !target.closest( ".ui-menu-item" ).is( ".ui-state-disabled" ) ) { + this.select( event ); + // Redirect focus to the menu with a delay for firefox + this._delay(function() { + if ( !this.element.is(":focus") ) { + this.element.focus(); + } + }, 20 ); + } } }, "mouseover .ui-menu-item": function( event ) { @@ -158,65 +165,49 @@ $.widget( "ui.menu", { case $.ui.keyCode.PAGE_UP: this.previousPage( event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.PAGE_DOWN: this.nextPage( event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.HOME: this._move( "first", "first", event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.END: this._move( "last", "last", event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.UP: this.previous( event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.DOWN: this.next( event ); event.preventDefault(); - event.stopImmediatePropagation(); break; case $.ui.keyCode.LEFT: - if (this.collapse( event )) { - event.stopImmediatePropagation(); - } + this.collapse( event ); event.preventDefault(); break; case $.ui.keyCode.RIGHT: - if (this.expand( event )) { - event.stopImmediatePropagation(); - } + this.expand( event ); event.preventDefault(); break; case $.ui.keyCode.ENTER: if ( this.active.children( "a[aria-haspopup='true']" ).length ) { - if ( this.expand( event ) ) { - event.stopImmediatePropagation(); - } + this.expand( event ); } else { this.select( event ); - event.stopImmediatePropagation(); } event.preventDefault(); break; case $.ui.keyCode.ESCAPE: - if ( this.collapse( event ) ) { - event.stopImmediatePropagation(); - } + this.collapse( event ); event.preventDefault(); break; default: - event.stopPropagation(); clearTimeout( this.filterTimer ); var match, prev = this.previousFilter || "", @@ -303,7 +294,7 @@ $.widget( "ui.menu", { focus: function( event, item ) { var nested, borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; - this.blur( event ); + this.blur( event, event.type == "focus" ); if ( this._hasScroll() ) { borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; @@ -342,8 +333,10 @@ $.widget( "ui.menu", { this._trigger( "focus", event, { item: item } ); }, - blur: function( event ) { - clearTimeout( this.timer ); + blur: function( event, fromFocus ) { + if ( !fromFocus ) { + clearTimeout( this.timer ); + } if ( !this.active ) { return; -- cgit v1.2.3 From e2a6cdd5256e0befe8f75590499d501141a46463 Mon Sep 17 00:00:00 2001 From: kborchers Date: Sat, 14 Apr 2012 16:00:19 -0400 Subject: Menu: Check that the event object is defined before checking type --- ui/jquery.ui.menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 01b7d0992..5e6b335ba 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -294,7 +294,7 @@ $.widget( "ui.menu", { focus: function( event, item ) { var nested, borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; - this.blur( event, event.type == "focus" ); + this.blur( event, event && event.type == "focus" ); if ( this._hasScroll() ) { borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; -- cgit v1.2.3 From 9a6392033a0ee2b79999777a5e279e6aa3cfb12a Mon Sep 17 00:00:00 2001 From: kborchers Date: Mon, 16 Apr 2012 07:02:28 -0500 Subject: Menu: Add aria-disabled attribute to disabled items, namespace and cleanup the currentEventTarget click event --- ui/jquery.ui.menu.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 5e6b335ba..ec7a69754 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -14,7 +14,7 @@ (function($) { var idIncrement = 0, - currentEventTarget; + currentEventTarget = null; $.widget( "ui.menu", { version: "@VERSION", @@ -54,7 +54,9 @@ $.widget( "ui.menu", { }, this )); if ( this.options.disabled ) { - this.element.addClass( "ui-state-disabled" ); + this.element + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); } this._bind({ @@ -70,8 +72,8 @@ $.widget( "ui.menu", { var target = $( event.target ); if ( target[0] != currentEventTarget ) { currentEventTarget = target[0]; - target.one( "click", function( event ) { - currentEventTarget = ""; + target.one( "click.menu", function( event ) { + currentEventTarget = null; }); // Don't select disabled menu items if ( !target.closest( ".ui-menu-item" ).is( ".ui-state-disabled" ) ) { @@ -158,6 +160,9 @@ $.widget( "ui.menu", { .removeAttr( "id" ) .children( ".ui-icon" ) .remove(); + + // unbind currentEventTarget click event handler + $( currentEventTarget ).unbind( "click.menu" ); }, _keydown: function( event ) { @@ -282,6 +287,9 @@ $.widget( "ui.menu", { // initialize unlinked menu-items as dividers menus.children( ":not(.ui-menu-item)" ).addClass( "ui-widget-content ui-menu-divider" ); + // add aria-disabled attribut to any disabled menu item + menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); + submenus.each(function() { var menu = $( this ), item = menu.prev( "a" ); -- cgit v1.2.3 From fac809f9e5e30cb46053710970fb2a0e855ce9e1 Mon Sep 17 00:00:00 2001 From: kborchers Date: Mon, 16 Apr 2012 07:05:02 -0500 Subject: Menu: Fixed typo in comment --- ui/jquery.ui.menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index ec7a69754..dd099395d 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -287,7 +287,7 @@ $.widget( "ui.menu", { // initialize unlinked menu-items as dividers menus.children( ":not(.ui-menu-item)" ).addClass( "ui-widget-content ui-menu-divider" ); - // add aria-disabled attribut to any disabled menu item + // add aria-disabled attribute to any disabled menu item menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); submenus.each(function() { -- cgit v1.2.3 From 1ce42f4328167826e9868ee1bf21f96317927dec Mon Sep 17 00:00:00 2001 From: kborchers Date: Mon, 16 Apr 2012 23:30:33 -0500 Subject: Menu: Modified interactions to allow keyboard navigation to disabled items so that they are announced by screen readers but prevent selection of and navigation to sub-menus of disabled items --- tests/visual/menu/menu.html | 2 +- ui/jquery.ui.menu.js | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/tests/visual/menu/menu.html b/tests/visual/menu/menu.html index d67083663..e62e18ae5 100644 --- a/tests/visual/menu/menu.html +++ b/tests/visual/menu/menu.html @@ -118,7 +118,7 @@
  • Ada
  • Adamsville
  • Addyston
  • -
  • +
  • Delphi
    • Ada
    • diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index dd099395d..0e70f6774 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -99,7 +99,7 @@ $.widget( "ui.menu", { "mouseleave .ui-menu": "collapseAll", "focus": function( event ) { var menu = this.element, - firstItem = menu.children( ".ui-menu-item" ).not( ".ui-state-disabled" ).eq( 0 ); + firstItem = menu.children( ".ui-menu-item" ).eq( 0 ); if ( this._hasScroll() && !this.active ) { menu.children().each(function() { var currentItem = $( this ); @@ -196,15 +196,17 @@ $.widget( "ui.menu", { event.preventDefault(); break; case $.ui.keyCode.RIGHT: - this.expand( event ); + !this.active.is(".ui-state-disabled") && this.expand( event ); event.preventDefault(); break; case $.ui.keyCode.ENTER: - if ( this.active.children( "a[aria-haspopup='true']" ).length ) { - this.expand( event ); - } - else { - this.select( event ); + if ( !this.active.is(".ui-state-disabled") ) { + if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + this.expand( event ); + } + else { + this.select( event ); + } } event.preventDefault(); break; @@ -442,7 +444,6 @@ $.widget( "ui.menu", { this.active .children( ".ui-menu " ) .children( ".ui-menu-item" ) - .not( ".ui-state-disabled" ) .first(); if ( newItem && newItem.length ) { @@ -478,12 +479,10 @@ $.widget( "ui.menu", { if ( direction === "first" || direction === "last" ) { next = this.active [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) - .not( ".ui-state-disabled" ) .eq( -1 ); } else { next = this.active [ direction + "All" ]( ".ui-menu-item" ) - .not( ".ui-state-disabled" ) .eq( 0 ); } } @@ -492,9 +491,6 @@ $.widget( "ui.menu", { } this.focus( event, next ); - if ( next.is( ".ui-state-disabled" ) ) { - this._move( direction, filter, event ); - } }, nextPage: function( event ) { @@ -509,14 +505,14 @@ $.widget( "ui.menu", { var base = this.active.offset().top, height = this.element.height(), result; - this.active.nextAll( ".ui-menu-item" ).not( ".ui-state-disabled" ).each(function() { + this.active.nextAll( ".ui-menu-item" ).each(function() { result = $( this ); return $( this ).offset().top - base - height < 0; }); this.focus( event, result ); } else { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).not( ".ui-state-disabled" ) + this.focus( event, this.activeMenu.children( ".ui-menu-item" ) [ !this.active ? "first" : "last" ]() ); } }, @@ -533,14 +529,14 @@ $.widget( "ui.menu", { var base = this.active.offset().top, height = this.element.height(), result; - this.active.prevAll( ".ui-menu-item" ).not( ".ui-state-disabled" ).each(function() { + this.active.prevAll( ".ui-menu-item" ).each(function() { result = $( this ); return $(this).offset().top - base + height > 0; }); this.focus( event, result ); } else { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).not( ".ui-state-disabled" ).first() ); + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); } }, -- cgit v1.2.3 From 49f85509fe17b99ce0470bf011c49e03c338fb2c Mon Sep 17 00:00:00 2001 From: kborchers Date: Wed, 18 Apr 2012 21:30:07 -0500 Subject: Menu: Whitespace --- ui/jquery.ui.menu.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 0e70f6774..b991b30e8 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -196,15 +196,16 @@ $.widget( "ui.menu", { event.preventDefault(); break; case $.ui.keyCode.RIGHT: - !this.active.is(".ui-state-disabled") && this.expand( event ); + if ( !this.active.is( ".ui-state-disabled" ) ) { + this.expand( event ); + } event.preventDefault(); break; case $.ui.keyCode.ENTER: - if ( !this.active.is(".ui-state-disabled") ) { + if ( !this.active.is( ".ui-state-disabled" ) ) { if ( this.active.children( "a[aria-haspopup='true']" ).length ) { this.expand( event ); - } - else { + } else { this.select( event ); } } -- cgit v1.2.3 From 72a0f5c5129b77c6e06c9936d290e89bd35a9eaa Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 19 Apr 2012 10:29:55 -0400 Subject: Menu: Lint. --- ui/jquery.ui.menu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index b991b30e8..abc759f1a 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -70,7 +70,7 @@ $.widget( "ui.menu", { }, "click .ui-menu-item:has(a)": function( event ) { var target = $( event.target ); - if ( target[0] != currentEventTarget ) { + if ( target[0] !== currentEventTarget ) { currentEventTarget = target[0]; target.one( "click.menu", function( event ) { currentEventTarget = null; @@ -305,7 +305,7 @@ $.widget( "ui.menu", { focus: function( event, item ) { var nested, borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; - this.blur( event, event && event.type == "focus" ); + this.blur( event, event && event.type === "focus" ); if ( this._hasScroll() ) { borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; -- cgit v1.2.3 From 00306d6bbdf6c12ae1499ec090ef62dfd1a59ec5 Mon Sep 17 00:00:00 2001 From: kborchers Date: Thu, 19 Apr 2012 23:49:33 -0500 Subject: Menu: Bind to mouseenter instead of mouseover to avoid use of stopImmediatePropagation --- ui/jquery.ui.menu.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'ui/jquery.ui.menu.js') diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index abc759f1a..bcefd5822 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -87,8 +87,7 @@ $.widget( "ui.menu", { } } }, - "mouseover .ui-menu-item": function( event ) { - event.stopImmediatePropagation(); + "mouseenter .ui-menu-item": function( event ) { 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 -- cgit v1.2.3