From 485e0a06121d712bccad82a21a9e443292d2f9bb Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Mon, 26 Aug 2013 00:06:44 -0500 Subject: Menu: Only focus menu after click if focus is on an element within menu. Fixes #9044 - Menu: Autofocus issue with dialog opened from menu widget --- tests/unit/menu/menu_core.js | 18 ++++++++++++++++++ ui/jquery.ui.menu.js | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/unit/menu/menu_core.js b/tests/unit/menu/menu_core.js index 5ee28c14a..923d2961e 100644 --- a/tests/unit/menu/menu_core.js +++ b/tests/unit/menu/menu_core.js @@ -27,4 +27,22 @@ test( "accessibility", function () { // Item roles are tested in the role option tests }); +asyncTest( "#9044: Autofocus issue with dialog opened from menu widget", function() { + expect( 1 ); + var element = $( "#menu1" ).menu(); + + $( "", { id: "test9044" } ).appendTo( "body" ); + + $( "#testID1" ).bind( "click", function() { + $( "#test9044" ).focus(); + }); + + TestHelpers.menu.click( element, "3" ); + setTimeout( function() { + equal( document.activeElement.id, "test9044", "Focus was swallowed by menu" ); + $( "#test9044" ).remove(); + start(); + }); +}); + })( jQuery ); diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 3352eb8bd..272ab7bf4 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -85,7 +85,8 @@ $.widget( "ui.menu", { // Open submenu on click if ( target.has( ".ui-menu" ).length ) { this.expand( event ); - } else if ( !this.element.is( ":focus" ) ) { + } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { + // Redirect focus to the menu this.element.trigger( "focus", [ true ] ); -- cgit v1.2.3 From 041e0ec49267fbd5a8a967ea111527fd14332161 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Fri, 20 Sep 2013 17:59:04 +0200 Subject: Build: Update grunt-compare-size to latest, add it's .sizecache.json to .gitignore --- .gitignore | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index de4d1f007..a8b8bc7ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ dist node_modules +.sizecache.json \ No newline at end of file diff --git a/package.json b/package.json index 4a9316612..9be0a3621 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "grunt-contrib-qunit": "0.2.0", "grunt-contrib-csslint": "0.1.1", "grunt-contrib-cssmin": "0.4.2", - "grunt-compare-size": "0.3.1", + "grunt-compare-size": "0.4.0-rc.3", "grunt-html": "0.3.3", "grunt-git-authors": "1.2.0", "rimraf": "2.1.4", -- cgit v1.2.3 From 9ef09edc797566e81f20682ab93208c9076341b5 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Fri, 20 Sep 2013 18:15:55 +0200 Subject: Build: Remove the build task and it's dependencies. Will bring back testing against minified files later. --- Gruntfile.js | 35 ---------------------------------- build/tasks/build.js | 50 ------------------------------------------------- package.json | 1 - tests/unit/testsuite.js | 4 ++++ 4 files changed, 4 insertions(+), 86 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index b35a4514d..ad5e6f925 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -67,19 +67,6 @@ var } }, - minifyCSS = { - options: { - keepSpecialComments: 0 - }, - main: { - options: { - keepSpecialComments: "*" - }, - src: "dist/jquery-ui.css", - dest: "dist/jquery-ui.min.css" - } - }, - compareFiles = { all: [ "dist/jquery-ui.js", @@ -107,16 +94,6 @@ uiFiles.concat( allI18nFiles ).forEach(function( file ) { minify[ file ].files[ mapMinFile( file ) ] = file; }); -cssFiles.forEach(function( file ) { - minifyCSS[ file ] = { - options: { - banner: createBanner() - }, - src: file, - dest: "dist/" + file.replace( /\.css$/, ".min.css" ).replace( /themes\/base\//, "themes/base/minified/" ) - }; -}); - uiFiles.forEach(function( file ) { // TODO this doesn't do anything until https://github.com/rwldrn/grunt-compare-size/issues/13 compareFiles[ file ] = [ file, mapMinFile( file ) ]; @@ -128,7 +105,6 @@ grunt.loadNpmTasks( "grunt-contrib-uglify" ); grunt.loadNpmTasks( "grunt-contrib-concat" ); grunt.loadNpmTasks( "grunt-contrib-qunit" ); grunt.loadNpmTasks( "grunt-contrib-csslint" ); -grunt.loadNpmTasks( "grunt-contrib-cssmin" ); grunt.loadNpmTasks( "grunt-html" ); grunt.loadNpmTasks( "grunt-compare-size" ); grunt.loadNpmTasks( "grunt-git-authors" ); @@ -186,20 +162,12 @@ grunt.initConfig({ } }, uglify: minify, - cssmin: minifyCSS, htmllint: { // ignore files that contain invalid html, used only for ajax content testing all: grunt.file.expand( [ "demos/**/*.html", "tests/**/*.html" ] ).filter(function( file ) { return !/(?:ajax\/content\d\.html|tabs\/data\/test\.html|tests\/unit\/core\/core.*\.html)/.test( file ); }) }, - copy: { - dist_units_images: { - src: "themes/base/images/*", - strip: /^themes\/base\//, - dest: "dist/" - } - }, qunit: { files: expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now @@ -249,7 +217,4 @@ grunt.registerTask( "test", [ "qunit" ] ); grunt.registerTask( "sizer", [ "concat:ui", "uglify:main", "compare_size:all" ] ); grunt.registerTask( "sizer_all", [ "concat:ui", "uglify", "compare_size" ] ); -// "copy:dist_units_images" is used by unit tests -grunt.registerTask( "build", [ "concat", "uglify", "cssmin", "copy:dist_units_images" ] ); - }; diff --git a/build/tasks/build.js b/build/tasks/build.js index c50745899..cdc03bd60 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -2,21 +2,6 @@ module.exports = function( grunt ) { "use strict"; -var fs = require( "fs" ); - -function expandFiles( files ) { - return grunt.util._.pluck( grunt.file.expandMapping( files ), "src" ).filter(function(filepath) { - // restrict to files, exclude folders - try { - return fs.statSync( filepath[ 0 ] ).isFile(); - } catch(e) { - throw grunt.task.taskError(e.message, e); - } - }).map(function( values ) { - return values[ 0 ]; - }); -} - grunt.registerTask( "manifest", "Generate jquery.json manifest files", function() { var pkg = grunt.config( "pkg" ), base = { @@ -96,41 +81,6 @@ grunt.registerTask( "manifest", "Generate jquery.json manifest files", function( }); }); -grunt.registerMultiTask( "copy", "Copy files to destination folder and replace @VERSION with pkg.version", function() { - function replaceVersion( source ) { - return source.replace( /@VERSION/g, grunt.config( "pkg.version" ) ); - } - function copyFile( src, dest ) { - if ( /(js|css)$/.test( src ) ) { - grunt.file.copy( src, dest, { - process: replaceVersion - }); - } else { - grunt.file.copy( src, dest ); - } - } - var files = expandFiles( this.filesSrc ), - target = this.data.dest + "/", - strip = this.data.strip, - renameCount = 0, - fileName; - if ( typeof strip === "string" ) { - strip = new RegExp( "^" + grunt.template.process( strip, grunt.config() ).replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ) ); - } - files.forEach(function( fileName ) { - var targetFile = strip ? fileName.replace( strip, "" ) : fileName; - copyFile( fileName, target + targetFile ); - }); - grunt.log.writeln( "Copied " + files.length + " files." ); - for ( fileName in this.data.renames ) { - renameCount += 1; - copyFile( fileName, target + grunt.template.process( this.data.renames[ fileName ], grunt.config() ) ); - } - if ( renameCount ) { - grunt.log.writeln( "Renamed " + renameCount + " files." ); - } -}); - grunt.registerTask( "clean", function() { require( "rimraf" ).sync( "dist" ); }); diff --git a/package.json b/package.json index 9be0a3621..1495a16c2 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "grunt-contrib-concat": "0.1.3", "grunt-contrib-qunit": "0.2.0", "grunt-contrib-csslint": "0.1.1", - "grunt-contrib-cssmin": "0.4.2", "grunt-compare-size": "0.4.0-rc.3", "grunt-html": "0.3.3", "grunt-git-authors": "1.2.0", diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index cef24e93b..83d69d2d9 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -27,11 +27,15 @@ QUnit.reset = function() { QUnit.config.requireExpects = true; +/* +// TODO: Add back the ability to test against minified files +// see QUnit.urlParams.min usage below QUnit.config.urlConfig.push({ id: "min", label: "Minified source", tooltip: "Load minified source files instead of the regular unminified ones." }); +*/ TestHelpers.loadResources = QUnit.urlParams.min ? function() { -- cgit v1.2.3 From e6360ab846c6d0248d6013d005d2c178906ca692 Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Fri, 27 Sep 2013 13:49:57 -0400 Subject: Spinner: Only format the value when there is one. Fixes #9573 - Spinner: forces a field validation in Firefox before field loses focus or form is submitted --- ui/jquery.ui.spinner.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index a4912fc7e..3bbd35f88 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -55,8 +55,12 @@ $.widget( "ui.spinner", { this._setOption( "min", this.options.min ); this._setOption( "step", this.options.step ); - // format the value, but don't constrain - this._value( this.element.val(), true ); + // Only format if there is a value, prevents the field from being marked + // as invalid in Firefox, see #9573. + if ( this.value() !== "" ) { + // Format the value, but don't constrain. + this._value( this.element.val(), true ); + } this._draw(); this._on( this._events ); -- cgit v1.2.3 From ec3cf6725aa5ae0c69cb302df92eb933a517cbaa Mon Sep 17 00:00:00 2001 From: Jasper de Groot Date: Mon, 30 Sep 2013 17:23:57 +0200 Subject: Dialog: Changed the width of the close button. Fixed #9133 - Dialog: Resizing causes close icon to misalign in Firefox. --- themes/base/jquery.ui.dialog.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.dialog.css b/themes/base/jquery.ui.dialog.css index c5499d8db..b49a4a76d 100644 --- a/themes/base/jquery.ui.dialog.css +++ b/themes/base/jquery.ui.dialog.css @@ -31,7 +31,7 @@ position: absolute; right: .3em; top: 50%; - width: 21px; + width: 20px; margin: -10px 0 0 0; padding: 1px; height: 20px; -- cgit v1.2.3 From 2dfe85d3e2269a571e07bd550bbd838ee703b833 Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Mon, 30 Sep 2013 17:49:42 +0300 Subject: Dialog: Safe activeElement access. Fixed #9420 - Dialog: Close causes blur of window in IE9 Fixed #8443 - Dialog: "unspecified error" when using ie9 and iframe --- ui/jquery.ui.dialog.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 0170a42d2..f7265e605 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -169,7 +169,8 @@ $.widget( "ui.dialog", { enable: $.noop, close: function( event ) { - var that = this; + var activeElement, + that = this; if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { return; @@ -179,10 +180,22 @@ $.widget( "ui.dialog", { this._destroyOverlay(); if ( !this.opener.filter(":focusable").focus().length ) { - // Hiding a focused element doesn't trigger blur in WebKit - // so in case we have nothing to focus on, explicitly blur the active element - // https://bugs.webkit.org/show_bug.cgi?id=47182 - $( this.document[0].activeElement ).blur(); + + // support: IE9 + // IE9 throws an "Unspecified error" accessing document.activeElement from an + + +
+

a bunch of content

+
+ +
Just another dialog to test stacking
+ + + diff --git a/tests/visual/index.html b/tests/visual/index.html index 730eb4553..bb46137f4 100644 --- a/tests/visual/index.html +++ b/tests/visual/index.html @@ -33,7 +33,11 @@

Dialog

Effects

diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index f7265e605..0669cd852 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -212,7 +212,17 @@ $.widget( "ui.dialog", { }, _moveToTop: function( event, silent ) { - var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; + var moved = false, + zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { + return +$( this ).css( "z-index" ); + }).get(), + zIndexMax = Math.max.apply( null, zIndicies ); + + if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { + this.uiDialog.css( "z-index", zIndexMax + 1 ); + moved = true; + } + if ( moved && !silent ) { this._trigger( "focus", event ); } -- cgit v1.2.3 From b67d1037a8583b11658d1ecfc96e7971b0c7fcee Mon Sep 17 00:00:00 2001 From: Stephane Deschamps Date: Thu, 5 Sep 2013 14:37:09 +0200 Subject: Day TH's: scope=col. Closes gh-1074 A TH must feature a way to know which span of TD's it applies to, and in simple tables such as date tables, this can be achieved through the use of the scope attribute. --- ui/jquery.ui.datepicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index b433cb79b..0f0ee7fe2 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -1721,7 +1721,7 @@ $.extend(Datepicker.prototype, { thead = (showWeek ? "" + this._get(inst, "weekHeader") + "" : ""); for (dow = 0; dow < 7; dow++) { // days of the week day = (dow + firstDay) % 7; - thead += "= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + + thead += "= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + "" + dayNamesMin[day] + ""; } calender += thead + ""; -- cgit v1.2.3 From acf153e0b45ee333b1ea99842494c839462686a4 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 3 Oct 2013 11:44:49 -0400 Subject: Updated author information. --- .mailmap | 10 ++++++++-- AUTHORS.txt | 14 +++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.mailmap b/.mailmap index e88315efc..acd2f1ed6 100644 --- a/.mailmap +++ b/.mailmap @@ -5,8 +5,8 @@ Alexander Polomoshnov Aliaksandr Rahalevich Andrew Couch Andrew Newcomb -Andrew Powell -Andrew Powell +Andrew Powell +Andrew Powell Andrey Kapitcyn Ben Hollis Benjamin Scott Boyle @@ -17,6 +17,8 @@ Corey Frang Courtland Allen Dan Streetman Danny Trunk +David De Sloovere +David Murdoch Diego Tres Dominique Vincent Doug Blood @@ -34,6 +36,7 @@ Filippo Cavallarin Florian Gutmann Genie <386@mail.com> Guntupalli Karunakar +Heiko Henning Hiroshi Tomita Ian Simpson Igor Milla @@ -42,6 +45,7 @@ Jacek Jędrzejewski Jamie Gegerson Jason Oster Jay Merrifield +Jean-Francois Remy John Enters Jonathan Vingiano Josh Varner @@ -49,6 +53,7 @@ Justin Domnitz Justin MacCarthy Jörn Zaefferer Karl Kirch +Keith Wood Kevin Dalman Klaus Hartl Klaus Hartl @@ -97,6 +102,7 @@ Stojce Slavkovski Tarafder Ashek-E-Elahi Thibault Duplessis Ting Kuei +Todd Parker Wesley Walser Xavi Ramirez Ziling Zhao diff --git a/AUTHORS.txt b/AUTHORS.txt index e4660111f..b346dd698 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -14,7 +14,7 @@ Gilles van den Hoven Micheil Bryan Smith Jörn Zaefferer Marc Grabanski -Keith Wood +Keith Wood Brandon Aaron Scott González Eduardo Lundgren @@ -29,8 +29,8 @@ Ca-Phun Ung Ariel Flesler Maggie Wachs Scott Jehl -Todd Parker -Andrew Powell +Todd Parker +Andrew Powell Brant Burnett Douglas Neiner Paul Irish @@ -79,10 +79,10 @@ Phillip Barnes Kyle Wilkinson Khaled AlHourani Marian Rudzynski -Jean-Francois Remy +Jean-Francois Remy Doug Blood Filippo Cavallarin -Heiko Henning +Heiko Henning Aliaksandr Rahalevich Mario Visic Xavi Ramirez @@ -124,7 +124,7 @@ Israel Tsadok Carson McDonald Jason Davies Garrison Locke -David Murdoch +David Murdoch Benjamin Scott Boyle Jesse Baird Jonathan Vingiano @@ -153,7 +153,7 @@ Gaëtan Muller William Griffiths Stojce Slavkovski David Soms -David De Sloovere +David De Sloovere Michael P. Jung Shannon Pekary Matthew Edward Hutton -- cgit v1.2.3 From ed09ee5b75064c7e6aa221e834cd5843d7c16260 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 3 Oct 2013 12:09:50 -0400 Subject: Dialog: Added note explaining that _on() is safe to use for shared handlers because of stacking. --- ui/jquery.ui.dialog.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 0669cd852..cbae739bf 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -757,6 +757,8 @@ $.widget( "ui.dialog", { if ( !this.document.data( "ui-dialog-overlays" ) ) { // Prevent use of anchors and inputs + // Using _on() for an event handler shared across many instances is + // safe because the dialogs stack and must be closed in reverse order this._on( this.document, { focusin: function( event ) { if ( isOpening ) { -- cgit v1.2.3 From e14f75ed480e5b036bb47ab3398d1e0df28a128a Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 4 Oct 2013 10:10:30 -0400 Subject: Tabs: Keep reference to existing tablist during refresh. Fixes #9584 - Tabs: Refresh issue when tabs are moved to bottom. --- ui/jquery.ui.tabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 5f81cda10..4077c9ac5 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -441,7 +441,7 @@ $.widget( "ui.tabs", { // allow overriding how to find the list for rare usage scenarios (#7715) _getList: function() { - return this.element.find( "ol,ul" ).eq( 0 ); + return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); }, _createPanel: function( id ) { -- cgit v1.2.3 From 3a61627a501cb7ba1ce80046bfabbff0f7f2f517 Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Tue, 17 Sep 2013 23:22:33 -0500 Subject: Menu: Remove the requirement to use anchors in menu items --- demos/menu/default.html | 44 +++-- tests/unit/menu/menu.html | 321 +++++++++++++++++------------------ tests/unit/menu/menu_events.js | 16 +- tests/unit/menu/menu_methods.js | 4 +- tests/unit/menu/menu_options.js | 27 ++- tests/unit/menu/menu_test_helpers.js | 2 +- themes/base/jquery.ui.menu.css | 21 +-- ui/jquery.ui.menu.js | 70 ++++---- 8 files changed, 240 insertions(+), 265 deletions(-) diff --git a/demos/menu/default.html b/demos/menu/default.html index d44b18b35..5fc0971d9 100644 --- a/demos/menu/default.html +++ b/demos/menu/default.html @@ -22,42 +22,38 @@
diff --git a/tests/unit/menu/menu.html b/tests/unit/menu/menu.html index ed376232e..7de175b3c 100644 --- a/tests/unit/menu/menu.html +++ b/tests/unit/menu/menu.html @@ -48,220 +48,211 @@
diff --git a/tests/unit/menu/menu_events.js b/tests/unit/menu/menu_events.js index 405300c46..12bd5b703 100644 --- a/tests/unit/menu/menu_events.js +++ b/tests/unit/menu/menu_events.js @@ -91,7 +91,7 @@ asyncTest( "handle focus of menu with active item", function() { expect( 1 ); var element = $( "#menu1" ).menu({ focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); + log( $( event.target ).find( ".ui-state-focus" ).index() ); } }); @@ -177,7 +177,7 @@ asyncTest( "handle keyboard navigation on menu without scroll and without submen log( $( ui.item[ 0 ] ).text() ); }, focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); + log( $( event.target ).find( ".ui-state-focus" ).index() ); } }); @@ -243,7 +243,7 @@ asyncTest( "handle keyboard navigation on menu without scroll and with submenus" log( $( ui.item[0] ).text() ); }, focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); + log( $( event.target ).find( ".ui-state-focus" ).index() ); } }); @@ -341,7 +341,7 @@ asyncTest( "handle keyboard navigation on menu without scroll and with submenus" element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); - equal( logOutput(), "keydown,5,6,0,1,0,2,4,0", "Keydown skip dividers and items without anchors" ); + equal( logOutput(), "keydown,5,6,0,1,0,2,4,0", "Keydown skip dividers" ); log( "keydown", true ); element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); @@ -363,7 +363,7 @@ asyncTest( "handle keyboard navigation on menu with scroll and without submenus" log( $( ui.item[ 0 ] ).text() ); }, focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index()); + log( $( event.target ).find( ".ui-state-focus" ).index()); } }); @@ -438,7 +438,7 @@ asyncTest( "handle keyboard navigation on menu with scroll and with submenus", f log( $( ui.item[ 0 ] ).text() ); }, focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index()); + log( $( event.target ).find( ".ui-state-focus" ).index()); } }); @@ -533,7 +533,7 @@ asyncTest( "handle keyboard navigation and mouse click on menu with disabled ite log( $( ui.item[0] ).text() ); }, focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index()); + log( $( event.target ).find( ".ui-state-focus" ).index()); } }); @@ -581,7 +581,7 @@ asyncTest( "handle keyboard navigation with spelling of menu items", function() expect( 2 ); var element = $( "#menu2" ).menu({ focus: function( event ) { - log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); + log( $( event.target ).find( ".ui-state-focus" ).index() ); } }); diff --git a/tests/unit/menu/menu_methods.js b/tests/unit/menu/menu_methods.js index 51d772972..5a633998d 100644 --- a/tests/unit/menu/menu_methods.js +++ b/tests/unit/menu/menu_methods.js @@ -73,11 +73,11 @@ test( "refresh icons (see #9377)", function() { expect( 3 ); var element = $( "#menu1" ).menu(); ok( !element.hasClass( "ui-menu-icons") ); - element.find( "li:first a" ).html( "Save" ); + element.find( "li:first" ).html( "Save" ); element.menu( "refresh" ); ok( element.hasClass( "ui-menu-icons" ) ); - element.find( "li:first a" ).html( "Save" ); + element.find( "li:first" ).html( "Save" ); element.menu( "refresh" ); ok( !element.hasClass( "ui-menu-icons" ) ); }); diff --git a/tests/unit/menu/menu_options.js b/tests/unit/menu/menu_options.js index 27cea67a4..527cc4784 100644 --- a/tests/unit/menu/menu_options.js +++ b/tests/unit/menu/menu_options.js @@ -66,15 +66,14 @@ test( "{ icons: { submenu: 'custom' } }", function() { test( "{ role: 'menu' } ", function() { var element = $( "#menu1" ).menu(), items = element.find( "li" ); - expect( 2 + 5 * items.length ); + expect( 2 + 4 * items.length ); equal( element.attr( "role" ), "menu" ); ok( items.length > 0, "number of menu items" ); items.each(function( item ) { ok( $( this ).hasClass( "ui-menu-item" ), "menu item ("+ item + ") class for item" ); - equal( $( this ).attr( "role" ), "presentation", "menu item ("+ item + ") role" ); - equal( $( "a", this ).attr( "role" ), "menuitem", "menu item ("+ item + ") role" ); - ok( $( "a", this ).hasClass( "ui-corner-all" ), "a element class for menu item ("+ item + ")" ); - equal( $( "a", this ).attr( "tabindex" ), "-1", "a element tabindex for menu item ("+ item + ")" ); + equal( $( this ).attr( "role" ), "menuitem", "menu item ("+ item + ") role" ); + ok( $( this ).hasClass( "ui-corner-all" ), "class for menu item ("+ item + ")" ); + equal( $( this ).attr( "tabindex" ), "-1", "tabindex for menu item ("+ item + ")" ); }); }); @@ -83,15 +82,14 @@ test( "{ role: 'listbox' } ", function() { role: "listbox" }), items = element.find( "li" ); - expect( 2 + 5 * items.length ); + expect( 2 + 4 * items.length ); equal( element.attr( "role" ), "listbox" ); ok( items.length > 0, "number of menu items" ); items.each(function( item ) { ok( $( this ).hasClass( "ui-menu-item" ), "menu item ("+ item + ") class for item" ); - equal( $( this ).attr( "role" ), "presentation", "menu item ("+ item + ") role" ); - equal( $( "a", this ).attr( "role" ), "option", "menu item ("+ item + ") role" ); - ok( $( "a", this ).hasClass( "ui-corner-all" ), "a element class for menu item ("+ item + ")" ); - equal( $( "a", this ).attr( "tabindex" ), "-1", "a element tabindex for menu item ("+ item + ")" ); + equal( $( this ).attr( "role" ), "option", "menu item ("+ item + ") role" ); + ok( $( this ).hasClass( "ui-corner-all" ), "class for menu item ("+ item + ")" ); + equal( $( this ).attr( "tabindex" ), "-1", "tabindex for menu item ("+ item + ")" ); }); }); @@ -100,15 +98,14 @@ test( "{ role: null }", function() { role: null }), items = element.find( "li" ); - expect( 2 + 5 * items.length ); + expect( 2 + 4 * items.length ); strictEqual( element.attr( "role" ), undefined ); ok( items.length > 0, "number of menu items" ); items.each(function( item ) { ok( $( this ).hasClass( "ui-menu-item" ), "menu item ("+ item + ") class for item" ); - equal( $( this ).attr( "role" ), "presentation", "menu item ("+ item + ") role" ); - equal( $( "a", this ).attr( "role" ), undefined, "menu item ("+ item + ") role" ); - ok( $( "a", this ).hasClass( "ui-corner-all" ), "a element class for menu item ("+ item + ")" ); - equal( $( "a", this ).attr( "tabindex" ), "-1", "a element tabindex for menu item ("+ item + ")" ); + equal( $( this ).attr( "role" ), undefined, "menu item ("+ item + ") role" ); + ok( $( this ).hasClass( "ui-corner-all" ), "class for menu item ("+ item + ")" ); + equal( $( this ).attr( "tabindex" ), "-1", "tabindex for menu item ("+ item + ")" ); }); }); diff --git a/tests/unit/menu/menu_test_helpers.js b/tests/unit/menu/menu_test_helpers.js index b6c09ad7a..77737c390 100644 --- a/tests/unit/menu/menu_test_helpers.js +++ b/tests/unit/menu/menu_test_helpers.js @@ -24,7 +24,7 @@ TestHelpers.menu = { click: function( menu, item ) { lastItem = item; - menu.children( ":eq(" + item + ")" ).find( "a:first" ).trigger( "click" ); + menu.children( ":eq(" + item + ")" ).trigger( "click" ); } }; diff --git a/themes/base/jquery.ui.menu.css b/themes/base/jquery.ui.menu.css index 8a61d1b69..cc390cec4 100644 --- a/themes/base/jquery.ui.menu.css +++ b/themes/base/jquery.ui.menu.css @@ -21,8 +21,11 @@ } .ui-menu .ui-menu-item { margin: 0; - padding: 0; - width: 100%; + display: block; + padding: 2px .4em; + line-height: 1.5; + min-height: 0; /* support: IE7 */ + font-weight: normal; /* support: IE10, see #8844 */ list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); } @@ -33,16 +36,8 @@ line-height: 0; border-width: 1px 0 0 0; } -.ui-menu .ui-menu-item a { - text-decoration: none; - display: block; - padding: 2px .4em; - line-height: 1.5; - min-height: 0; /* support: IE7 */ - font-weight: normal; -} -.ui-menu .ui-menu-item a.ui-state-focus, -.ui-menu .ui-menu-item a.ui-state-active { +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { font-weight: normal; margin: -1px; } @@ -60,7 +55,7 @@ .ui-menu-icons { position: relative; } -.ui-menu-icons .ui-menu-item a { +.ui-menu-icons .ui-menu-item { position: relative; padding-left: 2em; } diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 272ab7bf4..0acba14bc 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -66,14 +66,14 @@ $.widget( "ui.menu", { this._on({ // 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 ) { + "mousedown .ui-menu-item": function( event ) { event.preventDefault(); }, - "click .ui-state-disabled > a": function( event ) { + "click .ui-state-disabled": function( event ) { event.preventDefault(); }, - "click .ui-menu-item:has(a)": function( event ) { - var target = $( event.target ).closest( ".ui-menu-item" ); + "click .ui-menu-item": function( event ) { + var target = $( event.target ); if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { this.select( event ); @@ -102,7 +102,7 @@ $.widget( "ui.menu", { 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" ); + target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" ); this.focus( event, target ); }, mouseleave: "collapseAll", @@ -161,18 +161,17 @@ $.widget( "ui.menu", { .removeClass( "ui-menu-item" ) .removeAttr( "role" ) .removeAttr( "aria-disabled" ) - .children( "a" ) - .removeUniqueId() - .removeClass( "ui-corner-all ui-state-hover" ) - .removeAttr( "tabIndex" ) - .removeAttr( "role" ) - .removeAttr( "aria-haspopup" ) - .children().each( function() { - var elem = $( this ); - if ( elem.data( "ui-menu-submenu-carat" ) ) { - elem.remove(); - } - }); + .removeUniqueId() + .removeClass( "ui-corner-all ui-state-hover" ) + .removeAttr( "tabIndex" ) + .removeAttr( "role" ) + .removeAttr( "aria-haspopup" ) + .children().each( function() { + var elem = $( this ); + if ( elem.data( "ui-menu-submenu-carat" ) ) { + elem.remove(); + } + }); // Destroy menu dividers this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); @@ -236,7 +235,7 @@ $.widget( "ui.menu", { regex = new RegExp( "^" + escape( character ), "i" ); match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { - return regex.test( $( this ).children( "a" ).text() ); + return regex.test( $( this ).text() ); }); match = skip && match.index( this.active.next() ) !== -1 ? this.active.nextAll( ".ui-menu-item" ) : @@ -248,7 +247,7 @@ $.widget( "ui.menu", { character = String.fromCharCode( event.keyCode ); regex = new RegExp( "^" + escape( character ), "i" ); match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { - return regex.test( $( this ).children( "a" ).text() ); + return regex.test( $( this ).text() ); }); } @@ -274,7 +273,7 @@ $.widget( "ui.menu", { _activate: function( event ) { if ( !this.active.is( ".ui-state-disabled" ) ) { - if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + if ( this.active.is( "[aria-haspopup='true']" ) ) { this.expand( event ); } else { this.select( event ); @@ -300,7 +299,7 @@ $.widget( "ui.menu", { }) .each(function() { var menu = $( this ), - item = menu.prev( "a" ), + item = menu.parent(), submenuCarat = $( "" ) .addClass( "ui-menu-icon ui-icon " + icon ) .data( "ui-menu-submenu-carat", true ); @@ -313,18 +312,6 @@ $.widget( "ui.menu", { menus = submenus.add( this.element ); - // Don't refresh list items that are already adapted - menus.children( ":not(.ui-menu-item):has(a)" ) - .addClass( "ui-menu-item" ) - .attr( "role", "presentation" ) - .children( "a" ) - .uniqueId() - .addClass( "ui-corner-all" ) - .attr({ - tabIndex: -1, - role: this._itemRole() - }); - // Initialize unlinked menu-items containing spaces and/or dashes only as dividers menus.children( ":not(.ui-menu-item)" ).each(function() { var item = $( this ); @@ -334,6 +321,16 @@ $.widget( "ui.menu", { } }); + // Don't refresh list items that are already adapted + menus.children( ":not(.ui-menu-item,.ui-menu-divider)" ) + .addClass( "ui-menu-item" ) + .uniqueId() + .addClass( "ui-corner-all" ) + .attr({ + tabIndex: -1, + role: this._itemRole() + }); + // Add aria-disabled attribute to any disabled menu item menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); @@ -371,7 +368,7 @@ $.widget( "ui.menu", { this._scrollIntoView( item ); this.active = item.first(); - focused = this.active.children( "a" ).addClass( "ui-state-focus" ); + focused = this.active.addClass( "ui-state-focus" ); // Only update aria-activedescendant if there's a role // otherwise we assume focus is managed elsewhere if ( this.options.role ) { @@ -382,7 +379,6 @@ $.widget( "ui.menu", { this.active .parent() .closest( ".ui-menu-item" ) - .children( "a:first" ) .addClass( "ui-state-active" ); if ( event && event.type === "keydown" ) { @@ -429,7 +425,7 @@ $.widget( "ui.menu", { return; } - this.active.children( "a" ).removeClass( "ui-state-focus" ); + this.active.removeClass( "ui-state-focus" ); this.active = null; this._trigger( "blur", event, { item: this.active } ); @@ -499,7 +495,7 @@ $.widget( "ui.menu", { .attr( "aria-hidden", "true" ) .attr( "aria-expanded", "false" ) .end() - .find( "a.ui-state-active" ) + .find( ".ui-state-active" ) .removeClass( "ui-state-active" ); }, -- cgit v1.2.3 From fba5c6f94ae758452174c71db7ab107796b59486 Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Sun, 22 Sep 2013 21:03:46 -0500 Subject: Menu tests: Remove anchors from visual test --- tests/visual/menu/menu.html | 312 ++++++++++++++++++++------------------------ 1 file changed, 144 insertions(+), 168 deletions(-) diff --git a/tests/visual/menu/menu.html b/tests/visual/menu/menu.html index 3d4e81e92..f25163d5f 100644 --- a/tests/visual/menu/menu.html +++ b/tests/visual/menu/menu.html @@ -44,171 +44,161 @@

Default inline menu

Inline with disabled items and submenus

Menu with icons

Long menu with scroll overflow, to test menu's scroll-on-keypress behaviour

Menu with custom markup

@@ -216,93 +206,79 @@

Menu with custom markup, multi-line items and a custom submenu icon

Inline with dividers and elements without anchors

-- cgit v1.2.3 From e08791d2c1be7628b7fd6ca2398cff195cb2e2c2 Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Sun, 22 Sep 2013 22:25:29 -0500 Subject: Autocomplete: Don't add anchors to items in generated menu --- ui/jquery.ui.autocomplete.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 8328cb6e5..d1a3c252d 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -523,9 +523,7 @@ $.widget( "ui.autocomplete", { }, _renderItem: function( ul, item ) { - return $( "
  • " ) - .append( $( "" ).text( item.label ) ) - .appendTo( ul ); + return $( "
  • " ).text( item.label ).appendTo( ul ); }, _move: function( direction, event ) { -- cgit v1.2.3 From 31e705ab324ec830062eee173a112551f7c919ea Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Tue, 24 Sep 2013 23:46:59 -0500 Subject: Menu: Add items option for better definition of menu items in non parent-child structures --- tests/unit/menu/menu.html | 43 ++++++++++++++++++++++++++++++++++++++++++ tests/unit/menu/menu_common.js | 1 + tests/unit/menu/menu_events.js | 31 ++++++++++++++++++++++++++++++ tests/visual/menu/menu.html | 9 +++++++-- ui/jquery.ui.menu.js | 25 +++++++++++++----------- 5 files changed, 96 insertions(+), 13 deletions(-) diff --git a/tests/unit/menu/menu.html b/tests/unit/menu/menu.html index 7de175b3c..a49c72a04 100644 --- a/tests/unit/menu/menu.html +++ b/tests/unit/menu/menu.html @@ -255,6 +255,49 @@
  • Saarland
  • + +
    diff --git a/tests/unit/menu/menu_common.js b/tests/unit/menu/menu_common.js index 4a89a947a..2404ebe02 100644 --- a/tests/unit/menu/menu_common.js +++ b/tests/unit/menu/menu_common.js @@ -4,6 +4,7 @@ TestHelpers.commonWidgetTests( "menu", { icons: { submenu: "ui-icon-carat-1-e" }, + items: "> *", menus: "ul", position: { my: "left top", diff --git a/tests/unit/menu/menu_events.js b/tests/unit/menu/menu_events.js index 12bd5b703..0b89b86ac 100644 --- a/tests/unit/menu/menu_events.js +++ b/tests/unit/menu/menu_events.js @@ -577,6 +577,37 @@ asyncTest( "handle keyboard navigation and mouse click on menu with disabled ite } }); +asyncTest( "handle keyboard navigation and mouse click on menu with dividers and group labels", function() { + expect( 2 ); + var element = $( "#menu7" ).menu({ + items: "> :not('.ui-menu-group')", + select: function( event, ui ) { + log( $( ui.item[0] ).text() ); + }, + focus: function( event ) { + log( $( event.target ).find( ".ui-state-focus" ).index()); + } + }); + + log( "keydown", true ); + element.one( "menufocus", function() { + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + equal( logOutput(), "keydown,2,Ada", "Keydown skips initial group label" ); + setTimeout( menukeyboard1, 50 ); + }); + element.focus(); + + function menukeyboard1() { + log( "keydown", true ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + equal( logOutput(), "keydown,3,4,7", "Keydown focus skips divider and group label" ); + start(); + } +}); + asyncTest( "handle keyboard navigation with spelling of menu items", function() { expect( 2 ); var element = $( "#menu2" ).menu({ diff --git a/tests/visual/menu/menu.html b/tests/visual/menu/menu.html index f25163d5f..1c203ef12 100644 --- a/tests/visual/menu/menu.html +++ b/tests/visual/menu/menu.html @@ -15,7 +15,7 @@ $( "

    " ).text( "Selected: " + ui.item.text() ).appendTo( "#log" ); } - $( "#menu1, #menu2, #menu3, .menu4, #menu7" ).menu({ + $( "#menu1, #menu2, #menu3, .menu4" ).menu({ select: logger }); @@ -29,6 +29,11 @@ select: logger, icon: "ui-icon-carat-1-s" }); + + $( "#menu7" ).menu({ + items: "> :not('.ui-menu-group')", + select: logger + }); });