diff options
45 files changed, 937 insertions, 590 deletions
diff --git a/AUTHORS.txt b/AUTHORS.txt index a53bc9dc2..1da44ef23 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -1,4 +1,4 @@ -Authors ordered by first contribution +Authors ordered by first contribution A list of current team members is available at http://jqueryui.com/about Paul Bakaus <paul.bakaus@googlemail.com> @@ -208,3 +208,19 @@ Sindre Sorhus <sindresorhus@gmail.com> Bernhard Sirlinger <bernhard.sirlinger@tele2.de> Jared A. Scheel <jared@jaredscheel.com> Rafael Xavier de Souza <rxaviers@gmail.com> +John Chen <zhang.z.chen@intel.com> +Dale Kocian <dale.kocian@gmail.com> +Mike Sherov <mike.sherov@gmail.com> +Andrew Couch <andy@couchand.com> +Marc-Andre Lafortune <github@marc-andre.ca> +Nate Eagle <nate.eagle@teamaol.com> +David Souther <davidsouther@gmail.com> +Mathias Stenbom <mathias@stenbom.com> +Avinash R <nashpapa@gmail.com> +Sergey Kartashov <ebishkek@yandex.ru> +Ethan Romba <ethanromba@gmail.com> +Cory Gackenheimer <cory.gack@gmail.com> +Juan Pablo Kaniefsky <jpkaniefsky@gmail.com> +Roman Salnikov <bardt.dz@gmail.com> +Anika Henke <anika@selfthinker.org> +Samuel Bovée <samycookie2000@yahoo.fr> diff --git a/build/release/release.js b/build/release/release.js index 0e41702e9..4efa1d2b7 100644 --- a/build/release/release.js +++ b/build/release/release.js @@ -262,8 +262,9 @@ function gatherContributors() { function updateTrac() { echo( newVersion.cyan + " was tagged at " + tagTime.cyan + "." ); - echo( "Close the " + newVersion.cyan + " Milestone with the above date and time." ); - echo( "Create the " + newVersion.cyan + " Version with the above date and time." ); + echo( "Close the " + newVersion.cyan + " Milestone." ); + echo( "Create the " + newVersion.cyan + " Version." ); + echo( "When Trac asks for date and time, match the above. Should only change minutes and seconds." ); echo( "Create a Milestone for the next minor release." ); } @@ -342,9 +343,7 @@ function bootstrap( fn ) { fs.mkdirSync( baseDir ); console.log( "Installing dependencies..." ); - require( "child_process" ).exec( "npm install shelljs colors", { - cwd: baseDir - }, function( error ) { + require( "child_process" ).exec( "npm install shelljs colors", function( error ) { if ( error ) { console.log( error ); return process.exit( 1 ); diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index aa2686685..37eb55281 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -15,6 +15,7 @@ var versions = { "Core": "core/core.html", "Datepicker": "datepicker/datepicker.html", "Dialog": "dialog/dialog.html", + "Dialog_deprecated": "dialog/dialog_deprecated.html", "Draggable": "draggable/draggable.html", "Droppable": "droppable/droppable.html", "Effects": "effects/effects.html", diff --git a/demos/autocomplete/combobox.html b/demos/autocomplete/combobox.html index 9fd5d4050..6229d47b2 100644 --- a/demos/autocomplete/combobox.html +++ b/demos/autocomplete/combobox.html @@ -24,7 +24,7 @@ bottom: 0; margin-left: -1px; padding: 0; - /* adjust styles for IE 6/7 */ + /* support: IE7 */ *height: 1.7em; *top: 0.1em; } @@ -46,7 +46,7 @@ .addClass( "ui-combobox" ) .insertAfter( select ); - function removeIfInvalid(element) { + function removeIfInvalid( element ) { var value = $( element ).val(), matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( value ) + "$", "i" ), valid = false; @@ -56,6 +56,7 @@ return false; } }); + if ( !valid ) { // remove invalid value, as it didn't match anything $( element ) @@ -66,8 +67,7 @@ setTimeout(function() { input.tooltip( "close" ).attr( "title", "" ); }, 2500 ); - input.data( "autocomplete" ).term = ""; - return false; + input.data( "ui-autocomplete" ).term = ""; } } @@ -103,13 +103,14 @@ }); }, change: function( event, ui ) { - if ( !ui.item ) - return removeIfInvalid( this ); + if ( !ui.item ) { + removeIfInvalid( this ); + } } }) .addClass( "ui-widget ui-widget-content ui-corner-left" ); - input.data( "autocomplete" )._renderItem = function( ul, item ) { + input.data( "ui-autocomplete" )._renderItem = function( ul, item ) { return $( "<li>" ) .append( "<a>" + item.label + "</a>" ) .appendTo( ul ); @@ -144,19 +145,14 @@ input.focus(); }); - input - .tooltip({ - position: { - of: this.button - }, - tooltipClass: "ui-state-highlight" - }); + input.tooltip({ + tooltipClass: "ui-state-highlight" + }); }, - destroy: function() { + _destroy: function() { this.wrapper.remove(); this.element.show(); - $.Widget.prototype.destroy.call( this ); } }); })( jQuery ); diff --git a/demos/button/toolbar.html b/demos/button/toolbar.html index eb1d2c3ea..5be3668f6 100644 --- a/demos/button/toolbar.html +++ b/demos/button/toolbar.html @@ -11,7 +11,12 @@ <link rel="stylesheet" href="../demos.css"> <style> #toolbar { - padding: 10px 4px; + padding: 11px 4px 9px 4px; + } + + /* support: IE7 */ + *:first-child+html #toolbar { + padding: 4px 0px 4px 5px; } </style> <script> diff --git a/demos/dialog/animated.html b/demos/dialog/animated.html index 8e1daf131..061396548 100644 --- a/demos/dialog/animated.html +++ b/demos/dialog/animated.html @@ -11,6 +11,7 @@ <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> <script src="../../ui/jquery.ui.resizable.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <script src="../../ui/jquery.ui.effect.js"></script> <script src="../../ui/jquery.ui.effect-blind.js"></script> diff --git a/demos/dialog/default.html b/demos/dialog/default.html index 214f41d0d..777921e48 100644 --- a/demos/dialog/default.html +++ b/demos/dialog/default.html @@ -11,6 +11,7 @@ <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> <script src="../../ui/jquery.ui.resizable.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <link rel="stylesheet" href="../demos.css"> <script> diff --git a/demos/dialog/modal-confirmation.html b/demos/dialog/modal-confirmation.html index e73c9ea2b..04f5d93fb 100644 --- a/demos/dialog/modal-confirmation.html +++ b/demos/dialog/modal-confirmation.html @@ -11,6 +11,7 @@ <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <link rel="stylesheet" href="../demos.css"> <script> diff --git a/demos/dialog/modal-form.html b/demos/dialog/modal-form.html index a779494a4..b1d4e52cc 100644 --- a/demos/dialog/modal-form.html +++ b/demos/dialog/modal-form.html @@ -12,6 +12,7 @@ <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> <script src="../../ui/jquery.ui.resizable.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <script src="../../ui/jquery.ui.effect.js"></script> <link rel="stylesheet" href="../demos.css"> @@ -86,10 +87,10 @@ if ( bValid ) { $( "#users tbody" ).append( "<tr>" + - "<td>" + name.val() + "</td>" + - "<td>" + email.val() + "</td>" + + "<td>" + name.val() + "</td>" + + "<td>" + email.val() + "</td>" + "<td>" + password.val() + "</td>" + - "</tr>" ); + "</tr>" ); $( this ).dialog( "close" ); } }, diff --git a/demos/dialog/modal-message.html b/demos/dialog/modal-message.html index 60b7c3e15..19fc0e829 100644 --- a/demos/dialog/modal-message.html +++ b/demos/dialog/modal-message.html @@ -12,6 +12,7 @@ <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> <script src="../../ui/jquery.ui.resizable.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <link rel="stylesheet" href="../demos.css"> <script> diff --git a/demos/dialog/modal.html b/demos/dialog/modal.html index 886a3516c..a59358d53 100644 --- a/demos/dialog/modal.html +++ b/demos/dialog/modal.html @@ -11,6 +11,7 @@ <script src="../../ui/jquery.ui.draggable.js"></script> <script src="../../ui/jquery.ui.position.js"></script> <script src="../../ui/jquery.ui.resizable.js"></script> + <script src="../../ui/jquery.ui.button.js"></script> <script src="../../ui/jquery.ui.dialog.js"></script> <link rel="stylesheet" href="../demos.css"> <script> @@ -282,7 +282,7 @@ grunt.initConfig({ files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now // TODO except for all|index|test, try to include more as we go - return !( /(all|index|test|dialog|tabs|tooltip)\.html$/ ).test( file ); + return !( /(all|index|test|dialog|dialog_deprecated|tabs|tooltip)\.html$/ ).test( file ); }) }, lint: { diff --git a/tests/unit/all.html b/tests/unit/all.html index 7581a737b..25116846f 100644 --- a/tests/unit/all.html +++ b/tests/unit/all.html @@ -22,6 +22,7 @@ "core/core.html", "datepicker/datepicker.html", "dialog/dialog.html", + "dialog/dialog_deprecated.html", "draggable/draggable.html", "droppable/droppable.html", "effects/effects.html", diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index 8331c53d5..d3a25d2fc 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -5,8 +5,9 @@ module( "autocomplete: options" ); var data = [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl" ]; test( "appendTo", function() { - expect( 5 ); - var element = $( "#autocomplete" ).autocomplete(); + expect( 7 ); + var detached = $( "<div>" ), + element = $( "#autocomplete" ).autocomplete(); equal( element.autocomplete( "widget" ).parent()[0], document.body, "defaults to body" ); element.autocomplete( "destroy" ); @@ -26,6 +27,18 @@ test( "appendTo", function() { element.autocomplete().autocomplete( "option", "appendTo", "#ac-wrap1" ); equal( element.autocomplete( "widget" ).parent()[0], $( "#ac-wrap1" )[0], "modified after init" ); element.autocomplete( "destroy" ); + + element.autocomplete({ + appendTo: detached + }); + equal( element.autocomplete( "widget" ).parent()[0], detached[0], "detached jQuery object" ); + element.autocomplete( "destroy" ); + + element.autocomplete({ + appendTo: detached[0] + }); + equal( element.autocomplete( "widget" ).parent()[0], detached[0], "detached DOM element" ); + element.autocomplete( "destroy" ); }); function autoFocusTest( afValue, focusedLength ) { diff --git a/tests/unit/button/button.html b/tests/unit/button/button.html index 388209991..ebdc76470 100644 --- a/tests/unit/button/button.html +++ b/tests/unit/button/button.html @@ -68,6 +68,7 @@ </form> <input type="checkbox" id="check"><label for="check">Toggle</label> +<input type="checkbox" id="check2"><label for="check2">Checkbox</label> <div><input id="submit" type="submit" value="Label"></div> diff --git a/tests/unit/button/button_core.js b/tests/unit/button/button_core.js index f3c50d840..d53dedf90 100644 --- a/tests/unit/button/button_core.js +++ b/tests/unit/button/button_core.js @@ -88,4 +88,20 @@ test("buttonset (rtl)", function() { ok( set.children("label:eq(2)").is(".ui-button.ui-corner-left:not(.ui-corner-all)") ); }); +// TODO: simulated click events don't behave like real click events in IE +// remove this when simulate properly simulates this +// see http://yuilibrary.com/projects/yui2/ticket/2528826 fore more info +if ( !$.ui.ie || ( document.documentMode && document.documentMode > 8 ) ) { + test( "ensure checked and aria after single click on checkbox label button, see #5518", function() { + expect( 3 ); + + $("#check2").button().change( function() { + var lbl = $( this ).button("widget"); + ok( this.checked, "checked ok" ); + ok( lbl.attr("aria-pressed") === "true", "aria ok" ); + ok( lbl.hasClass("ui-state-active"), "ui-state-active ok" ); + }).button("widget").simulate("mousedown").simulate("click").simulate("mouseup"); + }); +} + })(jQuery); diff --git a/tests/unit/dialog/dialog.html b/tests/unit/dialog/dialog.html index cb74bb654..5413e7cc1 100644 --- a/tests/unit/dialog/dialog.html +++ b/tests/unit/dialog/dialog.html @@ -5,6 +5,9 @@ <title>jQuery UI Dialog Test Suite</title> <script src="../../jquery.js"></script> + <script> + $.uiBackCompat = false; + </script> <link rel="stylesheet" href="../../../external/qunit.css"> <script src="../../../external/qunit.js"></script> <script src="../../jquery.simulate.js"></script> @@ -19,6 +22,7 @@ "ui/jquery.ui.mouse.js", "ui/jquery.ui.draggable.js", "ui/jquery.ui.resizable.js", + "ui/jquery.ui.button.js", "ui/jquery.ui.dialog.js" ] }); @@ -44,6 +48,17 @@ <div id="qunit-fixture"> <div id="dialog1"></div> <div id="dialog2"></div> + <div id="form-dialog" title="Profile Information"> + <fieldset> + <legend>Please share some personal information</legend> + <label for="favorite-animal">Your favorite animal</label><input id="favorite-animal"> + <label for="favorite-color">Your favorite color</label><input id="favorite-color"> + </fieldset> + <div role="group" aria-describedby="section2"> + <p id="section2">Some more (optional) information</p> + <label for="favorite-food">Favorite food</label><input id="favorite-food"> + </div> + </div> </div> </body> </html> diff --git a/tests/unit/dialog/dialog_common.js b/tests/unit/dialog/dialog_common.js index 2c0e86b46..47fff1013 100644 --- a/tests/unit/dialog/dialog_common.js +++ b/tests/unit/dialog/dialog_common.js @@ -23,10 +23,20 @@ TestHelpers.commonWidgetTests( "dialog", { }, resizable: true, show: null, - title: '', + title: null, width: 300, // callbacks - create: null + beforeClose: null, + close: null, + create: null, + drag: null, + dragStart: null, + dragStop: null, + focus: null, + open: null, + resize: null, + resizeStart: null, + resizeStop: null } }); diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js index b36f6204f..9c0e80825 100644 --- a/tests/unit/dialog/dialog_core.js +++ b/tests/unit/dialog/dialog_core.js @@ -17,22 +17,18 @@ test("title id", function() { el.remove(); }); -test("ARIA", function() { - expect(4); +test( "ARIA", function() { + expect( 4 ); - var labelledBy, - el = $('<div></div>').dialog(); - - equal(el.dialog('widget').attr('role'), 'dialog', 'dialog role'); - - labelledBy = el.dialog('widget').attr('aria-labelledby'); - ok(labelledBy.length > 0, 'has aria-labelledby attribute'); - equal(el.dialog('widget').find('.ui-dialog-title').attr('id'), labelledBy, - 'proper aria-labelledby attribute'); - - equal(el.dialog('widget').find('.ui-dialog-titlebar-close').attr('role'), 'button', - 'close link role'); + var el = $( "<div></div>" ).dialog(), + wrapper = el.dialog( "widget" ); + equal( wrapper.attr( "role" ), "dialog", "dialog role" ); + equal( wrapper.attr( "aria-labelledby" ), wrapper.find( ".ui-dialog-title" ).attr( "id" ) ); + equal( wrapper.attr( "aria-describedby" ), el.attr( "id" ), "aria-describedby added" ); + el.remove(); + el = $( '<div><div aria-describedby="section2"><p id="section2">descriotion</p></div></div>' ).dialog(); + strictEqual( el.dialog( "widget" ).attr( "aria-describedby" ), undefined, "no aria-describedby added, as already present in markup" ); el.remove(); }); @@ -42,4 +38,59 @@ test("widget method", function() { deepEqual(dialog.parent()[0], dialog.dialog("widget")[0]); }); +test( "focus tabbable", function() { + expect( 5 ); + var el, + options = { + buttons: [{ + text: "Ok", + click: $.noop + }] + }; + + el = $( "<div><input><input autofocus></div>" ).dialog( options ); + equal( document.activeElement, el.find( "input" )[ 1 ], "1. first element inside the dialog matching [autofocus]" ); + el.remove(); + + // IE8 fails to focus the input, <body> ends up being the activeElement + // so wait for that stupid browser + stop(); + setTimeout(function() { + el = $( "<div><input><input></div>" ).dialog( options ); + equal( document.activeElement, el.find( "input" )[ 0 ], "2. tabbable element inside the content element" ); + el.remove(); + + el = $( "<div>text</div>" ).dialog( options ); + equal( document.activeElement, el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ], "3. tabbable element inside the buttonpane" ); + el.remove(); + + el = $( "<div>text</div>" ).dialog(); + equal( document.activeElement, el.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ], "4. the close button" ); + el.remove(); + + el = $( "<div>text</div>" ).dialog({ + autoOpen: false + }); + el.dialog( "widget" ).find( ".ui-dialog-titlebar-close" ).hide(); + el.dialog( "open" ); + equal( document.activeElement, el.parent()[ 0 ], "5. the dialog itself" ); + el.remove(); + + start(); + }, 13); +}); + +// #7960 +test( "resizable handles below modal overlays", function() { + expect( 1 ); + + var resizable = $( "<div>" ).resizable(), + dialog = $( "<div>" ).dialog({ modal: true }), + resizableZindex = parseInt( resizable.find( ".ui-resizable-handle" ).css( "zIndex" ), 10 ), + overlayZindex = parseInt( $( ".ui-widget-overlay" ).css( "zIndex" ), 10 ); + + ok( resizableZindex < overlayZindex, "Resizable handles have lower z-index than modal overlay" ); + dialog.dialog( "destroy" ); +}); + })(jQuery); diff --git a/tests/unit/dialog/dialog_deprecated.html b/tests/unit/dialog/dialog_deprecated.html new file mode 100644 index 000000000..2a876ac73 --- /dev/null +++ b/tests/unit/dialog/dialog_deprecated.html @@ -0,0 +1,62 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>jQuery UI Dialog Test Suite</title> + + <script src="../../jquery.js"></script> + <link rel="stylesheet" href="../../../external/qunit.css"> + <script src="../../../external/qunit.js"></script> + <script src="../../jquery.simulate.js"></script> + <script src="../testsuite.js"></script> + <script> + TestHelpers.loadResources({ + css: [ "ui.core", "ui.dialog" ], + js: [ + "ui/jquery.ui.core.js", + "ui/jquery.ui.widget.js", + "ui/jquery.ui.position.js", + "ui/jquery.ui.mouse.js", + "ui/jquery.ui.draggable.js", + "ui/jquery.ui.resizable.js", + "ui/jquery.ui.button.js", + "ui/jquery.ui.dialog.js" + ] + }); + </script> + + <script src="dialog_common.js"></script> + <script src="dialog_core.js"></script> + <script src="dialog_events.js"></script> + <script src="dialog_methods.js"></script> + <script src="dialog_options.js"></script> + <script src="dialog_test_helpers.js"></script> + <script src="dialog_tickets.js"></script> + <script src="dialog_deprecated.js"></script> + + <script src="../swarminject.js"></script> +</head> +<body> + +<h1 id="qunit-header">jQuery UI Dialog Test Suite</h1> +<h2 id="qunit-banner"></h2> +<div id="qunit-testrunner-toolbar"></div> +<h2 id="qunit-userAgent"></h2> +<ol id="qunit-tests"></ol> +<div id="qunit-fixture"> + <div id="dialog1"></div> + <div id="dialog2"></div> + <div id="form-dialog" title="Profile Information"> + <fieldset> + <legend>Please share some personal information</legend> + <label for="favorite-animal">Your favorite animal</label><input id="favorite-animal"> + <label for="favorite-color">Your favorite color</label><input id="favorite-color"> + </fieldset> + <div role="group" aria-describedby="section2"> + <p id="section2">Some more (optional) information</p> + <label for="favorite-food">Favorite food</label><input id="favorite-food"> + </div> + </div> +</div> +</body> +</html> diff --git a/tests/unit/dialog/dialog_deprecated.js b/tests/unit/dialog/dialog_deprecated.js new file mode 100644 index 000000000..fcbd22faa --- /dev/null +++ b/tests/unit/dialog/dialog_deprecated.js @@ -0,0 +1,53 @@ +module("dialog (deprecated): position option with string and array"); + +if ( !$.ui.ie ) { + test("position, right bottom on window w/array", function() { + expect( 2 ); + var el = $('<div></div>').dialog({ position: ["right", "bottom"] }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); + el.remove(); + }); + + test("position, right bottom on window", function() { + expect( 2 ); + var el = $('<div></div>').dialog({ position: "right bottom" }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); + el.remove(); + }); +} + +test("position, offset from top left w/array", function() { + expect( 2 ); + var el = $('<div></div>').dialog({ position: [10, 10] }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, 10 + $(window).scrollLeft(), 1); + closeEnough(offset.top, 10 + $(window).scrollTop(), 1); + el.remove(); +}); + +test("position, top on window", function() { + expect( 2 ); + var el = $('<div></div>').dialog({ position: "top" }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).scrollTop(), 1); + el.remove(); +}); + +test("position, left on window", function() { + expect( 2 ); + var el = $('<div></div>').dialog({ position: "left" }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, 0, 1); + closeEnough(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop(), 1); + el.remove(); +}); diff --git a/tests/unit/dialog/dialog_events.js b/tests/unit/dialog/dialog_events.js index ee7a8bcb3..cbeced0f8 100644 --- a/tests/unit/dialog/dialog_events.js +++ b/tests/unit/dialog/dialog_events.js @@ -39,6 +39,51 @@ test("open", function() { el.remove(); }); + +test( "focus", function() { + expect( 5 ); + var el, other; + el = $("#dialog1").dialog({ + autoOpen: false + }); + other = $("#dialog2").dialog({ + autoOpen: false + }); + + el.one( "dialogopen", function() { + ok( true, "open, just once" ); + }); + el.one( "dialogfocus", function() { + ok( true, "focus on open" ); + }); + other.dialog( "open" ); + + el.one( "dialogfocus", function() { + ok( true, "when opening and already open and wasn't on top" ); + }); + other.dialog( "open" ); + el.dialog( "open" ); + + el.one( "dialogfocus", function() { + ok( true, "when calling moveToTop and wasn't on top" ); + }); + other.dialog( "moveToTop" ); + el.dialog( "moveToTop" ); + + el.bind( "dialogfocus", function() { + ok( true, "when mousedown anywhere on the dialog and it wasn't on top" ); + }); + other.dialog( "moveToTop" ); + el.trigger( "mousedown" ); + + // triggers just once when already on top + el.dialog( "open" ); + el.dialog( "moveToTop" ); + el.trigger( "mousedown" ); + + el.add( other ).remove(); +}); + test("dragStart", function() { expect(9); @@ -280,4 +325,20 @@ test("beforeClose", function() { el.remove(); }); +// #8789 and #8838 +asyncTest("ensure dialog's container doesn't scroll on resize and focus", function() { + expect(2); + + var el = $('#dialog1').dialog(), + initialScroll = $(window).scrollTop(); + el.dialog('option', 'height', 600); + equal($(window).scrollTop(), initialScroll, "scroll hasn't moved after height change"); + setTimeout( function(){ + $(".ui-dialog-titlebar-close").simulate('mousedown'); + equal($(window).scrollTop(), initialScroll, "scroll hasn't moved after focus moved to dialog"); + el.dialog('destroy'); + start(); + }, 500); +}); + })(jQuery); diff --git a/tests/unit/dialog/dialog_methods.js b/tests/unit/dialog/dialog_methods.js index 7048a76a9..e5275c7a4 100644 --- a/tests/unit/dialog/dialog_methods.js +++ b/tests/unit/dialog/dialog_methods.js @@ -34,48 +34,25 @@ test("init", function() { }); test("destroy", function() { - expect( 4 ); - - $("<div></div>").appendTo('body').dialog().dialog("destroy").remove(); - ok(true, '.dialog("destroy") called on element'); - - $([]).dialog().dialog("destroy").remove(); - ok(true, '.dialog("destroy") called on empty collection'); - - $('<div></div>').dialog().dialog("destroy").remove(); - ok(true, '.dialog("destroy") called on disconnected DOMElement'); - - var expected = $('<div></div>').dialog(), - actual = expected.dialog('destroy'); - equal(actual, expected, 'destroy is chainable'); -}); - -test("enable", function() { - expect( 3 ); - - var el, - expected = $('<div></div>').dialog(), - actual = expected.dialog('enable'); - equal(actual, expected, 'enable is chainable'); - - el = $('<div></div>').dialog({ disabled: true }); - el.dialog('enable'); - equal(el.dialog('option', 'disabled'), false, 'enable method sets disabled option to false'); - ok(!el.dialog('widget').hasClass('ui-dialog-disabled'), 'enable method removes ui-dialog-disabled class from ui-dialog element'); + expect( 6 ); + domEqual( "#dialog1", function() { + var dialog = $( "#dialog1" ).dialog().dialog( "destroy" ); + equal( dialog.parent()[ 0 ], $( "#qunit-fixture" )[ 0 ] ); + equal( dialog.index(), 0 ); + }); + domEqual( "#form-dialog", function() { + var dialog = $( "#form-dialog" ).dialog().dialog( "destroy" ); + equal( dialog.parent()[ 0 ], $( "#qunit-fixture" )[ 0 ] ); + equal( dialog.index(), 2 ); + }); }); -test("disable", function() { - expect( 3 ); - - var el, - expected = $('<div></div>').dialog(), - actual = expected.dialog('disable'); - equal(actual, expected, 'disable is chainable'); - - el = $('<div></div>').dialog({ disabled: false }); - el.dialog('disable'); - equal(el.dialog('option', 'disabled'), true, 'disable method sets disabled option to true'); - ok(el.dialog('widget').hasClass('ui-dialog-disabled'), 'disable method adds ui-dialog-disabled class to ui-dialog element'); +test( "enable/disable disabled", function() { + expect( 2 ); + var el = $( "<div></div>" ).dialog(); + el.dialog( "disable" ); + equal(el.dialog( "option", "disabled" ), false, "disable method doesn't do anything" ); + ok( !el.dialog( "widget" ).hasClass( "ui-dialog-disabled" ), "disable method doesn't add ui-dialog-disabled class" ); }); test("close", function() { diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index 331230318..f01a1a2a8 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -35,7 +35,7 @@ test("buttons", function() { }, el = $('<div></div>').dialog({ buttons: buttons }); - btn = $("button", el.dialog('widget')); + btn = el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" ); equal(btn.length, 2, "number of buttons"); i = 0; @@ -61,7 +61,7 @@ test("buttons", function() { el.dialog("option", "buttons", newButtons); deepEqual(el.dialog("option", "buttons"), newButtons, '.dialog("option", "buttons", ...) setter'); - btn = $("button", el.dialog('widget')); + btn = el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" ); equal(btn.length, 1, "number of buttons after setter"); btn.trigger('click'); @@ -72,7 +72,7 @@ test("buttons", function() { }); el.dialog("option", "buttons", null); - btn = $("button", el.dialog('widget')); + btn = el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" ); equal(btn.length, 0, "all buttons have been removed"); equal(el.find(".ui-dialog-buttonset").length, 0, "buttonset has been removed"); equal(el.parent().hasClass('ui-dialog-buttons'), false, "dialog wrapper removes class about having buttons"); @@ -81,7 +81,7 @@ test("buttons", function() { }); test("buttons - advanced", function() { - expect(5); + expect( 7 ); var buttons, el = $("<div></div>").dialog({ @@ -92,16 +92,22 @@ test("buttons - advanced", function() { id: "my-button-id", click: function() { equal(this, el[0], "correct context"); - } + }, + icons: { + primary: "ui-icon-cancel" + }, + showText: false } ] }); - buttons = el.dialog('widget').find("button"); + buttons = el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" ); equal(buttons.length, 1, "correct number of buttons"); equal(buttons.attr("id"), "my-button-id", "correct id"); equal(buttons.text(), "a button", "correct label"); ok(buttons.hasClass("additional-class"), "additional classes added"); + deepEqual( buttons.button("option", "icons"), { primary: "ui-icon-cancel", secondary: null } ); + equal( buttons.button( "option", "text" ), false ); buttons.click(); el.remove(); @@ -148,7 +154,7 @@ test("closeText", function() { }); test("dialogClass", function() { - expect(4); + expect( 6 ); var el = $('<div></div>').dialog(); equal(el.dialog('widget').is(".foo"), false, 'dialogClass not specified. foo class added'); @@ -156,6 +162,9 @@ test("dialogClass", function() { el = $('<div></div>').dialog({ dialogClass: "foo" }); equal(el.dialog('widget').is(".foo"), true, 'dialogClass in init. foo class added'); + el.dialog( "option", "dialogClass", "foobar" ); + equal( el.dialog('widget').is(".foo"), false, "dialogClass changed, previous one was removed" ); + equal( el.dialog('widget').is(".foobar"), true, "dialogClass changed, new one was added" ); el.remove(); el = $('<div></div>').dialog({ dialogClass: "foo bar" }); @@ -289,49 +298,8 @@ test("position, default center on window", function() { el.remove(); }); -test("position, top on window", function() { - expect( 2 ); - var el = $('<div></div>').dialog({ position: "top" }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - closeEnough(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft(), 1); - closeEnough(offset.top, $(window).scrollTop(), 1); - el.remove(); -}); - -test("position, left on window", function() { - expect( 2 ); - var el = $('<div></div>').dialog({ position: "left" }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - closeEnough(offset.left, 0, 1); - closeEnough(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop(), 1); - el.remove(); -}); - // todo: figure out these fails in IE7 if ( !$.ui.ie ) { - - test("position, right bottom on window", function() { - expect( 2 ); - var el = $('<div></div>').dialog({ position: "right bottom" }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); - closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); - el.remove(); - }); - - test("position, right bottom on window w/array", function() { - expect( 2 ); - var el = $('<div></div>').dialog({ position: ["right", "bottom"] }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); - closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); - el.remove(); - }); - test("position, right bottom at right bottom via ui.position args", function() { expect( 2 ); var el = $('<div></div>').dialog({ @@ -347,19 +315,8 @@ if ( !$.ui.ie ) { closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); el.remove(); }); - } -test("position, offset from top left w/array", function() { - expect( 2 ); - var el = $('<div></div>').dialog({ position: [10, 10] }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - closeEnough(offset.left, 10 + $(window).scrollLeft(), 1); - closeEnough(offset.top, 10 + $(window).scrollTop(), 1); - el.remove(); -}); - test("position, at another element", function() { expect( 4 ); var parent = $('<div></div>').css({ @@ -415,37 +372,45 @@ test("resizable", function() { el.remove(); }); -test("title", function() { - expect(9); +test( "title", function() { + expect( 11 ); function titleText() { - return el.dialog('widget').find(".ui-dialog-title").html(); + return el.dialog('widget').find( ".ui-dialog-title" ).html(); } - var el = $('<div></div>').dialog(); + var el = $( '<div></div>' ).dialog(); // some browsers return a non-breaking space and some return " " // so we generate a non-breaking space for comparison - equal(titleText(), $( "<span> </span>" ).html(), "[default]"); - equal(el.dialog("option", "title"), "", "option not changed"); + equal( titleText(), $( "<span> </span>" ).html(), "[default]" ); + equal( el.dialog( "option", "title" ), null, "option not changed" ); el.remove(); - el = $('<div title="foo">').dialog(); - equal(titleText(), "foo", "title in element attribute"); - equal(el.dialog("option", "title"), "foo", "option updated from attribute"); + el = $( '<div title="foo">' ).dialog(); + equal( titleText(), "foo", "title in element attribute" ); + equal( el.dialog( "option", "title"), "foo", "option updated from attribute" ); el.remove(); - el = $('<div></div>').dialog({ title: 'foo' }); - equal(titleText(), "foo", "title in init options"); - equal(el.dialog("option", "title"), "foo", "opiton set from options hash"); + el = $( '<div></div>' ).dialog({ title: 'foo' }); + equal( titleText(), "foo", "title in init options" ); + equal( el.dialog("option", "title"), "foo", "opiton set from options hash" ); el.remove(); - el = $('<div title="foo">').dialog({ title: 'bar' }); - equal(titleText(), "bar", "title in init options should override title in element attribute"); - equal(el.dialog("option", "title"), "bar", "opiton set from options hash"); + el = $( '<div title="foo">' ).dialog({ title: 'bar' }); + equal( titleText(), "bar", "title in init options should override title in element attribute" ); + equal( el.dialog("option", "title"), "bar", "opiton set from options hash" ); el.remove(); - el = $('<div></div>').dialog().dialog('option', 'title', 'foo'); - equal(titleText(), 'foo', 'title after init'); + el = $( '<div></div>' ).dialog().dialog( 'option', 'title', 'foo' ); + equal( titleText(), 'foo', 'title after init' ); + el.remove(); + + // make sure attroperties are properly ignored - #5742 - .attr() might return a DOMElement + el = $( '<form><input name="title"></form>' ).dialog(); + // some browsers return a non-breaking space and some return " " + // so we get the text to normalize to the actual non-breaking space + equal( titleText(), $( "<span> </span>" ).html(), "[default]" ); + equal( el.dialog( "option", "title" ), null, "option not changed" ); el.remove(); }); diff --git a/tests/unit/dialog/dialog_tickets.js b/tests/unit/dialog/dialog_tickets.js index 3055c5fc1..655f1e445 100644 --- a/tests/unit/dialog/dialog_tickets.js +++ b/tests/unit/dialog/dialog_tickets.js @@ -71,24 +71,24 @@ test("#5184: isOpen in dialogclose event is true", function() { }); test("#5531: dialog width should be at least minWidth on creation", function () { - expect( 4 ); - var el = $('<div></div>').dialog({ - width: 200, - minWidth: 300 - }); - - equal(el.dialog('option', 'width'), 300, "width is minWidth"); - el.dialog('option', 'width', 200); - equal(el.dialog('option', 'width'), 300, "width unchanged when set to < minWidth"); - el.dialog('option', 'width', 320); - equal(el.dialog('option', 'width'), 320, "width changed if set to > minWidth"); - el.remove(); - - el = $('<div></div>').dialog({ - minWidth: 300 - }); - ok(el.dialog('option', 'width') >= 300, "width is at least 300"); - el.remove(); + expect( 4 ); + var el = $('<div></div>').dialog({ + width: 200, + minWidth: 300 + }); + + equal(el.dialog('option', 'width'), 300, "width is minWidth"); + el.dialog('option', 'width', 200); + equal(el.dialog('option', 'width'), 300, "width unchanged when set to < minWidth"); + el.dialog('option', 'width', 320); + equal(el.dialog('option', 'width'), 320, "width changed if set to > minWidth"); + el.remove(); + + el = $('<div></div>').dialog({ + minWidth: 300 + }); + ok(el.dialog('option', 'width') >= 300, "width is at least 300"); + el.remove(); }); @@ -108,20 +108,21 @@ test("#6137: dialog('open') causes form elements to reset on IE7", function() { }); test("#6645: Missing element not found check in overlay", function(){ - expect(2); - var d1 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true}), - d2 = $('<div title="dialog 2">Dialog 2</div>').dialog({modal: true, close: function(){ d2.remove(); }}); - - equal($.ui.dialog.overlay.instances.length, 2, 'two overlays created'); - d2.dialog('close'); - equal($.ui.dialog.overlay.instances.length, 1, 'one overlay remains after closing the 2nd overlay'); - d1.add(d2).remove(); + expect(2); + var d1 = $('<div title="dialog 1">Dialog 1</div>').dialog({modal: true}), + d2 = $('<div title="dialog 2">Dialog 2</div>').dialog({modal: true, close: function(){ d2.remove(); }}); + + equal($.ui.dialog.overlay.instances.length, 2, 'two overlays created'); + d2.dialog('close'); + equal($.ui.dialog.overlay.instances.length, 1, 'one overlay remains after closing the 2nd overlay'); + d1.add(d2).remove(); }); +// TODO merge this with the main destroy test test("#4980: Destroy should place element back in original DOM position", function(){ - expect( 2 ); - var container = $('<div id="container"><div id="modal">Content</div></div>'), - modal = container.find('#modal'); + expect( 2 ); + var container = $('<div id="container"><div id="modal">Content</div></div>'), + modal = container.find('#modal'); modal.dialog(); ok(!$.contains(container[0], modal[0]), 'dialog should move modal element to outside container element'); modal.dialog('destroy'); diff --git a/tests/unit/resizable/resizable_common.js b/tests/unit/resizable/resizable_common.js index 119f5bd0e..2c64f3cb1 100644 --- a/tests/unit/resizable/resizable_common.js +++ b/tests/unit/resizable/resizable_common.js @@ -19,7 +19,7 @@ TestHelpers.commonWidgetTests('resizable', { maxWidth: null, minHeight: 10, minWidth: 10, - zIndex: 1000, + zIndex: 90, // callbacks create: null diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index f6e89e84f..c78c42b58 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -235,10 +235,18 @@ test( "{ heightStyle: 'content' }", function() { }); test( "{ heightStyle: 'fill' }", function() { - expect( 2 ); + expect( 4 ); $( "#tabs8Wrapper" ).height( 500 ); var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); equalHeight( element, 485 ); + element.tabs( "destroy" ); + + element = $( "#tabs8" ).css({ + "border": "1px solid black", + "padding": "1px 0" + }); + element.tabs({ heightStyle: "fill" }); + equalHeight( element, 481 ); }); test( "{ heightStyle: 'fill' } with sibling", function() { diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index f9da27fb7..01ac25040 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -16,6 +16,20 @@ test( "content: default", function() { deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "anchortitle" ); }); +test( "content: default; HTML escaping", function() { + expect( 2 ); + var scriptText = "<script>$.ui.tooltip.hacked = true;</script>", + element = $( "#tooltipped1" ); + + $.ui.tooltip.hacked = false; + element.attr( "title", scriptText ) + .tooltip() + .tooltip( "open" ); + equal( $.ui.tooltip.hacked, false, "script did not execute" ); + deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), scriptText, + "correct tooltip text" ); +}); + test( "content: return string", function() { expect( 1 ); var element = $( "#tooltipped1" ).tooltip({ diff --git a/tests/visual/dialog/animated.html b/tests/visual/dialog/animated.html index d1f5acb10..07097fbfa 100644 --- a/tests/visual/dialog/animated.html +++ b/tests/visual/dialog/animated.html @@ -11,6 +11,7 @@ <script src="../../../ui/jquery.ui.draggable.js"></script> <script src="../../../ui/jquery.ui.position.js"></script> <script src="../../../ui/jquery.ui.resizable.js"></script> + <script src="../../../ui/jquery.ui.button.js"></script> <script src="../../../ui/jquery.ui.dialog.js"></script> <script src="../../../ui/jquery.ui.effect.js"></script> <script src="../../../ui/jquery.ui.effect-blind.js"></script> diff --git a/tests/visual/dialog/complex-dialogs.html b/tests/visual/dialog/complex-dialogs.html index 6399d8a4b..5cd9271ae 100644 --- a/tests/visual/dialog/complex-dialogs.html +++ b/tests/visual/dialog/complex-dialogs.html @@ -11,6 +11,7 @@ <script src="../../../ui/jquery.ui.draggable.js"></script> <script src="../../../ui/jquery.ui.position.js"></script> <script src="../../../ui/jquery.ui.resizable.js"></script> + <script src="../../../ui/jquery.ui.button.js"></script> <script src="../../../ui/jquery.ui.dialog.js"></script> <!-- stuff needed to make things complex --> @@ -23,9 +24,27 @@ $(function() { var dialog = $( "#dialog" ).dialog({ modal: true, - height: 300, - width: 500 - }), + width: 500, + buttons: [ + { + click: $.noop, + icons: { + primary: "ui-icon-check" + }, + text: "Ok" + }, + { + click: function() { + $( this ).dialog( "close" ); + }, + icons: { + primary: "ui-icon-cancel" + }, + text: "Cancel", + showText: false + } + ] + }).dialog("option", "height", 600), datepickerDialog = $( "#dialog-datepicker" ).dialog({ autoOpen: false, @@ -62,6 +81,11 @@ ] }); + $( "#destroy-dialog" ).click(function() { + dialog.dialog( "destroy" ).show(); + $( this ).remove(); + }); + $( document ).tooltip(); }); </script> @@ -71,18 +95,18 @@ <p>WHAT: A modal dialog opening another modal dialog (including a datepicker), opening a non-modal dialog (including an autocomplete with tooltip applied). A regular link on the page, outside of the dialogs.</p> <p>EXPECTED: As long as a modal dialog is open, focus stays within the dialogs. Both mouse and keyboard interactions are captured and restricted to the dialog. When the nested modal dialog is open, the first modal dialog can't be interacted with, until the nested dialog is closed. When the third dialog is open (not modal), switching between the two dialogs is possible, both can be interacted with.</p> -<a href="#">Outside link</a> <button id="open-dialog">Reopen dialog</button> <div id="dialog" title="Basic dialog"> <p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p> <p><button id="open-datepicker">Open another window with a datepicker.</button></p> + <p><button id="destroy-dialog">Self destruct</button></p> </div> <div id="dialog-datepicker" title="A dialog with a datepicker"> <p>Date: <input id="datepicker"></p> - <p><button id="open-autocomplete">Open another window with an autocomplete and a tooltip.</button></p> + <p><button id="open-autocomplete" autofocus>Open another window with an autocomplete and a tooltip.</button></p> </div> <div id="dialog-autocomplete"> @@ -90,5 +114,7 @@ <input id="autocomplete" title="Try typing something!"> </div> +<a href="#">Outside link</a> + </body> </html> diff --git a/tests/visual/dialog/form.html b/tests/visual/dialog/form.html index 867991911..ed70ec69b 100644 --- a/tests/visual/dialog/form.html +++ b/tests/visual/dialog/form.html @@ -11,6 +11,7 @@ <script src="../../../ui/jquery.ui.draggable.js"></script> <script src="../../../ui/jquery.ui.position.js"></script> <script src="../../../ui/jquery.ui.resizable.js"></script> + <script src="../../../ui/jquery.ui.button.js"></script> <script src="../../../ui/jquery.ui.dialog.js"></script> <script src="../../../ui/jquery.ui.effect.js"></script> <script src="../../../ui/jquery.ui.effect-blind.js"></script> diff --git a/tests/visual/dialog/performance.html b/tests/visual/dialog/performance.html index 937b9464f..8f63d6a69 100644 --- a/tests/visual/dialog/performance.html +++ b/tests/visual/dialog/performance.html @@ -11,6 +11,7 @@ <script src="../../../ui/jquery.ui.mouse.js"></script> <script src="../../../ui/jquery.ui.draggable.js"></script> <script src="../../../ui/jquery.ui.resizable.js"></script> + <script src="../../../ui/jquery.ui.button.js"></script> <script src="../../../ui/jquery.ui.dialog.js"></script> <script> $(function() { diff --git a/themes/base/jquery.ui.button.css b/themes/base/jquery.ui.button.css index b540983f2..5588eb42c 100644 --- a/themes/base/jquery.ui.button.css +++ b/themes/base/jquery.ui.button.css @@ -42,7 +42,7 @@ button.ui-button-icons-only { /* button text element */ .ui-button .ui-button-text { - display: block; + display: inline-block; line-height: 1.4; } .ui-button-text-only .ui-button-text { @@ -94,10 +94,6 @@ input.ui-button { .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} /* button sets */ .ui-buttonset { diff --git a/themes/base/jquery.ui.datepicker.css b/themes/base/jquery.ui.datepicker.css index 5ed7dfa4c..2c49361e0 100644 --- a/themes/base/jquery.ui.datepicker.css +++ b/themes/base/jquery.ui.datepicker.css @@ -15,7 +15,7 @@ } .ui-datepicker .ui-datepicker-header { position: relative; - padding:.2em 0; + padding: .2em 0; } .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { @@ -128,9 +128,7 @@ .ui-datepicker-multi-4 .ui-datepicker-group { width: 25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { - border-left-width: 0; -} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width: 0; } @@ -140,7 +138,7 @@ .ui-datepicker-row-break { clear: both; width: 100%; - font-size: 0em; + font-size: 0; } /* RTL support */ @@ -169,16 +167,11 @@ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { - float:right; -} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, .ui-datepicker-rtl .ui-datepicker-group { float: right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width: 0; border-left-width: 1px; diff --git a/themes/base/jquery.ui.dialog.css b/themes/base/jquery.ui.dialog.css index f1b25c104..d278d9649 100644 --- a/themes/base/jquery.ui.dialog.css +++ b/themes/base/jquery.ui.dialog.css @@ -29,18 +29,10 @@ position: absolute; right: .3em; top: 50%; - width: 19px; + width: 21px; margin: -10px 0 0 0; padding: 1px; - height: 18px; -} -.ui-dialog .ui-dialog-titlebar-close span { - display: block; - margin: 1px; -} -.ui-dialog .ui-dialog-titlebar-close:hover, -.ui-dialog .ui-dialog-titlebar-close:focus { - padding: 0; + height: 20px; } .ui-dialog .ui-dialog-content { position: relative; diff --git a/themes/base/jquery.ui.progressbar.css b/themes/base/jquery.ui.progressbar.css index 5aba50cdf..349cc6d72 100644 --- a/themes/base/jquery.ui.progressbar.css +++ b/themes/base/jquery.ui.progressbar.css @@ -15,7 +15,7 @@ } .ui-progressbar .ui-progressbar-value { margin: -1px; - height:100%; + height: 100%; } .ui-progressbar .ui-progressbar-value .ui-progressbar-overlay { background: url("images/animated-overlay.gif"); diff --git a/themes/base/jquery.ui.theme.css b/themes/base/jquery.ui.theme.css index 89f03aa86..6388885c2 100644 --- a/themes/base/jquery.ui.theme.css +++ b/themes/base/jquery.ui.theme.css @@ -41,6 +41,7 @@ background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; + zoom: 1; } .ui-widget-header a { color: #222222/*{fcHeader}*/; } @@ -154,9 +155,9 @@ .ui-icon { width: 16px; height: 16px; - background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; background-position: 16px 16px; } +.ui-icon, .ui-widget-content .ui-icon { background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } @@ -367,36 +368,24 @@ .ui-corner-top, .ui-corner-left, .ui-corner-tl { - -moz-border-radius-topleft: 4px/*{cornerRadius}*/; - -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; - -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { - -moz-border-radius-topright: 4px/*{cornerRadius}*/; - -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; - -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { - -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; - -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; - -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { - -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; - -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; - -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } @@ -412,8 +401,5 @@ background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; /* no space between ".3;" and "filter" because themeRoller looks back to the first space for replacement */ opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; - -moz-border-radius: 8px/*{cornerRadiusShadow}*/; - -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; - -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index f2a7089c4..5edb84d44 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -181,7 +181,7 @@ $.widget( "ui.autocomplete", { this._initSource(); this.menu = $( "<ul>" ) .addClass( "ui-autocomplete" ) - .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] ) + .appendTo( this._appendTo() ) .menu({ // custom key handling for now input: $(), @@ -320,6 +320,14 @@ $.widget( "ui.autocomplete", { } }, + _appendTo: function() { + var element = this.options.appendTo; + if ( element && (element.jquery || element.nodeType) ) { + return $( element ); + } + return this.document.find( element || "body" ).eq( 0 ); + }, + _isMultiLine: function() { // Textareas are always multi-line if ( this.element.is( "textarea" ) ) { diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index d6eed67dc..1108bd50c 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -147,8 +147,6 @@ $.widget( "ui.button", { if ( options.disabled || clickDragged ) { return false; } - $( this ).toggleClass( "ui-state-active" ); - that.buttonElement.attr( "aria-pressed", that.element[0].checked ); }); } else if ( this.type === "radio" ) { this.buttonElement.bind( "click" + this.eventNamespace, function() { diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 823934e05..9f480bf38 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -13,7 +13,6 @@ */ (function( $, undefined ) { -/*jshint evil: true */ $.extend($.ui, { datepicker: { version: "@VERSION" } }); var PROP_NAME = 'datepicker', @@ -139,20 +138,7 @@ $.extend(Datepicker.prototype, { * @param settings object - the new settings to use for this date picker instance (anonymous) */ _attachDatepicker: function(target, settings) { - // check for settings on the control itself - in namespace 'date:' - var attrName, attrValue, nodeName, inline, inst, - inlineSettings = null; - for (attrName in this._defaults) { - attrValue = target.getAttribute('date:' + attrName); - if (attrValue) { - inlineSettings = inlineSettings || {}; - try { - inlineSettings[attrName] = eval(attrValue); - } catch (err) { - inlineSettings[attrName] = attrValue; - } - } - } + var nodeName, inline, inst; nodeName = target.nodeName.toLowerCase(); inline = (nodeName === 'div' || nodeName === 'span'); if (!target.id) { @@ -160,7 +146,7 @@ $.extend(Datepicker.prototype, { target.id = 'dp' + this.uuid; } inst = this._newInst($(target), inline); - inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + inst.settings = $.extend({}, settings || {}); if (nodeName === 'input') { this._connectDatepicker(target, inst); } else if (inline) { diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 07c5c7cb6..808d31d5b 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -67,127 +67,49 @@ $.widget("ui.dialog", { }, resizable: true, show: null, - title: "", - width: 300 + title: null, + width: 300, + + // callbacks + beforeClose: null, + close: null, + drag: null, + dragStart: null, + dragStop: null, + focus: null, + open: null, + resize: null, + resizeStart: null, + resizeStop: null }, _create: function() { this.originalTitle = this.element.attr( "title" ); - // #5742 - .attr() might return a DOMElement - if ( typeof this.originalTitle !== "string" ) { - this.originalTitle = ""; - } + this.options.title = this.options.title || this.originalTitle; this.oldPosition = { parent: this.element.parent(), index: this.element.parent().children().index( this.element ) }; - this.options.title = this.options.title || this.originalTitle; - var that = this, - options = this.options, - title = options.title || " ", - uiDialog, - uiDialogTitlebar, - uiDialogTitlebarClose, - uiDialogTitle, - uiDialogButtonPane; + this._createWrapper(); - uiDialog = ( this.uiDialog = $( "<div>" ) ) - .addClass( uiDialogClasses + options.dialogClass ) - .hide() - // setting tabIndex makes the div focusable - .attr( "tabIndex", -1) - .keydown(function( event ) { - if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE ) { - that.close( event ); - event.preventDefault(); - } - }) - .mousedown(function( event ) { - that.moveToTop( event ); - }) - .appendTo( this.document[ 0 ].body ); - - this.element - .show() - .removeAttr( "title" ) - .addClass( "ui-dialog-content ui-widget-content" ) - .appendTo( uiDialog ); - - uiDialogTitlebar = ( this.uiDialogTitlebar = $( "<div>" ) ) - .addClass( "ui-dialog-titlebar ui-widget-header " + - "ui-corner-all ui-helper-clearfix" ) - .bind( "mousedown", function() { - // Dialog isn't getting focus when dragging (#8063) - uiDialog.focus(); - }) - .prependTo( uiDialog ); - - uiDialogTitlebarClose = $( "<a href='#'></a>" ) - .addClass( "ui-dialog-titlebar-close ui-corner-all" ) - .attr( "role", "button" ) - .click(function( event ) { - event.preventDefault(); - that.close( event ); - }) - .appendTo( uiDialogTitlebar ); - - ( this.uiDialogTitlebarCloseText = $( "<span>" ) ) - .addClass( "ui-icon ui-icon-closethick" ) - .text( options.closeText ) - .appendTo( uiDialogTitlebarClose ); - - uiDialogTitle = $( "<span>" ) - .uniqueId() - .addClass( "ui-dialog-title" ) - .html( title ) - .prependTo( uiDialogTitlebar ); - - uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - - ( this.uiButtonSet = $( "<div>" ) ) - .addClass( "ui-dialog-buttonset" ) - .appendTo( uiDialogButtonPane ); - - uiDialog.attr({ - role: "dialog", - "aria-labelledby": uiDialogTitle.attr( "id" ) - }); + this.element + .show() + .removeAttr( "title" ) + .addClass( "ui-dialog-content ui-widget-content" ) + .appendTo( this.uiDialog ); - uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); - this._hoverable( uiDialogTitlebarClose ); - this._focusable( uiDialogTitlebarClose ); + this._createTitlebar(); + this._createButtonPane(); - if ( options.draggable && $.fn.draggable ) { + if ( this.options.draggable && $.fn.draggable ) { this._makeDraggable(); } - if ( options.resizable && $.fn.resizable ) { + if ( this.options.resizable && $.fn.resizable ) { this._makeResizable(); } - this._createButtons( options.buttons ); this._isOpen = false; - - // prevent tabbing out of dialogs - this._on( uiDialog, { keydown: function( event ) { - if ( event.keyCode !== $.ui.keyCode.TAB ) { - return; - } - - var tabbables = $( ":tabbable", uiDialog ), - first = tabbables.filter( ":first" ), - last = tabbables.filter( ":last" ); - - if ( ( event.target === last[ 0 ] || event.target === uiDialog[ 0 ] ) && !event.shiftKey ) { - first.focus( 1 ); - return false; - } else if ( ( event.target === first[ 0 ] || event.target === uiDialog[ 0 ] ) && event.shiftKey ) { - last.focus( 1 ); - return false; - } - }}); }, _init: function() { @@ -200,14 +122,15 @@ $.widget("ui.dialog", { var next, oldPosition = this.oldPosition; - if ( this.overlay ) { - this.overlay.destroy(); - } - this.uiDialog.hide(); + this._destroyOverlay(); + this.element + .removeUniqueId() .removeClass( "ui-dialog-content ui-widget-content" ) .hide() - .appendTo( "body" ); + // without detaching first, the following becomes really slow + .detach(); + this.uiDialog.remove(); if ( this.originalTitle ) { @@ -227,6 +150,9 @@ $.widget("ui.dialog", { return this.uiDialog; }, + disable: $.noop, + enable: $.noop, + close: function( event ) { var that = this; @@ -234,15 +160,13 @@ $.widget("ui.dialog", { return; } - if ( false === this._trigger( "beforeClose", event ) ) { + if ( this._trigger( "beforeClose", event ) === false ) { return; } this._isOpen = false; - if ( this.overlay ) { - this.overlay.destroy(); - } + this._destroyOverlay(); if ( !this.opener.filter( ":focusable" ).focus().length ) { // Hiding a focused element doesn't trigger blur in WebKit @@ -260,40 +184,35 @@ $.widget("ui.dialog", { return this._isOpen; }, - moveToTop: function( event, silent ) { - var moved = this.uiDialog.nextAll( ":visible" ).insertBefore( this.uiDialog ); - if ( !silent && moved.length ) { + moveToTop: function() { + this._moveToTop(); + }, + + _moveToTop: function( event, silent ) { + var moved = !!this.uiDialog.nextAll( ":visible" ).insertBefore( this.uiDialog ).length; + if ( !silent && moved ) { this._trigger( "focus", event ); } + return moved; }, open: function() { if ( this._isOpen ) { + if ( this._moveToTop() ) { + this._focusTabbable(); + } return; } - var hasFocus, - options = this.options, - uiDialog = this.uiDialog; - this.opener = $( this.document[ 0 ].activeElement ); this._size(); - this._position( options.position ); - this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null; - this.moveToTop( null, true ); - this._show( uiDialog, options.show ); - - // set focus to the first tabbable element in the content area or the first button - // if there are no tabbable elements, set focus on the dialog itself - hasFocus = this.element.find( ":tabbable" ); - if ( !hasFocus.length ) { - hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); - if ( !hasFocus.length ) { - hasFocus = uiDialog; - } - } - hasFocus.eq( 0 ).focus(); + this._position(); + this._createOverlay(); + this._moveToTop( null, true ); + this._show( this.uiDialog, this.options.show ); + + this._focusTabbable(); this._isOpen = true; this._trigger( "open" ); @@ -302,13 +221,36 @@ $.widget("ui.dialog", { return this; }, + _focusTabbable: function() { + // set focus to the first match: + // 1. first element inside the dialog matching [autofocus] + // 2. tabbable element inside the content element + // 3. tabbable element inside the buttonpane + // 4. the close button + // 5. the dialog itself + var hasFocus = this.element.find( "[autofocus]" ); + if ( !hasFocus.length ) { + hasFocus = this.element.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialog; + } + } + } + } + hasFocus.eq( 0 ).focus(); + }, + _keepFocus: function( event ) { function checkFocus() { var activeElement = this.document[ 0 ].activeElement, isActive = this.uiDialog[ 0 ] === activeElement || $.contains( this.uiDialog[ 0 ], activeElement ); if ( !isActive ) { - this.uiDialog.focus(); + this._focusTabbable(); } } event.preventDefault(); @@ -319,22 +261,134 @@ $.widget("ui.dialog", { this._delay( checkFocus ); }, - _createButtons: function( buttons ) { + _createWrapper: function() { + this.uiDialog = $( "<div>" ) + .addClass( uiDialogClasses + this.options.dialogClass ) + .hide() + .attr({ + // setting tabIndex makes the div focusable + tabIndex: -1, + role: "dialog" + }) + .appendTo( this.document[ 0 ].body ); + + this._on( this.uiDialog, { + keydown: function( event ) { + if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + event.preventDefault(); + this.close( event ); + return; + } + + // prevent tabbing out of dialogs + if ( event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + var tabbables = this.uiDialog.find( ":tabbable" ), + first = tabbables.filter( ":first" ), + last = tabbables.filter( ":last" ); + + if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) && !event.shiftKey ) { + first.focus( 1 ); + return false; + } else if ( ( event.target === first[ 0 ] || event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) { + last.focus( 1 ); + return false; + } + }, + mousedown: function( event ) { + if ( this._moveToTop( event ) ) { + this._focusTabbable(); + } + } + }); + + // We assume that any existing aria-describedby attribute means + // that the dialog content is marked up properly + // otherwise we brute force the content as the description + if ( !this.element.find( "[aria-describedby]" ).length ) { + this.uiDialog.attr({ + "aria-describedby": this.element.uniqueId().attr( "id" ) + }); + } + }, + + _createTitlebar: function() { + var uiDialogTitle; + + this.uiDialogTitlebar = $( "<div>" ) + .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) + .prependTo( this.uiDialog ); + this._on( this.uiDialogTitlebar, { + mousedown: function( event ) { + // Don't prevent click on close button (#8838) + // Focusing a dialog that is partially scrolled out of view + // causes the browser to scroll it into view, preventing the click event + if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { + // Dialog isn't getting focus when dragging (#8063) + this.uiDialog.focus(); + } + } + }); + + this.uiDialogTitlebarClose = $( "<button></button>" ) + .button({ + label: this.options.closeText, + icons: { + primary: "ui-icon-closethick" + }, + text: false + }) + .addClass( "ui-dialog-titlebar-close" ) + .appendTo( this.uiDialogTitlebar ); + this._on( this.uiDialogTitlebarClose, { + "click": function( event ) { + event.preventDefault(); + this.close( event ); + } + }); + + uiDialogTitle = $( "<span>" ) + .uniqueId() + .addClass( "ui-dialog-title" ) + .prependTo( this.uiDialogTitlebar ); + this._title( uiDialogTitle ); + + this.uiDialog.attr({ + "aria-labelledby": uiDialogTitle.attr( "id" ) + }); + }, + + _title: function( title ) { + if ( !this.options.title ) { + title.html( " " ); + } + title.text( this.options.title ); + }, + + _createButtonPane: function() { + var uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); + + this.uiButtonSet = $( "<div>" ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + this._createButtons(); + }, + + _createButtons: function() { var that = this, - hasButtons = false; + buttons = this.options.buttons; // if we already have a button pane, remove it this.uiDialogButtonPane.remove(); this.uiButtonSet.empty(); - if ( typeof buttons === "object" && buttons !== null ) { - $.each( buttons, function() { - return !(hasButtons = true); - }); - } - if ( hasButtons ) { + if ( !$.isEmptyObject( buttons ) ) { $.each( buttons, function( name, props ) { - var button, click; + var click, buttonOptions; props = $.isFunction( props ) ? { click: props, text: name } : props; @@ -345,11 +399,15 @@ $.widget("ui.dialog", { props.click = function() { click.apply( that.element[0], arguments ); }; - button = $( "<button></button>", props ) + buttonOptions = { + icons: props.icons, + text: props.showText + }; + delete props.icons; + delete props.showText; + $( "<button></button>", props ) + .button( buttonOptions ) .appendTo( that.uiButtonSet ); - if ( $.fn.button ) { - button.button(); - } }); this.uiDialog.addClass( "ui-dialog-buttons" ); this.uiDialogButtonPane.appendTo( this.uiDialog ); @@ -393,10 +451,10 @@ $.widget("ui.dialog", { }); }, - _makeResizable: function( handles ) { - handles = (handles === undefined ? this.options.resizable : handles); + _makeResizable: function() { var that = this, options = this.options, + handles = options.resizable, // .ui-resizable has position: relative defined in the stylesheet // but dialogs have to use absolute or fixed positioning position = this.uiDialog.css( "position" ), @@ -451,47 +509,13 @@ $.widget("ui.dialog", { } }, - _position: function( position ) { - var myAt = [], - offset = [ 0, 0 ], - isVisible; - - if ( position ) { - // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( - // if (typeof position == 'string' || $.isArray(position)) { - // myAt = $.isArray(position) ? position : position.split(' '); - - if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { - myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; - if ( myAt.length === 1 ) { - myAt[ 1 ] = myAt[ 0 ]; - } - - $.each( [ "left", "top" ], function( i, offsetPosition ) { - if ( +myAt[ i ] === myAt[ i ] ) { - offset[ i ] = myAt[ i ]; - myAt[ i ] = offsetPosition; - } - }); - - position = { - my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + - myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), - at: myAt.join( " " ) - }; - } - - position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); - } else { - position = $.ui.dialog.prototype.options.position; - } - + _position: function() { // need to show the dialog to get the actual offset in the position plugin - isVisible = this.uiDialog.is( ":visible" ); + var isVisible = this.uiDialog.is( ":visible" ); if ( !isVisible ) { this.uiDialog.show(); } - this.uiDialog.position( position ); + this.uiDialog.position( this.options.position ); if ( !isVisible ) { this.uiDialog.hide(); } @@ -515,6 +539,7 @@ $.widget("ui.dialog", { if ( resize ) { this._size(); + this._position(); } if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", resizableOptions ); @@ -525,64 +550,65 @@ $.widget("ui.dialog", { var isDraggable, isResizable, uiDialog = this.uiDialog; - switch ( key ) { - case "buttons": - this._createButtons( value ); - break; - case "closeText": + if ( key === "dialogClass" ) { + uiDialog + .removeClass( this.options.dialogClass ) + .addClass( value ); + } + + if ( key === "disabled" ) { + return; + } + + this._super( key, value ); + + if ( key === "buttons" ) { + this._createButtons(); + } + + if ( key === "closeText" ) { + this.uiDialogTitlebarClose.button({ // ensure that we always pass a string - this.uiDialogTitlebarCloseText.text( "" + value ); - break; - case "dialogClass": - uiDialog - .removeClass( this.options.dialogClass ) - .addClass( uiDialogClasses + value ); - break; - case "disabled": - if ( value ) { - uiDialog.addClass( "ui-dialog-disabled" ); - } else { - uiDialog.removeClass( "ui-dialog-disabled" ); - } - break; - case "draggable": - isDraggable = uiDialog.is( ":data(ui-draggable)" ); - if ( isDraggable && !value ) { - uiDialog.draggable( "destroy" ); - } + label: "" + value + }); + } - if ( !isDraggable && value ) { - this._makeDraggable(); - } - break; - case "position": - this._position( value ); - break; - case "resizable": - // currently resizable, becoming non-resizable - isResizable = uiDialog.is( ":data(ui-resizable)" ); - if ( isResizable && !value ) { - uiDialog.resizable( "destroy" ); - } + if ( key === "draggable" ) { + isDraggable = uiDialog.is( ":data(ui-draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } - // currently resizable, changing handles - if ( isResizable && typeof value === "string" ) { - uiDialog.resizable( "option", "handles", value ); - } + if ( !isDraggable && value ) { + this._makeDraggable(); + } + } - // currently non-resizable, becoming resizable - if ( !isResizable && value !== false ) { - this._makeResizable( value ); - } - break; - case "title": - // convert whatever was passed in o a string, for html() to not throw up - $( ".ui-dialog-title", this.uiDialogTitlebar ) - .html( "" + ( value || " " ) ); - break; + if ( key === "position" ) { + this._position(); } - this._super( key, value ); + if ( key === "resizable" ) { + // currently resizable, becoming non-resizable + isResizable = uiDialog.is( ":data(ui-resizable)" ); + if ( isResizable && !value ) { + uiDialog.resizable( "destroy" ); + } + + // currently resizable, changing handles + if ( isResizable && typeof value === "string" ) { + uiDialog.resizable( "option", "handles", value ); + } + + // currently non-resizable, becoming resizable + if ( !isResizable && value !== false ) { + this._makeResizable(); + } + } + + if ( key === "title" ) { + this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); + } }, _size: function() { @@ -624,63 +650,112 @@ $.widget("ui.dialog", { if (this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); } - } -}); - -$.extend($.ui.dialog, { - uuid: 0, - - getTitleId: function($el) { - var id = $el.attr( "id" ); - if ( !id ) { - this.uuid += 1; - id = this.uuid; - } - return "ui-dialog-title-" + id; }, - overlay: function( dialog ) { - this.$el = $.ui.dialog.overlay.create( dialog ); - } -}); - -$.extend( $.ui.dialog.overlay, { - instances: [], - // reuse old instances due to IE memory leak with alpha transparency (see #5185) - oldInstances: [], - create: function( dialog ) { + _createOverlay: function() { + if ( !this.options.modal ) { + return; + } + if ( $.ui.dialog.overlay.instances.length === 0 ) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ( $.ui.dialog.overlay.instances.length ) { + $( document ).bind( "focusin.dialog-overlay", function( event ) { + if ( !$( event.target ).closest( ".ui-dialog").length ) { + event.preventDefault(); + $( ".ui-dialog:visible:last .ui-dialog-content" ).data( "ui-dialog" )._focusTabbable(); + } + }); + } + }, 1 ); + } - var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay ui-front" ) ); + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + var $el = this.overlay = ( $.ui.dialog.overlay.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay ui-front" ) ); $el.appendTo( document.body ); - $el.bind( "mousedown", function( event ) { - dialog._keepFocus( event ); + this._on( $el, { + mousedown: "_keepFocus" }); - this.instances.push( $el ); - return $el; + $.ui.dialog.overlay.instances.push( $el ); }, - destroy: function( $el ) { - var indexOf = $.inArray( $el, this.instances ); + _destroyOverlay: function() { + if ( !this.options.modal ) { + return; + } + var indexOf = $.inArray( this.overlay, $.ui.dialog.overlay.instances ); if ( indexOf !== -1 ) { - this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] ); + $.ui.dialog.overlay.oldInstances.push( $.ui.dialog.overlay.instances.splice( indexOf, 1 )[ 0 ] ); } - if ( this.instances.length === 0 ) { + if ( $.ui.dialog.overlay.instances.length === 0 ) { $( [ document, window ] ).unbind( ".dialog-overlay" ); } - $el.remove(); + this.overlay.remove(); } }); -$.extend( $.ui.dialog.overlay.prototype, { - destroy: function() { - $.ui.dialog.overlay.destroy( this.$el ); - } -}); +$.ui.dialog.overlay = { + instances: [], + oldInstances: [] +}; + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // position option with array notation + // just override with old implementation + $.widget( "ui.dialog", $.ui.dialog, { + _position: function() { + var position = this.options.position, + myAt = [], + offset = [ 0, 0 ], + isVisible; + + if ( position ) { + if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { + myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; + if ( myAt.length === 1 ) { + myAt[ 1 ] = myAt[ 0 ]; + } + + $.each( [ "left", "top" ], function( i, offsetPosition ) { + if ( +myAt[ i ] === myAt[ i ] ) { + offset[ i ] = myAt[ i ]; + myAt[ i ] = offsetPosition; + } + }); + + position = { + my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + + myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), + at: myAt.join( " " ) + }; + } + + position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is( ":visible" ); + if ( !isVisible ) { + this.uiDialog.show(); + } + this.uiDialog.position( position ); + if ( !isVisible ) { + this.uiDialog.hide(); + } + } + }); +} }( jQuery ) ); diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index fee3359bf..d8d32e932 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -17,24 +17,24 @@ $.effects = { }; /*! - * jQuery Color Animations v2.0.0 - * http://jquery.com/ + * jQuery Color Animations v2.1.1 + * https://github.com/jquery/jquery-color * * Copyright 2012 jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license * - * Date: Mon Aug 13 13:41:02 2012 -0500 + * Date: Sun Oct 28 15:08:06 2012 -0400 */ (function( jQuery, undefined ) { - var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "), + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", // plusequals test for += 100 -= 100 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, // a set of RE's that can match strings and generate color tuples. stringParsers = [{ - re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, parse: function( execResult ) { return [ execResult[ 1 ], @@ -44,7 +44,7 @@ $.effects = { ]; } }, { - re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, parse: function( execResult ) { return [ execResult[ 1 ] * 2.55, @@ -74,7 +74,7 @@ $.effects = { ]; } }, { - re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, space: "hsla", parse: function( execResult ) { return [ @@ -291,7 +291,7 @@ color.fn = jQuery.extend( color.prototype, { }); // everything defined but alpha? - if ( inst[ cache ] && $.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { // use the default of 1 inst[ cache ][ 3 ] = 1; if ( space.from ) { @@ -479,8 +479,10 @@ spaces.hsla.to = function ( rgba ) { h = ( 60 * ( r - g ) / diff ) + 240; } - if ( l === 0 || l === 1 ) { - s = l; + // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% + // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) + if ( diff === 0 ) { + s = 0; } else if ( l <= 0.5 ) { s = diff / add; } else { @@ -584,51 +586,58 @@ each( spaces, function( spaceName, space ) { }); }); -// add .fx.step functions -each( stepHooks, function( i, hook ) { - jQuery.cssHooks[ hook ] = { - set: function( elem, value ) { - var parsed, curElem, - backgroundColor = ""; - - if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) { - value = color( parsed || value ); - if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { - curElem = hook === "backgroundColor" ? elem.parentNode : elem; - while ( - (backgroundColor === "" || backgroundColor === "transparent") && - curElem && curElem.style - ) { - try { - backgroundColor = jQuery.css( curElem, "backgroundColor" ); - curElem = curElem.parentNode; - } catch ( e ) { +// add cssHook and .fx.step function for each named hook. +// accept a space separated string of properties +color.hook = function( hook ) { + var hooks = hook.split( " " ); + each( hooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + (backgroundColor === "" || backgroundColor === "transparent") && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); } - value = value.blend( backgroundColor && backgroundColor !== "transparent" ? - backgroundColor : - "_default" ); + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch( e ) { + // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' } - - value = value.toRgbaString(); } - try { - elem.style[ hook ] = value; - } catch( error ) { - // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; } - } - }; - jQuery.fx.step[ hook ] = function( fx ) { - if ( !fx.colorInit ) { - fx.start = color( fx.elem, hook ); - fx.end = color( fx.end ); - fx.colorInit = true; - } - jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); - }; -}); + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + }); + +}; + +color.hook( stepHooks ); jQuery.cssHooks.borderColor = { expand: function( value ) { @@ -672,7 +681,6 @@ colors = jQuery.Color.names = { })( jQuery ); - /******************************************************************************/ /****************************** CLASS ANIMATIONS ******************************/ /******************************************************************************/ @@ -788,7 +796,7 @@ $.effects.animateClass = function( value, duration, easing, callback ) { allAnimations = allAnimations.map(function() { var styleInfo = this, dfd = $.Deferred(), - opts = jQuery.extend({}, o, { + opts = $.extend({}, o, { queue: false, complete: function() { dfd.resolve( styleInfo ); diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index 41f3c03c0..4a019336e 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -42,7 +42,8 @@ $.widget("ui.resizable", $.ui.mouse, { maxWidth: null, minHeight: 10, minWidth: 10, - zIndex: 1000 + // See #7960 + zIndex: 90 }, _create: function() { diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 0b6480123..dcb0c2768 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -497,6 +497,8 @@ $.widget( "ui.tabs", { if ( heightStyle === "fill" ) { maxHeight = parent.height(); + maxHeight -= this.element.outerHeight() - this.element.height(); + this.element.siblings( ":visible" ).each(function() { var elem = $( this ), position = elem.css( "position" ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 2ccd61f46..ab8d5173c 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -46,7 +46,9 @@ $.widget( "ui.tooltip", { version: "@VERSION", options: { content: function() { - return $( this ).attr( "title" ); + var title = $( this ).attr( "title" ); + // Escape title, since we're going from an attribute to raw HTML + return $( "<a>" ).text( title ).html(); }, hide: true, // Disabled elements have inconsistent behavior across browsers (#8661) |