diff options
author | kborchers <kris.borchers@gmail.com> | 2011-12-15 12:56:12 -0600 |
---|---|---|
committer | kborchers <kris.borchers@gmail.com> | 2011-12-15 12:57:11 -0600 |
commit | a53916b45427d1afa3507acbebb6f92a03bbcd84 (patch) | |
tree | fac2d548af11865cecdca70c20a9d419ba9a7ace | |
parent | c00b685cb824fe940226be041067b0b9c44ba983 (diff) | |
parent | a8d0e4c8043b42257c51a1d65cd07d1042538062 (diff) | |
download | jquery-ui-a53916b45427d1afa3507acbebb6f92a03bbcd84.tar.gz jquery-ui-a53916b45427d1afa3507acbebb6f92a03bbcd84.zip |
Merge branch 'master' into selectmenu
-rw-r--r-- | demos/menubar/default.html | 55 | ||||
-rw-r--r-- | tests/unit/menu/menu_defaults.js | 2 | ||||
-rw-r--r-- | tests/unit/menu/menu_events.js | 7 | ||||
-rw-r--r-- | tests/visual/menu/menu.html | 4 | ||||
-rw-r--r-- | themes/base/jquery.ui.menu.css | 2 | ||||
-rw-r--r-- | themes/base/jquery.ui.menubar.css | 2 | ||||
-rw-r--r-- | ui/jquery.ui.menu.js | 76 | ||||
-rw-r--r-- | ui/jquery.ui.menubar.js | 101 |
8 files changed, 149 insertions, 100 deletions
diff --git a/demos/menubar/default.html b/demos/menubar/default.html index 72c124423..ef39a7121 100644 --- a/demos/menubar/default.html +++ b/demos/menubar/default.html @@ -35,6 +35,15 @@ }, select: select }); + + $("#bar3").menubar({ + position: { + within: $("#demo-frame").add(window).first() + }, + select: select, + items: ".menubarItem", + menuElement: ".menuElement" + }); }); </script> <style> @@ -136,6 +145,52 @@ </li> </ul> +<div id="bar3" class="menubar"> + <div class="menubarItem"> + <a href="#File">File</a> + <div class="menuElement"> + <div><a href="#Open...">Open...</a></div> + <div class="ui-state-disabled">Open recent...</div> + <div><a href="#Save">Save</a></div> + <div><a href="#Save as...">Save as...</a></div> + <div><a href="#Close">Close</a></div> + <div><a href="#Quit">Quit</a></div> + </div> + </div> + <div class="menubarItem"> + <a href="#Edit">Edit</a> + <div class="menuElement"> + <div><a href="#Copy">Copy</a></div> + <div><a href="#Cut">Cut</a></div> + <div class="ui-state-disabled">Paste</div> + </div> + </div> + <div class="menubarItem"> + <a href="#View">View</a> + <div class="menuElement"> + <div><a href="#Fullscreen">Fullscreen</a></div> + <div><a href="#Fit into view">Fit into view</a></div> + <div> + <a href="#Encoding">Encoding</a> + <div class="menuElement"> + <div class="ui-state-disabled">Auto-detect</div> + <div><a href="#UTF-8">UTF-8</a></div> + <div> + <a href="#UTF-16">UTF-16</a> + <div class="menuElement"> + <div><a href="#Option 1">Option 1</a></div> + <div><a href="#Option 2">Option 2</a></div> + <div class="ui-state-disabled">Option 3</div> + <div><a href="#Option 4">Option 4</a></div> + </div> + </div> + </div> + </div> + <div><a href="#Customize...">Customize...</a></div> + </div> + </div> +</div> + <div class="ui-widget" style="margin-top:2em; font-family:Arial"> Log: <div id="log" style="height: 100px; width: 300px; overflow: auto;" class="ui-widget-content"></div> diff --git a/tests/unit/menu/menu_defaults.js b/tests/unit/menu/menu_defaults.js index a559a3d8d..3d7ec297f 100644 --- a/tests/unit/menu/menu_defaults.js +++ b/tests/unit/menu/menu_defaults.js @@ -5,7 +5,7 @@ commonWidgetTests( "menu", { my: "left top", at: "right top" }, - items: "ul", + menus: "ul", trigger: null, // callbacks diff --git a/tests/unit/menu/menu_events.js b/tests/unit/menu/menu_events.js index 55ec1e2ff..79b98163b 100644 --- a/tests/unit/menu/menu_events.js +++ b/tests/unit/menu/menu_events.js @@ -27,7 +27,7 @@ test("handle click on custom item menu", function() { select: function(event, ui) { menu_log(); }, - items: "div" + menus: "div" }); menu_log("click",true); menu_click($('#menu5'),"1"); @@ -38,6 +38,8 @@ test("handle click on custom item menu", function() { equals( $("#log").html(), "1,3,2,afterclick,1,click,", "Click order not valid."); }); +/* Commenting out these tests until a way to handle the extra focus and blur events + fired by IE is found test( "handle blur: click", function() { expect( 4 ); var $menu = $( "#menu1" ).menu({ @@ -78,6 +80,7 @@ test( "handle blur on custom item menu: click", function() { $("#remove").remove(); }); +*/ asyncTest( "handle submenu auto collapse: mouseleave", function() { expect( 4 ); @@ -100,7 +103,7 @@ asyncTest( "handle submenu auto collapse: mouseleave", function() { asyncTest( "handle custom menu item submenu auto collapse: mouseleave", function() { expect( 5 ); - var $menu = $( "#menu5" ).menu( { items: "div" } ); + var $menu = $( "#menu5" ).menu( { menus: "div" } ); $menu.children( ":nth-child(7)" ).trigger( "mouseover" ); setTimeout(function() { diff --git a/tests/visual/menu/menu.html b/tests/visual/menu/menu.html index 50837f43e..0715ac7f7 100644 --- a/tests/visual/menu/menu.html +++ b/tests/visual/menu/menu.html @@ -28,14 +28,14 @@ select: function(event, ui) { $("<div/>").text("Selected: " + ui.item.text()).appendTo("#log"); }, - items: "div" + menus: "div" }); $("#menu6").menu({ select: function(event, ui) { $("<div/>").text("Selected: " + ui.item.text()).appendTo("#log"); }, - items: ".menuElement" + menus: ".menuElement" }); } diff --git a/themes/base/jquery.ui.menu.css b/themes/base/jquery.ui.menu.css index c616cf2c5..33a9498fb 100644 --- a/themes/base/jquery.ui.menu.css +++ b/themes/base/jquery.ui.menu.css @@ -14,7 +14,7 @@ .ui-menu .ui-menu-item a.ui-state-focus, .ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; } -.ui-menu li.ui-state-disabled { font-weight: normal; padding: .0em .4em; margin: .4em 0 .2em; line-height: 1.5; } +.ui-menu .ui-state-disabled { font-weight: normal; padding: .0em .4em; margin: .4em 0 .2em; line-height: 1.5; } /* icon support */ .ui-menu-icons { position: relative; } diff --git a/themes/base/jquery.ui.menubar.css b/themes/base/jquery.ui.menubar.css index 95c42ae9e..8b175f28a 100644 --- a/themes/base/jquery.ui.menubar.css +++ b/themes/base/jquery.ui.menubar.css @@ -12,4 +12,4 @@ .ui-menubar .ui-button { float: left; font-weight: normal; border-top-width: 0 !important; border-bottom-width: 0 !important; margin: 0; outline: none; } .ui-menubar .ui-menubar-link { border-right: 1px dashed transparent; border-left: 1px dashed transparent; } -.ui-menubar .ui-menu { width: 200px; position: absolute; z-index: 9999; } +.ui-menubar .ui-menu { width: 200px; position: absolute; z-index: 9999; font-weight: normal; } diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 0263cff65..6e534b1ba 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -54,14 +54,13 @@ $.widget( "ui.menu", { }, "click .ui-menu-item:has(a)": function( event ) { event.stopImmediatePropagation(); - var target = $( event.currentTarget ); - // it's possible to click an item without hovering it (#7085) - if ( !this.active || ( this.active[ 0 ] !== target[ 0 ] ) ) { - this.focus( event, target ); - } this.select( event ); - // Redirect focus to the menu. - this.element.focus(); + // 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 ) { event.stopImmediatePropagation(); @@ -72,9 +71,21 @@ $.widget( "ui.menu", { }, "mouseleave": "collapseAll", "mouseleave .ui-menu": "collapseAll", - "mouseout .ui-menu-item": "blur", "focus": function( event ) { - this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); + var firstItem = this.element.children( ".ui-menu-item" ).eq( 0 ); + if ( this._hasScroll() && !this.active ) { + var menu = this.element; + menu.children().each( function() { + var currentItem = $( this ); + if ( currentItem.offset().top - menu.offset().top >= 0 ) { + firstItem = currentItem; + return false; + } + }); + } else if ( this.active ) { + firstItem = this.active; + } + this.focus( event, firstItem ); }, blur: function( event ) { this._delay( function() { @@ -283,21 +294,6 @@ $.widget( "ui.menu", { focus: function( event, item ) { this.blur( event ); - if ( this._hasScroll() ) { - 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(), - itemHeight = item.height(); - - if ( offset < 0 ) { - this.activeMenu.scrollTop( scroll + offset ); - } else if ( offset + itemHeight > elementHeight ) { - this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); - } - } - this.active = item.first() .children( "a" ) .addClass( "ui-state-focus" ) @@ -463,15 +459,14 @@ $.widget( "ui.menu", { }, nextPage: function( event ) { + if ( !this.active ) { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + return; + } + if ( this.last() ) { + return; + } if ( this._hasScroll() ) { - if ( !this.active ) { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); - return; - } - if ( this.last() ) { - return; - } - var base = this.active.offset().top, height = this.element.height(), result; @@ -488,15 +483,14 @@ $.widget( "ui.menu", { }, previousPage: function( event ) { + if ( !this.active ) { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + return; + } + if ( this.first() ) { + return; + } if ( this._hasScroll() ) { - if ( !this.active ) { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); - return; - } - if ( this.first() ) { - return; - } - var base = this.active.offset().top, height = this.element.height(), result; @@ -512,7 +506,7 @@ $.widget( "ui.menu", { }, _hasScroll: function() { - return this.element.height() < this.element.prop( "scrollHeight" ); + return this.element.outerHeight() < this.element.prop( "scrollHeight" ); }, select: function( event ) { diff --git a/ui/jquery.ui.menubar.js b/ui/jquery.ui.menubar.js index 673493366..6bc03ba4d 100644 --- a/ui/jquery.ui.menubar.js +++ b/ui/jquery.ui.menubar.js @@ -22,6 +22,8 @@ $.widget( "ui.menubar", { options: { autoExpand: false, buttons: false, + items: "li", + menuElement: "ul", menuIcon: false, position: { my: "left top", @@ -30,19 +32,21 @@ $.widget( "ui.menubar", { }, _create: function() { var that = this; - var items = this.items = this.element.children( "li" ) + this.menuItems = this.element.children( this.options.items ); + this.items = this.menuItems.children( "button, a" ); + + this.menuItems .addClass( "ui-menubar-item" ) - .attr( "role", "presentation" ) - .children( "button, a" ); + .attr( "role", "presentation" ); // let only the first item receive focus - items.slice(1).attr( "tabIndex", -1 ); + this.items.slice(1).attr( "tabIndex", -1 ); this.element .addClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) .attr( "role", "menubar" ); - this._focusable( items ); - this._hoverable( items ); - items.next( "ul" ) + this._focusable( this.items ); + this._hoverable( this.items ); + this.items.siblings( this.options.menuElement ) .menu({ position: { within: this.options.position.within @@ -53,7 +57,8 @@ $.widget( "ui.menubar", { // TODO what is this targetting? there's probably a better way to access it $(event.target).prev().focus(); that._trigger( "select", event, ui ); - } + }, + menus: that.options.menuElement }) .hide() .attr({ @@ -66,19 +71,19 @@ $.widget( "ui.menubar", { return; switch ( event.keyCode ) { case $.ui.keyCode.LEFT: - that._left( event ); + that.previous( event ); event.preventDefault(); break; case $.ui.keyCode.RIGHT: - that._right( event ); + that.next( event ); event.preventDefault(); break; }; }); - items.each(function() { + this.items.each(function() { var input = $(this), // TODO menu var is only used on two places, doesn't quite justify the .each - menu = input.next( "ul" ); + menu = input.next( that.options.menuElement ); input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) { // ignore triggered focus event @@ -109,11 +114,11 @@ $.widget( "ui.menubar", { event.preventDefault(); break; case $.ui.keyCode.LEFT: - that._prev( event, $( this ) ); + that.previous( event ); event.preventDefault(); break; case $.ui.keyCode.RIGHT: - that._next( event, $( this ) ); + that.next( event ); event.preventDefault(); break; } @@ -166,17 +171,16 @@ $.widget( "ui.menubar", { }, _destroy : function() { - var items = this.element.children( "li" ) + this.menuItems .removeClass( "ui-menubar-item" ) - .removeAttr( "role" ) - .children( "button, a" ); + .removeAttr( "role" ); this.element .removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) .removeAttr( "role" ) .unbind( ".menubar" ); - items + this.items .unbind( ".menubar" ) .removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" ) .removeAttr( "role" ) @@ -243,55 +247,48 @@ $.widget( "ui.menubar", { }, this.options.position ) ) .removeAttr( "aria-hidden" ) .attr( "aria-expanded", "true" ) - .menu("focus", event, menu.children( "li" ).first() ) + .menu("focus", event, menu.children( ".ui-menu-item" ).first() ) // TODO need a comment here why both events are triggered .focus() .focusin(); this.open = true; }, - // TODO refactor this and the next three methods - _prev: function( event, button ) { - button.attr( "tabIndex", -1 ); - var prev = button.parent().prevAll( "li" ).children( ".ui-button" ).eq( 0 ); - if ( prev.length ) { - prev.removeAttr( "tabIndex" )[0].focus(); - } else { - var lastItem = this.element.children( "li:last" ).children( ".ui-button:last" ); - lastItem.removeAttr( "tabIndex" )[0].focus(); - } + next: function( event ) { + this._move( "next", "first", event ); }, - _next: function( event, button ) { - button.attr( "tabIndex", -1 ); - var next = button.parent().nextAll( "li" ).children( ".ui-button" ).eq( 0 ); - if ( next.length ) { - next.removeAttr( "tabIndex")[0].focus(); - } else { - var firstItem = this.element.children( "li:first" ).children( ".ui-button:first" ); - firstItem.removeAttr( "tabIndex" )[0].focus(); - } + previous: function( event ) { + this._move( "prev", "last", event ); }, - // TODO rename to parent - _left: function( event ) { - var prev = this.active.parent().prevAll( "li:eq(0)" ).children( ".ui-menu" ).eq( 0 ); - if ( prev.length ) { - this._open( event, prev ); + _move: function( direction, filter, event ) { + var next, + wrapItem; + if ( this.open ) { + next = this.active.closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).first().children( ".ui-menu" ).eq( 0 ); + wrapItem = this.menuItems[ filter ]().children( ".ui-menu" ).eq( 0 ); } else { - var lastItem = this.element.children( "li:last" ).children( ".ui-menu:first" ); - this._open( event, lastItem ); + if ( event ) { + next = $( event.target ).closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).children( ".ui-menubar-link" ).eq( 0 ); + wrapItem = this.menuItems[ filter ]().children( ".ui-menubar-link" ).eq( 0 ); + } else { + next = wrapItem = this.menuItems.children( "a" ).eq( 0 ); + } } - }, - // TODO rename to child (or something like that) - _right: function( event ) { - var next = this.active.parent().nextAll( "li:eq(0)" ).children( ".ui-menu" ).eq( 0 ); if ( next.length ) { - this._open( event, next ); + if ( this.open ) { + this._open( event, next ); + } else { + next.removeAttr( "tabIndex")[0].focus(); + } } else { - var firstItem = this.element.children( "li:first" ).children( ".ui-menu:first" ); - this._open( event, firstItem ); + if ( this.open ) { + this._open( event, wrapItem ); + } else { + wrapItem.removeAttr( "tabIndex")[0].focus(); + } } } }); |