diff options
50 files changed, 2081 insertions, 1057 deletions
diff --git a/demos/menubar/default.html b/demos/menubar/default.html index 79662bd9f..57a3209ce 100644 --- a/demos/menubar/default.html +++ b/demos/menubar/default.html @@ -3,7 +3,7 @@ <head> <title>jQuery UI Menubar - Default demo</title> <link rel="stylesheet" href="../demos.css" type="text/css" /> - <link rel="stylesheet" href="../../themes/base/jquery.ui.all.css" type="text/css" title="ui-theme" /> + <link rel="stylesheet" href="../../themes/base/jquery.ui.all.css" /> <script src="../../jquery-1.5.1.js"></script> <script src="../../ui/jquery.ui.core.js"></script> <script src="../../ui/jquery.ui.widget.js"></script> @@ -13,56 +13,29 @@ <script src="../../ui/jquery.ui.menubar.js"></script> <script> $(function() { - $("td:has(.menubar)").clone().appendTo("tbody tr:not(:first)"); - - $("#bar1, .menubar").menubar({ + $("#bar1").menubar({ + position: { + within: $("#demo-frame").add(window).first() + }, select: function(event, ui) { $("<div/>").text("Selected: " + ui.item.text()).appendTo("#log"); } }); - + $(".menubar-icons").menubar({ menuIcon: true, buttons: true, + position: { + within: $("#demo-frame").add(window).first() + }, select: function(event, ui) { $("<div/>").text("Selected: " + ui.item.text()).appendTo("#log"); } }); }); </script> - <style type="text/css"> - #bar1, #bar2 { margin: 0 0 4em; } /* style for this page only */ - .ui-menu { width: 200px; position: absolute; outline: none; z-index: 9999; } - .ui-menu .ui-icon { float: right; } - .ui-menu li.ui-state-disabled { - font-weight: bold; - padding: .0em .4em; - margin: .4em 0 .2em; - line-height: 1.5; - } - - /* menubar styles */ - .ui-menubar .ui-button { float: left; font-weight: normal; border-top-width: 0 !important; border-bottom-width: 0 !important; margin: 0; outline: none; } - .ui-menubar .ui-menubar-link { border-right: 1px dashed transparent; border-left: 1px dashed transparent; } - - .ui-menubar { - list-style: none; - margin: 0; - padding-left: 0; - } - - .ui-menubar-item { - float: left; - } - /* - table { - border-collapse: collapse; - } - th, td { - padding: 0.5em; - border: 1px solid black; - } - */ + <style> + #bar1, #bar2 { margin: 0 0 4em; } </style> </head> <body> @@ -160,63 +133,6 @@ </li> </ul> -<!-- -<table id="movies" class="ui-widget"> - <thead> - <tr> - <th data-field="Name" class="ui-widget-header">Name</th> - <th data-field="ReleaseYear" class="ui-widget-header">Release Year</th> - <th data-field="AverageRating" class="ui-widget-header">Average Rating</th> - <th class="ui-widget-header"></th> - </tr> - </thead> - <tbody> - <tr> - <td class="ui-widget-content">Red Hot Chili Peppers: Funky Monks</td> - <td class="ui-widget-content">1993</td> - <td class="ui-widget-content">3.6</td> - <td class="ui-widget-content"> - <ul class="menubar"> - <li> - <a href="#Options">Options</a> - <ul> - <li><a href="#Order...">Order...</a></li> - <li class="ui-state-disabled">Write a Review...</li> - <li><a href="#Find Similar Movies...">Find Similar Movies...</a></li> - <li> - <a href="#Rate">Rate</a> - <ul> - <li><a href="#5 stars">5 stars</a></li> - <li><a href="#4 stars">4 stars</a></li> - <li><a href="#3 stars">3 stars</a></li> - <li><a href="#2 stars">2 stars</a></li> - <li><a href="#1 stars">1 stars</a></li> - </ul> - </li> - </ul> - </li> - </ul> - </td> - </tr> - <tr> - <td class="ui-widget-content">Rod Stewart: Storyteller 1984-1991</td> - <td class="ui-widget-content">1991</td> - <td class="ui-widget-content">3.1</td> - </tr> - <tr> - <td class="ui-widget-content">Stevie Ray Vaughan and Double Trouble: Live at the El Mocambo 1983</td> - <td class="ui-widget-content">1991</td> - <td class="ui-widget-content">3.9</td> - </tr> - <tr> - <td class="ui-widget-content">Spike and Mike's Sick & Twisted Festival of Animation</td> - <td class="ui-widget-content">1997</td> - <td class="ui-widget-content">2.6</td> - </tr> - </tbody> -</table> ---> - <div class="ui-widget" style="margin-top:2em; font-family:Arial"> Log: <div id="log" style="height: 100px; width: 300px; overflow: auto;" class="ui-widget-content"></div> diff --git a/demos/popup/default.html b/demos/popup/default.html index 71b3c8dd2..7b63d9e1d 100644 --- a/demos/popup/default.html +++ b/demos/popup/default.html @@ -29,7 +29,7 @@ <style type="text/css"> .ui-popup { position: absolute; z-index: 5000; } .ui-menu { width: 200px; } - + /* table { border-collapse: collapse; @@ -55,26 +55,24 @@ <div class="demo"> <a href="#login-form">Log In</a> - <div id="login-form" class="ui-widget-content" tabIndex="0"> - <form> - <div> - <label>Username</label> - <input type="username" /> - </div> - <div> - <label>Password</label> - <input type="password" /> - </div> - <div> - <input type="submit" class="submit" value="Login" /> - </div> - </form> + <div class="ui-widget-content" id="login-form" aria-label="Login options"> + <div> + <label for="un">Username</label> + <input type="text" id="un" /> + </div> + <div> + <label for="pw">Password</label> + <input type="password" id="pw" /> + </div> + <div> + <input type="submit" value="Login" class="submit" /> + </div> </div> </div> <div class="demo-description"> -<p>A link to a login form that opens as a popup. [Not quite functional, focus handling needs to get better]</p> +<p>A link to a login form that opens as a popup.</p> </div><!-- End demo-description --> diff --git a/demos/widget/default.html b/demos/widget/default.html index 410318e0a..c2b520983 100644 --- a/demos/widget/default.html +++ b/demos/widget/default.html @@ -10,7 +10,7 @@ <script src="../../ui/jquery.ui.position.js"></script> <link rel="stylesheet" href="../demos.css"> <style> - .colorize { + .custom-colorize { font-size: 25px; width: 75px; height: 75px; @@ -28,20 +28,21 @@ blue: 0, // callbacks + change: null, random: null }, // the constructor _create: function() { this.element - // add a class for themeing - .addClass("colorize") + // add a class for theming + .addClass( "custom-colorize" ) // prevent double click to select text .disableSelection(); // bind click events to random method this._bind({ - // _bind won"t call random when widget is disabled + // _bind won't call random when widget is disabled click: "random" }); this._refresh(); @@ -68,7 +69,7 @@ blue: Math.floor( Math.random() * 256 ) }; - // trigger an event, check if it"s canceled + // trigger an event, check if it's canceled if ( this._trigger( "random", event, colors ) !== false ) { this.option( colors ); } @@ -78,24 +79,26 @@ // revert other modifications here _destroy: function() { this.element - .removeClass( "colorize" ) + .removeClass( "custom-colorize" ) .enableSelection() .css( "background-color", "transparent" ); }, - _setOption: function( key, value ) { - // prevent invalid color values - if ( /red|green|blue/.test(key) && value < 0 || value > 255 ) { - return; - } - this._super( "_setOptions", options ); - }, - + // _setOptions is called with a hash of all options that are changing // always refresh when changing options _setOptions: function() { - // _super handles keeping the right this-context + // _super and _superApply handle keeping the right this-context this._superApply( "_setOptions", arguments ); this._refresh(); + }, + + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) { + // prevent invalid color values + if ( /red|green|blue/.test(key) && (value < 0 || value > 255) ) { + return; + } + this._super( "_setOption", key, value ); } }); @@ -131,7 +134,7 @@ red: 0, green: 0, blue: 0 - } ); + }); }); }); </script> diff --git a/tests/unit/accordion/accordion.html b/tests/unit/accordion/accordion.html index c260ef22f..c4eee6b4c 100644 --- a/tests/unit/accordion/accordion.html +++ b/tests/unit/accordion/accordion.html @@ -25,17 +25,17 @@ var actual = accordion.find( ".ui-accordion-content" ).map(function() { return $( this ).css( "display" ) === "none" ? 0 : 1; }).get(); - same( actual, expected ); + deepEqual( actual, expected ); } - function equalHeights( accordion, min, max ) { + function accordion_equalHeights( accordion, min, max ) { var sizes = []; accordion.find( ".ui-accordion-content" ).each(function() { sizes.push( $( this ).outerHeight() ); }); ok( sizes[ 0 ] >= min && sizes[ 0 ] <= max, "must be within " + min + " and " + max + ", was " + sizes[ 0 ] ); - same( sizes[ 0 ], sizes[ 1 ] ); - same( sizes[ 0 ], sizes[ 2 ] ); + deepEqual( sizes[ 0 ], sizes[ 1 ] ); + deepEqual( sizes[ 0 ], sizes[ 2 ] ); } function accordionSetupTeardown() { var animated = $.ui.accordion.prototype.options.animated; diff --git a/tests/unit/accordion/accordion_core.js b/tests/unit/accordion/accordion_core.js index 280339c26..ec4ca29d5 100644 --- a/tests/unit/accordion/accordion_core.js +++ b/tests/unit/accordion/accordion_core.js @@ -3,6 +3,7 @@ module( "accordion: core", accordionSetupTeardown() ); $.each( { div: "#list1", ul: "#navigation", dl: "#accordion-dl" }, function( type, selector ) { + expect( 4 ); test( "markup structure: " + type, function() { var element = $( selector ).accordion(); ok( element.hasClass( "ui-accordion" ), "main element is .ui-accordion" ); @@ -10,13 +11,14 @@ $.each( { div: "#list1", ul: "#navigation", dl: "#accordion-dl" }, function( typ ".ui-accordion-header elements exist, correct number" ); equal( element.find( ".ui-accordion-content" ).length, 3, ".ui-accordion-content elements exist, correct number" ); - same( element.find( ".ui-accordion-header" ).next().get(), + deepEqual( element.find( ".ui-accordion-header" ).next().get(), element.find( ".ui-accordion-content" ).get(), "content panels come immediately after headers" ); }); }); test( "handle click on header-descendant", function() { + expect( 1 ); var element = $( "#navigation" ).accordion(); $( "#navigation h2:eq(1) a" ).click(); accordion_state( element, 0, 1, 0 ); @@ -26,7 +28,7 @@ test( "ui-accordion-heading class added to headers anchor", function() { expect( 1 ); var element = $( "#list1" ).accordion(); var anchors = element.find( ".ui-accordion-heading" ); - equals( anchors.length, 3 ); + equal( anchors.length, 3 ); }); test( "accessibility", function () { @@ -34,20 +36,20 @@ test( "accessibility", function () { var element = $( "#list1" ).accordion().accordion( "option", "active", 1 ); var headers = element.find( ".ui-accordion-header" ); - equals( headers.eq( 1 ).attr( "tabindex" ), 0, "active header should have tabindex=0" ); - equals( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header should have tabindex=-1" ); - equals( element.attr( "role" ), "tablist", "main role" ); - equals( headers.attr( "role" ), "tab", "tab roles" ); - equals( headers.next().attr( "role" ), "tabpanel", "tabpanel roles" ); - equals( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab has aria-expanded" ); - equals( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab has aria-expanded" ); - equals( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab has aria-selected" ); - equals( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected" ); + equal( headers.eq( 1 ).attr( "tabindex" ), 0, "active header should have tabindex=0" ); + equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header should have tabindex=-1" ); + equal( element.attr( "role" ), "tablist", "main role" ); + equal( headers.attr( "role" ), "tab", "tab roles" ); + equal( headers.next().attr( "role" ), "tabpanel", "tabpanel roles" ); + equal( headers.eq( 1 ).attr( "aria-expanded" ), "true", "active tab has aria-expanded" ); + equal( headers.eq( 0 ).attr( "aria-expanded" ), "false", "inactive tab has aria-expanded" ); + equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab has aria-selected" ); + equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected" ); element.accordion( "option", "active", 0 ); - equals( headers.eq( 0 ).attr( "aria-expanded" ), "true", "newly active tab has aria-expanded" ); - equals( headers.eq( 1 ).attr( "aria-expanded" ), "false", "newly inactive tab has aria-expanded" ); - equals( headers.eq( 0 ).attr( "aria-selected" ), "true", "active tab has aria-selected" ); - equals( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected" ); + equal( headers.eq( 0 ).attr( "aria-expanded" ), "true", "newly active tab has aria-expanded" ); + equal( headers.eq( 1 ).attr( "aria-expanded" ), "false", "newly inactive tab has aria-expanded" ); + equal( headers.eq( 0 ).attr( "aria-selected" ), "true", "active tab has aria-selected" ); + equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected" ); }); }( jQuery ) ); diff --git a/tests/unit/accordion/accordion_deprecated.html b/tests/unit/accordion/accordion_deprecated.html index e8254f4f3..5bfe7562b 100644 --- a/tests/unit/accordion/accordion_deprecated.html +++ b/tests/unit/accordion/accordion_deprecated.html @@ -22,17 +22,17 @@ var actual = accordion.find( ".ui-accordion-content" ).map(function() { return $( this ).css( "display" ) === "none" ? 0 : 1; }).get(); - same( actual, expected ); + deepEqual( actual, expected ); } - function equalHeights( accordion, min, max ) { + function accordion_equalHeights( accordion, min, max ) { var sizes = []; accordion.find( ".ui-accordion-content" ).each(function() { sizes.push( $( this ).outerHeight() ); }); ok( sizes[ 0 ] >= min && sizes[ 0 ] <= max, "must be within " + min + " and " + max + ", was " + sizes[ 0 ] ); - same( sizes[ 0 ], sizes[ 1 ] ); - same( sizes[ 0 ], sizes[ 2 ] ); + deepEqual( sizes[ 0 ], sizes[ 1 ] ); + deepEqual( sizes[ 0 ], sizes[ 2 ] ); } function accordionSetupTeardown() { var animated = $.ui.accordion.prototype.options.animated; diff --git a/tests/unit/accordion/accordion_deprecated.js b/tests/unit/accordion/accordion_deprecated.js index 0435f48a7..3a2075b2b 100644 --- a/tests/unit/accordion/accordion_deprecated.js +++ b/tests/unit/accordion/accordion_deprecated.js @@ -3,6 +3,7 @@ module( "accordion (deprecated): expanded active option, activate method", accordionSetupTeardown() ); test( "activate, numeric", function() { + expect( 5 ); var element = $( "#list1" ).accordion({ active: 1 }); accordion_state( element, 0, 1, 0 ); element.accordion( "activate", 2 ); @@ -16,6 +17,7 @@ test( "activate, numeric", function() { }); test( "activate, numeric, collapsible:true", function() { + expect( 3 ); var element = $( "#list1" ).accordion({ collapsible: true }); element.accordion( "activate", 2 ); accordion_state( element, 0, 0, 1 ); @@ -26,6 +28,7 @@ test( "activate, numeric, collapsible:true", function() { }); test( "activate, boolean, collapsible: true", function() { + expect( 2 ); var element = $( "#list1" ).accordion({ collapsible: true }); element.accordion( "activate", 2 ); accordion_state( element, 0, 0, 1 ); @@ -34,6 +37,7 @@ test( "activate, boolean, collapsible: true", function() { }); test( "activate, boolean, collapsible: false", function() { + expect( 2 ); var element = $( "#list1" ).accordion(); element.accordion( "activate", 2 ); accordion_state( element, 0, 0, 1 ); @@ -42,6 +46,7 @@ test( "activate, boolean, collapsible: false", function() { }); test( "activate, string expression", function() { + expect( 4 ); var element = $( "#list1" ).accordion({ active: "h3:last" }); accordion_state( element, 0, 0, 1 ); element.accordion( "activate", ":first" ); @@ -53,6 +58,7 @@ test( "activate, string expression", function() { }); test( "activate, jQuery or DOM element", function() { + expect( 3 ); var element = $( "#list1" ).accordion({ active: $( "#list1 h3:last" ) }); accordion_state( element, 0, 0, 1 ); element.accordion( "activate", $( "#list1 h3:first" ) ); @@ -62,6 +68,7 @@ test( "activate, jQuery or DOM element", function() { }); test( "{ active: Selector }", function() { + expect( 2 ); var element = $("#list1").accordion({ active: "h3:last" }); @@ -71,6 +78,7 @@ test( "{ active: Selector }", function() { }); test( "{ active: Element }", function() { + expect( 2 ); var element = $( "#list1" ).accordion({ active: $( "#list1 h3:last" )[ 0 ] }); @@ -80,6 +88,7 @@ test( "{ active: Element }", function() { }); test( "{ active: jQuery Object }", function() { + expect( 2 ); var element = $( "#list1" ).accordion({ active: $( "#list1 h3:last" ) }); @@ -95,14 +104,16 @@ test( "{ active: jQuery Object }", function() { module( "accordion (deprecated) - height options", accordionSetupTeardown() ); test( "{ autoHeight: true }, default", function() { - equalHeights($('#navigation').accordion({ autoHeight: true }), 95, 130); + expect( 3 ); + accordion_equalHeights( $( "#navigation" ).accordion({ autoHeight: true }), 95, 130 ); }); -test("{ autoHeight: false }", function() { - var element = $('#navigation').accordion({ autoHeight: false }); +test( "{ autoHeight: false }", function() { + expect( 3 ); + var element = $( "#navigation" ).accordion({ autoHeight: false }); var sizes = []; - element.find(".ui-accordion-content").each(function() { - sizes.push($(this).height()); + element.find( ".ui-accordion-content" ).each(function() { + sizes.push( $(this).height() ); }); ok( sizes[0] >= 70 && sizes[0] <= 105, "was " + sizes[0] ); ok( sizes[1] >= 98 && sizes[1] <= 126, "was " + sizes[1] ); @@ -110,12 +121,14 @@ test("{ autoHeight: false }", function() { }); test( "{ fillSpace: true }", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); var element = $( "#navigation" ).accordion({ fillSpace: true }); - equalHeights( element, 446, 458 ); + accordion_equalHeights( element, 446, 458 ); }); test( "{ fillSapce: true } with sibling", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); $( "<p>Lorem Ipsum</p>" ) .css({ @@ -125,10 +138,11 @@ test( "{ fillSapce: true } with sibling", function() { }) .prependTo( "#navigationWrapper" ); var element = $( "#navigation" ).accordion({ fillSpace: true }); - equalHeights( element , 346, 358); + accordion_equalHeights( element , 346, 358); }); test( "{ fillSpace: true } with multiple siblings", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); $( "<p>Lorem Ipsum</p>" ) .css({ @@ -153,7 +167,7 @@ test( "{ fillSpace: true } with multiple siblings", function() { }) .prependTo( "#navigationWrapper" ); var element = $( "#navigation" ).accordion({ fillSpace: true }); - equalHeights( element, 296, 308 ); + accordion_equalHeights( element, 296, 308 ); }); @@ -163,6 +177,7 @@ test( "{ fillSpace: true } with multiple siblings", function() { module( "accordion (deprecated) - icons", accordionSetupTeardown() ); test( "icons, headerSelected", function() { + expect( 3 ); var element = $( "#list1" ).accordion({ icons: { headerSelected: "a1", header: "h1" } }); @@ -179,6 +194,7 @@ test( "icons, headerSelected", function() { module( "accordion (deprecated) - resize", accordionSetupTeardown() ); test( "resize", function() { + expect( 6 ); var element = $( "#navigation" ) .parent() .height( 300 ) @@ -186,11 +202,11 @@ test( "resize", function() { .accordion({ heightStyle: "fill" }); - equalHeights( element, 246, 258 ); + accordion_equalHeights( element, 246, 258 ); element.parent().height( 500 ); element.accordion( "resize" ); - equalHeights( element, 446, 458 ); + accordion_equalHeights( element, 446, 458 ); }); @@ -200,6 +216,7 @@ test( "resize", function() { module( "accordion (deprecated) - navigation", accordionSetupTeardown() ); test( "{ navigation: true, navigationFilter: header }", function() { + expect( 2 ); var element = $( "#navigation" ).accordion({ navigation: true, navigationFilter: function() { @@ -211,10 +228,11 @@ test( "{ navigation: true, navigationFilter: header }", function() { }); test( "{ navigation: true, navigationFilter: content }", function() { - var element = $("#navigation").accordion({ + expect( 2 ); + var element = $( "#navigation" ).accordion({ navigation: true, navigationFilter: function() { - return /\?p=1\.1\.3\.2$/.test(this.href); + return /\?p=1\.1\.3\.2$/.test( this.href ); } }); equal( element.accordion( "option", "active" ), 2 ); @@ -237,11 +255,11 @@ test( "changestart", function() { var content = element.find( ".ui-accordion-content" ); element.one( "accordionchangestart", function( event, ui ) { - equals( ui.oldHeader.size(), 0 ); - equals( ui.oldContent.size(), 0 ); - equals( ui.newHeader.size(), 1 ); + equal( ui.oldHeader.size(), 0 ); + equal( ui.oldContent.size(), 0 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); accordion_state( element, 0, 0, 0 ); }); @@ -249,13 +267,13 @@ test( "changestart", function() { accordion_state( element, 1, 0, 0 ); element.one( "accordionchangestart", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equals( ui.newHeader.size(), 1 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); accordion_state( element, 1, 0, 0 ); }); @@ -263,12 +281,12 @@ test( "changestart", function() { accordion_state( element, 0, 1, 0 ); element.one( "accordionchangestart", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equals( ui.newHeader.size(), 0 ); - equals( ui.newContent.size(), 0 ); + equal( ui.newHeader.size(), 0 ); + equal( ui.newContent.size(), 0 ); accordion_state( element, 0, 1, 0 ); }); element.accordion( "option", "active", false ); @@ -285,34 +303,34 @@ test( "change", function() { var content = element.find( ".ui-accordion-content" ); element.one( "accordionchange", function( event, ui ) { - equals( ui.oldHeader.size(), 0 ); - equals( ui.oldContent.size(), 0 ); - equals( ui.newHeader.size(), 1 ); + equal( ui.oldHeader.size(), 0 ); + equal( ui.oldContent.size(), 0 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); }); element.accordion( "option", "active", 0 ); element.one( "accordionchange", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equals( ui.newHeader.size(), 1 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); }); headers.eq( 1 ).click(); element.one( "accordionchange", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equals( ui.newHeader.size(), 0 ); - equals( ui.newContent.size(), 0 ); + equal( ui.newHeader.size(), 0 ); + equal( ui.newContent.size(), 0 ); }); element.accordion( "option", "active", false ); }); diff --git a/tests/unit/accordion/accordion_events.js b/tests/unit/accordion/accordion_events.js index 2438f28ea..d704e54c8 100644 --- a/tests/unit/accordion/accordion_events.js +++ b/tests/unit/accordion/accordion_events.js @@ -13,11 +13,11 @@ test( "beforeActivate", function() { element.one( "accordionbeforeactivate", function( event, ui ) { ok( !( "originalEvent" in event ) ); - equals( ui.oldHeader.size(), 0 ); - equals( ui.oldContent.size(), 0 ); - equals( ui.newHeader.size(), 1 ); + equal( ui.oldHeader.size(), 0 ); + equal( ui.oldContent.size(), 0 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); accordion_state( element, 0, 0, 0 ); }); @@ -25,14 +25,14 @@ test( "beforeActivate", function() { accordion_state( element, 1, 0, 0 ); element.one( "accordionbeforeactivate", function( event, ui ) { - equals( event.originalEvent.type, "click" ); - equals( ui.oldHeader.size(), 1 ); + equal( event.originalEvent.type, "click" ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equals( ui.newHeader.size(), 1 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); accordion_state( element, 1, 0, 0 ); }); @@ -41,12 +41,12 @@ test( "beforeActivate", function() { element.one( "accordionbeforeactivate", function( event, ui ) { ok( !( "originalEvent" in event ) ); - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equals( ui.newHeader.size(), 0 ); - equals( ui.newContent.size(), 0 ); + equal( ui.newHeader.size(), 0 ); + equal( ui.newContent.size(), 0 ); accordion_state( element, 0, 1, 0 ); }); element.accordion( "option", "active", false ); @@ -54,11 +54,11 @@ test( "beforeActivate", function() { element.one( "accordionbeforeactivate", function( event, ui ) { ok( !( "originalEvent" in event ) ); - equals( ui.oldHeader.size(), 0 ); - equals( ui.oldContent.size(), 0 ); - equals( ui.newHeader.size(), 1 ); + equal( ui.oldHeader.size(), 0 ); + equal( ui.oldContent.size(), 0 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 2 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 2 ] ); event.preventDefault(); accordion_state( element, 0, 0, 0 ); @@ -77,34 +77,34 @@ test( "activate", function() { var content = element.find( ".ui-accordion-content" ); element.one( "accordionactivate", function( event, ui ) { - equals( ui.oldHeader.size(), 0 ); - equals( ui.oldContent.size(), 0 ); - equals( ui.newHeader.size(), 1 ); + equal( ui.oldHeader.size(), 0 ); + equal( ui.oldContent.size(), 0 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); }); element.accordion( "option", "active", 0 ); element.one( "accordionactivate", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equals( ui.newHeader.size(), 1 ); + equal( ui.newHeader.size(), 1 ); strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equals( ui.newContent.size(), 1 ); + equal( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); }); headers.eq( 1 ).click(); element.one( "accordionactivate", function( event, ui ) { - equals( ui.oldHeader.size(), 1 ); + equal( ui.oldHeader.size(), 1 ); strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equals( ui.oldContent.size(), 1 ); + equal( ui.oldContent.size(), 1 ); strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equals( ui.newHeader.size(), 0 ); - equals( ui.newContent.size(), 0 ); + equal( ui.newHeader.size(), 0 ); + equal( ui.newContent.size(), 0 ); }); element.accordion( "option", "active", false ); diff --git a/tests/unit/accordion/accordion_methods.js b/tests/unit/accordion/accordion_methods.js index d45bde134..c6ba3230a 100644 --- a/tests/unit/accordion/accordion_methods.js +++ b/tests/unit/accordion/accordion_methods.js @@ -3,13 +3,15 @@ module( "accordion: methods", accordionSetupTeardown() ); test( "destroy", function() { - domEqual("#list1", function() { - $("#list1").accordion().accordion("destroy"); + expect( 1 ); + domEqual( "#list1", function() { + $( "#list1" ).accordion().accordion( "destroy" ); }); }); test( "enable/disable", function() { - var element = $('#list1').accordion(); + expect( 3 ); + var element = $( "#list1" ).accordion(); accordion_state( element, 1, 0, 0 ); element.accordion( "disable" ); element.accordion( "option", "active", 1 ); @@ -20,6 +22,7 @@ test( "enable/disable", function() { }); test( "refresh", function() { + expect( 6 ); var element = $( "#navigation" ) .parent() .height( 300 ) @@ -27,11 +30,11 @@ test( "refresh", function() { .accordion({ heightStyle: "fill" }); - equalHeights( element, 246, 258 ); + accordion_equalHeights( element, 246, 258 ); element.parent().height( 500 ); element.accordion( "refresh" ); - equalHeights( element, 446, 458 ); + accordion_equalHeights( element, 446, 458 ); }); }( jQuery ) ); diff --git a/tests/unit/accordion/accordion_options.js b/tests/unit/accordion/accordion_options.js index 7bd6f2e74..80b7f0b39 100644 --- a/tests/unit/accordion/accordion_options.js +++ b/tests/unit/accordion/accordion_options.js @@ -3,23 +3,25 @@ module( "accordion: options", accordionSetupTeardown() ); test( "{ active: default }", function() { + expect( 2 ); var element = $( "#list1" ).accordion(); - equals( element.accordion( "option", "active" ), 0 ); + equal( element.accordion( "option", "active" ), 0 ); accordion_state( element, 1, 0, 0 ); }); test( "{ active: false }", function() { + expect( 7 ); var element = $( "#list1" ).accordion({ active: false, collapsible: true }); accordion_state( element, 0, 0, 0 ); - equals( element.find( ".ui-accordion-header.ui-state-active" ).size(), 0, "no headers selected" ); - equals( element.accordion( "option", "active" ), false ); + equal( element.find( ".ui-accordion-header.ui-state-active" ).size(), 0, "no headers selected" ); + equal( element.accordion( "option", "active" ), false ); element.accordion( "option", "collapsible", false ); accordion_state( element, 1, 0, 0 ); - equals( element.accordion( "option", "active" ), 0 ); + equal( element.accordion( "option", "active" ), 0 ); element.accordion( "destroy" ); element.accordion({ @@ -30,43 +32,45 @@ test( "{ active: false }", function() { }); test( "{ active: Number }", function() { + expect( 8 ); var element = $( "#list1" ).accordion({ active: 2 }); - equals( element.accordion( "option", "active" ), 2 ); + equal( element.accordion( "option", "active" ), 2 ); accordion_state( element, 0, 0, 1 ); element.accordion( "option", "active", 0 ); - equals( element.accordion( "option", "active" ), 0 ); + equal( element.accordion( "option", "active" ), 0 ); accordion_state( element, 1, 0, 0 ); element.find( ".ui-accordion-header" ).eq( 1 ).click(); - equals( element.accordion( "option", "active" ), 1 ); + equal( element.accordion( "option", "active" ), 1 ); accordion_state( element, 0, 1, 0 ); element.accordion( "option", "active", 10 ); - equals( element.accordion( "option", "active" ), 1 ); + equal( element.accordion( "option", "active" ), 1 ); accordion_state( element, 0, 1, 0 ); }); if ( $.uiBackCompat === false ) { test( "{ active: -Number }", function() { + expect( 8 ); var element = $( "#list1" ).accordion({ active: -1 }); - equals( element.accordion( "option", "active" ), 2 ); + equal( element.accordion( "option", "active" ), 2 ); accordion_state( element, 0, 0, 1 ); element.accordion( "option", "active", -2 ); - equals( element.accordion( "option", "active" ), 1 ); + equal( element.accordion( "option", "active" ), 1 ); accordion_state( element, 0, 1, 0 ); element.accordion( "option", "active", -10 ); - equals( element.accordion( "option", "active" ), 1 ); + equal( element.accordion( "option", "active" ), 1 ); accordion_state( element, 0, 1, 0 ); element.accordion( "option", "active", -3 ); - equals( element.accordion( "option", "active" ), 0 ); + equal( element.accordion( "option", "active" ), 0 ); accordion_state( element, 1, 0, 0 ); }); } @@ -74,6 +78,7 @@ if ( $.uiBackCompat === false ) { // TODO: add animation tests test( "{ collapsible: false }", function() { + expect( 4 ); var element = $( "#list1" ).accordion({ active: 1 }); @@ -87,6 +92,7 @@ test( "{ collapsible: false }", function() { }); test( "{ collapsible: true }", function() { + expect( 6 ); var element = $( "#list1" ).accordion({ active: 1, collapsible: true @@ -101,11 +107,12 @@ test( "{ collapsible: true }", function() { accordion_state( element, 0, 1, 0 ); element.find( ".ui-accordion-header" ).eq( 1 ).click(); - equals( element.accordion( "option", "active" ), false ); + equal( element.accordion( "option", "active" ), false ); accordion_state( element, 0, 0, 0 ); }); test( "{ event: null }", function() { + expect( 5 ); var element = $( "#list1" ).accordion({ event: null }); @@ -122,6 +129,7 @@ test( "{ event: null }", function() { }); test( "{ event: custom }", function() { + expect( 11 ); var element = $( "#list1" ).accordion({ event: "custom1 custom2" }); @@ -153,6 +161,7 @@ test( "{ event: custom }", function() { }); test( "{ header: default }", function() { + expect( 2 ); // default: > li > :first-child,> :not(li):even // > :not(li):even accordion_state( $( "#list1" ).accordion(), 1, 0, 0); @@ -161,6 +170,7 @@ test( "{ header: default }", function() { }); test( "{ header: custom }", function() { + expect( 6 ); var element = $( "#navigationWrapper" ).accordion({ header: "h2" }); @@ -174,11 +184,13 @@ test( "{ header: custom }", function() { }); test( "{ heightStyle: 'auto' }", function() { + expect( 3 ); var element = $( "#navigation" ).accordion({ heightStyle: "auto" }); - equalHeights( element, 95, 130 ); + accordion_equalHeights( element, 95, 130 ); }); test( "{ heightStyle: 'content' }", function() { + expect( 3 ); var element = $( "#navigation" ).accordion({ heightStyle: "content" }); var sizes = element.find( ".ui-accordion-content" ).map(function() { return $( this ).height(); @@ -189,12 +201,14 @@ test( "{ heightStyle: 'content' }", function() { }); test( "{ heightStyle: 'fill' }", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); var element = $( "#navigation" ).accordion({ heightStyle: "fill" }); - equalHeights( element, 446, 458 ); + accordion_equalHeights( element, 446, 458 ); }); test( "{ heightStyle: 'fill' } with sibling", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); $( "<p>Lorem Ipsum</p>" ) .css({ @@ -204,10 +218,11 @@ test( "{ heightStyle: 'fill' } with sibling", function() { }) .prependTo( "#navigationWrapper" ); var element = $( "#navigation" ).accordion({ heightStyle: "fill" }); - equalHeights( element , 346, 358); + accordion_equalHeights( element , 346, 358); }); test( "{ heightStyle: 'fill' } with multiple siblings", function() { + expect( 3 ); $( "#navigationWrapper" ).height( 500 ); $( "<p>Lorem Ipsum</p>" ) .css({ @@ -232,14 +247,15 @@ test( "{ heightStyle: 'fill' } with multiple siblings", function() { }) .prependTo( "#navigationWrapper" ); var element = $( "#navigation" ).accordion({ heightStyle: "fill" }); - equalHeights( element, 296, 308 ); + accordion_equalHeights( element, 296, 308 ); }); test( "{ icons: false }", function() { + expect( 8 ); var element = $( "#list1" ); function icons( on ) { - same( element.find( "span.ui-icon").length, on ? 3 : 0 ); - same( element.hasClass( "ui-accordion-icons" ), on ); + deepEqual( element.find( "span.ui-icon").length, on ? 3 : 0 ); + deepEqual( element.hasClass( "ui-accordion-icons" ), on ); } element.accordion(); icons( true ); @@ -254,6 +270,7 @@ test( "{ icons: false }", function() { }); test( "{ icons: hash }", function() { + expect( 3 ); var element = $( "#list1" ).accordion({ icons: { activeHeader: "a1", header: "h1" } }); diff --git a/tests/unit/autocomplete/autocomplete.html b/tests/unit/autocomplete/autocomplete.html index 8f1d9db9a..a69562d3f 100644 --- a/tests/unit/autocomplete/autocomplete.html +++ b/tests/unit/autocomplete/autocomplete.html @@ -1,46 +1,44 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> - <meta charset="UTF-8" /> + <meta charset="utf-8"> <title>jQuery UI Autocomplete Test Suite</title> - <link type="text/css" href="../../../themes/base/jquery.ui.autocomplete.css" rel="stylesheet" /> - - <script type="text/javascript" src="../../../jquery-1.5.1.js"></script> - <script type="text/javascript" src="../../../ui/jquery.ui.core.js"></script> - <script type="text/javascript" src="../../../ui/jquery.ui.widget.js"></script> - <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script> - <script type="text/javascript" src="../../../ui/jquery.ui.menu.js"></script> - <script type="text/javascript" src="../../../ui/jquery.ui.autocomplete.js"></script> - - <link rel="stylesheet" href="../../../external/qunit.css" type="text/css"/> - <script type="text/javascript" src="../../../external/qunit.js"></script> - <script type="text/javascript" src="../../jquery.simulate.js"></script> - <script type="text/javascript" src="../testsuite.js"></script> - - <script type="text/javascript" src="autocomplete_core.js"></script> - <script type="text/javascript" src="autocomplete_defaults.js"></script> - <script type="text/javascript" src="autocomplete_events.js"></script> - <script type="text/javascript" src="autocomplete_methods.js"></script> - <script type="text/javascript" src="autocomplete_options.js"></script> - - <script type="text/javascript" src="../swarminject.js"></script> + <link rel="stylesheet" href="../../../themes/base/jquery.ui.autocomplete.css"> + + <script src="../../../jquery-1.5.1.js"></script> + <script src="../../../ui/jquery.ui.core.js"></script> + <script src="../../../ui/jquery.ui.widget.js"></script> + <script src="../../../ui/jquery.ui.position.js"></script> + <script src="../../../ui/jquery.ui.menu.js"></script> + <script src="../../../ui/jquery.ui.autocomplete.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 src="autocomplete_defaults.js"></script> + <script src="autocomplete_core.js"></script> + <script src="autocomplete_events.js"></script> + <script src="autocomplete_methods.js"></script> + <script src="autocomplete_options.js"></script> + + <script src="../swarminject.js"></script> </head> -<body id="body"> +<body> <h1 id="qunit-header">jQuery UI Autocomplete Test Suite</h1> <h2 id="qunit-banner"></h2> <div id="qunit-testrunner-toolbar"></div> <h2 id="qunit-userAgent"></h2> -<ol id="qunit-tests"> -</ol> - +<ol id="qunit-tests"></ol> <div id="qunit-fixture"> - <div id="ac-wrap1" class="ac-wrap"></div> - <div id="ac-wrap2" class="ac-wrap"><input id="autocomplete" class="foo" /></div> - <div id="autocomplete-contenteditable" contenteditable="" tabindex=0></div> -</div> +<div id="ac-wrap1" class="ac-wrap"></div> +<div id="ac-wrap2" class="ac-wrap"><input id="autocomplete" class="foo" /></div> +<div id="autocomplete-contenteditable" contenteditable="" tabindex=0></div> +</div> </body> </html> diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index 19f52dc15..3f92aa01f 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -1,73 +1,83 @@ -/* - * autocomplete_core.js - */ +(function( $ ) { +module( "autocomplete: core" ); -(function($) { +asyncTest( "close-on-blur is properly delayed", function() { + expect( 3 ); + var element = $( "#autocomplete" ) + .autocomplete({ + source: [ "java", "javascript" ] + }) + .val( "ja" ) + .autocomplete( "search" ), + menu = element.autocomplete( "widget" ); -module("autocomplete: core", { - teardown: function() { - $( ":ui-autocomplete" ).autocomplete( "destroy" ); - } -}); - -test("close-on-blur is properly delayed", function() { - var ac = $("#autocomplete").autocomplete({ - source: ["java", "javascript"] - }).val("ja").autocomplete("search"); - same( $(".ui-menu:visible").length, 1 ); - ac.blur(); - same( $(".ui-menu:visible").length, 1 ); - stop(); + ok( menu.is( ":visible" ) ); + element.blur(); + ok( menu.is( ":visible" ) ); setTimeout(function() { - same( $(".ui-menu:visible").length, 0 ); + ok( menu.is( ":hidden") ); start(); - }, 200); + }, 200 ); }); -test("close-on-blur is cancelled when starting a search", function() { - var ac = $("#autocomplete").autocomplete({ - source: ["java", "javascript"] - }).val("ja").autocomplete("search"); - same( $(".ui-menu:visible").length, 1 ); - ac.blur(); - same( $(".ui-menu:visible").length, 1 ); - ac.autocomplete("search"); - stop(); +asyncTest( "close-on-blur is cancelled when starting a search", function() { + expect( 3 ); + var element = $( "#autocomplete" ) + .autocomplete({ + source: [ "java", "javascript" ] + }) + .val( "ja" ) + .autocomplete( "search" ), + menu = element.autocomplete( "widget" ); + + ok( menu.is( ":visible" ) ); + element.blur(); + ok( menu.is( ":visible" ) ); + element.autocomplete( "search" ); setTimeout(function() { - same( $(".ui-menu:visible").length, 1 ); + ok( menu.is( ":visible" ) ); start(); - }, 200); + }, 200 ); }); test( "prevent form submit on enter when menu is active", function() { - var event; - var ac = $( "#autocomplete" ).autocomplete({ - source: [ "java", "javascript" ] - }).val( "ja" ).autocomplete( "search" ); - + expect( 2 ); + var event, + element = $( "#autocomplete" ) + .autocomplete({ + source: [ "java", "javascript" ] + }) + .val( "ja" ) + .autocomplete( "search" ), + menu = element.autocomplete( "widget" ); + event = $.Event( "keydown" ); event.keyCode = $.ui.keyCode.DOWN; - ac.trigger( event ); - same( $( ".ui-menu-item:has(.ui-state-focus)" ).length, 1, "menu item is active" ); - + element.trigger( event ); + deepEqual( menu.find( ".ui-menu-item:has(.ui-state-focus)" ).length, 1, "menu item is active" ); + event = $.Event( "keydown" ); event.keyCode = $.ui.keyCode.ENTER; - ac.trigger( event ); + element.trigger( event ); ok( event.isDefaultPrevented(), "default action is prevented" ); }); test( "allow form submit on enter when menu is not active", function() { - var event; - var ac = $( "#autocomplete" ).autocomplete({ - autoFocus: false, - source: [ "java", "javascript" ] - }).val( "ja" ).autocomplete( "search" ); - + expect( 1 ); + var event, + element = $( "#autocomplete" ) + .autocomplete({ + autoFocus: false, + source: [ "java", "javascript" ] + }) + .val( "ja" ) + .autocomplete( "search" ); + event = $.Event( "keydown" ); event.keyCode = $.ui.keyCode.ENTER; - ac.trigger( event ); + element.trigger( event ); ok( !event.isDefaultPrevented(), "default action is prevented" ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index c884733d6..c6d42ddcc 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -1,206 +1,197 @@ -/* - * autocomplete_events.js - */ -(function($) { +(function( $ ) { -module("autocomplete: events", { - teardown: function() { - $( ":ui-autocomplete" ).autocomplete( "destroy" ); - } -}); +module( "autocomplete: events" ); var data = [ "Clojure", "COBOL", "ColdFusion", "Java", "JavaScript", "Scala", "Scheme" ]; -test("all events", function() { - expect(14); - var ac = $("#autocomplete").autocomplete({ - autoFocus: false, - delay: 0, - source: data, - search: function(event) { - same(event.type, "autocompletesearch"); - }, - response: function(event, ui) { - same(event.type, "autocompleteresponse"); - same(ui.content, [ - { label: "Clojure", value: "Clojure" }, - { label: "Java", value: "Java" }, - { label: "JavaScript", value: "JavaScript" } - ]); - ui.content.splice( 0, 1 ); - }, - open: function(event) { - same(event.type, "autocompleteopen"); - }, - focus: function(event, ui) { - same(event.type, "autocompletefocus"); - same(ui.item, {label:"Java", value:"Java"}); - }, - close: function(event) { - same(event.type, "autocompleteclose"); - same( $(".ui-menu:visible").length, 0 ); - }, - select: function(event, ui) { - same(event.type, "autocompleteselect"); - same(ui.item, {label:"Java", value:"Java"}); - }, - change: function(event, ui) { - same(event.type, "autocompletechange"); - same(ui.item, {label:"Java", value:"Java"}); - same( $(".ui-menu:visible").length, 0 ); - start(); - } - }); - stop(); - ac.focus().val("j").keydown(); +asyncTest( "all events", function() { + expect( 13 ); + var element = $( "#autocomplete" ) + .autocomplete({ + autoFocus: false, + delay: 0, + source: data, + search: function( event ) { + equal( event.originalEvent.type, "keydown", "search originalEvent" ); + }, + response: function( event, ui ) { + deepEqual( ui.content, [ + { label: "Clojure", value: "Clojure" }, + { label: "Java", value: "Java" }, + { label: "JavaScript", value: "JavaScript" } + ], "response ui.content" ); + ui.content.splice( 0, 1 ); + }, + open: function( event ) { + ok( menu.is( ":visible" ), "menu open on open" ); + }, + focus: function( event, ui ) { + equal( event.originalEvent.type, "menufocus", "focus originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "focus ui.item" ); + }, + close: function( event ) { + equal( event.originalEvent.type, "menuselect", "close originalEvent" ); + ok( menu.is( ":hidden" ), "menu closed on close" ); + }, + select: function( event, ui ) { + equal( event.originalEvent.type, "menuselect", "select originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "select ui.item" ); + }, + change: function( event, ui ) { + equal( event.originalEvent.type, "blur", "change originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "chnage ui.item" ); + ok( menu.is( ":hidden" ), "menu closed on change" ); + start(); + } + }), + menu = element.autocomplete( "widget" ); + + element.focus().val( "j" ).keydown(); setTimeout(function() { - same( $(".ui-menu:visible").length, 1 ); - ac.simulate("keydown", { keyCode: $.ui.keyCode.DOWN }); - ac.simulate("keydown", { keyCode: $.ui.keyCode.ENTER }); + ok( menu.is( ":visible" ), "menu is visible after delay" ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); // blurring through jQuery causes a bug in IE 6 which causes the // autocompletechange event to occur twice - ac[0].blur(); - }, 50); + element[0].blur(); + }, 50 ); }); -test("all events - contenteditable", function() { - expect(14); - var ac = $("#autocomplete-contenteditable").autocomplete({ - autoFocus: false, - delay: 0, - source: data, - search: function(event) { - same(event.type, "autocompletesearch"); - }, - response: function(event, ui) { - same(event.type, "autocompleteresponse"); - same(ui.content, [ - { label: "Clojure", value: "Clojure" }, - { label: "Java", value: "Java" }, - { label: "JavaScript", value: "JavaScript" } - ]); - ui.content.splice( 0, 1 ); - }, - open: function(event) { - same(event.type, "autocompleteopen"); - }, - focus: function(event, ui) { - same(event.type, "autocompletefocus"); - same(ui.item, {label:"Java", value:"Java"}); - }, - close: function(event) { - same(event.type, "autocompleteclose"); - same( $(".ui-menu:visible").length, 0 ); - }, - select: function(event, ui) { - same(event.type, "autocompleteselect"); - same(ui.item, {label:"Java", value:"Java"}); - }, - change: function(event, ui) { - same(event.type, "autocompletechange"); - same(ui.item, {label:"Java", value:"Java"}); - same( $(".ui-menu:visible").length, 0 ); - start(); - } - }); - stop(); - ac.focus().text("j").keydown(); +asyncTest( "all events - contenteditable", function() { + expect( 13 ); + var element = $( "#autocomplete-contenteditable" ) + .autocomplete({ + autoFocus: false, + delay: 0, + source: data, + search: function( event ) { + equal( event.originalEvent.type, "keydown", "search originalEvent" ); + }, + response: function( event, ui ) { + deepEqual( ui.content, [ + { label: "Clojure", value: "Clojure" }, + { label: "Java", value: "Java" }, + { label: "JavaScript", value: "JavaScript" } + ], "response ui.content" ); + ui.content.splice( 0, 1 ); + }, + open: function( event ) { + ok( menu.is( ":visible" ), "menu open on open" ); + }, + focus: function( event, ui ) { + equal( event.originalEvent.type, "menufocus", "focus originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "focus ui.item" ); + }, + close: function( event ) { + equal( event.originalEvent.type, "menuselect", "close originalEvent" ); + ok( menu.is( ":hidden" ), "menu closed on close" ); + }, + select: function( event, ui ) { + equal( event.originalEvent.type, "menuselect", "select originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "select ui.item" ); + }, + change: function( event, ui ) { + equal( event.originalEvent.type, "blur", "change originalEvent" ); + deepEqual( ui.item, { label: "Java", value: "Java" }, "chnage ui.item" ); + ok( menu.is( ":hidden" ), "menu closed on change" ); + start(); + } + }), + menu = element.autocomplete( "widget" ); + + element.focus().text( "j" ).keydown(); setTimeout(function() { - same( $(".ui-menu:visible").length, 1 ); - ac.simulate("keydown", { keyCode: $.ui.keyCode.DOWN }); - ac.simulate("keydown", { keyCode: $.ui.keyCode.ENTER }); - // blurring through jQuery causes a bug in IE 6 which causes the + ok( menu.is( ":visible" ), "menu is visible after delay" ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + // TODO: blurring through jQuery causes a bug in IE 6 which causes the // autocompletechange event to occur twice - ac[0].blur(); - }, 50); + element[0].blur(); + }, 50 ); }); -test("change without selection", function() { - expect(2); - stop(); - var ac = $("#autocomplete").autocomplete({ +asyncTest( "change without selection", function() { + expect( 1 ); + var element = $( "#autocomplete" ).autocomplete({ delay: 0, source: data, - change: function(event, ui) { - same(event.type, "autocompletechange"); - same(ui.item, null); + change: function( event, ui ) { + strictEqual( ui.item, null ); start(); } }); - ac.triggerHandler("focus"); - ac.val("ja").triggerHandler("blur"); + element.triggerHandler( "focus" ); + element.val( "ja" ).triggerHandler( "blur" ); }); -test("cancel search", function() { - expect(6); - var first = true; - var ac = $("#autocomplete").autocomplete({ - delay: 0, - source: data, - search: function() { - if (first) { - same( ac.val(), "ja" ); - first = false; - return false; +asyncTest( "cancel search", function() { + expect( 6 ); + var first = true, + element = $( "#autocomplete" ).autocomplete({ + delay: 0, + source: data, + search: function() { + if ( first ) { + equal( element.val(), "ja", "val on first search" ); + first = false; + return false; + } + equal( element.val(), "java", "val on second search" ); + }, + open: function() { + ok( true, "menu opened" ); } - same( ac.val(), "java" ); - }, - open: function() { - ok(true); - } - }); - stop(); - ac.val("ja").keydown(); + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).keydown(); setTimeout(function() { - same( $(".ui-menu:visible").length, 0 ); - ac.val("java").keydown(); + ok( menu.is( ":hidden" ), "menu is hidden after first search" ); + element.val( "java" ).keydown(); setTimeout(function() { - same( $(".ui-menu:visible").length, 1 ); - same( $(".ui-menu .ui-menu-item").length, 2 ); + ok( menu.is( ":visible" ), "menu is visible after second search" ); + equal( menu.find( ".ui-menu-item" ).length, 2, "# of menu items" ); start(); - }, 50); - }, 50); + }, 50 ); + }, 50 ); }); -test("cancel focus", function() { - expect(1); - var customVal = 'custom value'; - var ac = $("#autocomplete").autocomplete({ - delay: 0, - source: data, - focus: function(event, ui) { - $(this).val(customVal); - return false; - } - }); - stop(); - ac.val("ja").keydown(); +asyncTest( "cancel focus", function() { + expect( 1 ); + var customVal = "custom value"; + element = $( "#autocomplete" ).autocomplete({ + delay: 0, + source: data, + focus: function( event, ui ) { + $( this ).val( customVal ); + return false; + } + }); + element.val( "ja" ).keydown(); setTimeout(function() { - ac.simulate("keydown", { keyCode: $.ui.keyCode.DOWN }); - same( ac.val(), customVal ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + equal( element.val(), customVal ); start(); - }, 50); + }, 50 ); }); -test("cancel select", function() { - expect(1); - var customVal = 'custom value'; - var ac = $("#autocomplete").autocomplete({ - delay: 0, - source: data, - select: function(event, ui) { - $(this).val(customVal); - return false; - } - }); - stop(); - ac.val("ja").keydown(); +asyncTest( "cancel select", function() { + expect( 1 ); + var customVal = "custom value", + element = $( "#autocomplete" ).autocomplete({ + delay: 0, + source: data, + select: function( event, ui ) { + $( this ).val( customVal ); + return false; + } + }); + element.val( "ja" ).keydown(); setTimeout(function() { - ac.simulate("keydown", { keyCode: $.ui.keyCode.DOWN }); - ac.simulate("keydown", { keyCode: $.ui.keyCode.ENTER }); - same( ac.val(), customVal ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); + element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); + equal( element.val(), customVal ); start(); - }, 50); + }, 50 ); }); /* TODO previous fix broke more than it fixed, disabling this for now - messed up regular menu select event @@ -215,10 +206,10 @@ test("blur without selection", function() { setTimeout(function() { $( ".ui-menu-item" ).first().simulate("mouseover"); ac.simulate("keydown", { keyCode: $.ui.keyCode.TAB }); - same( ac.val(), "j" ); + deepEqual( ac.val(), "j" ); start(); }, 50); }); */ -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/autocomplete/autocomplete_methods.js b/tests/unit/autocomplete/autocomplete_methods.js index 1043e47ba..3fe035d28 100644 --- a/tests/unit/autocomplete/autocomplete_methods.js +++ b/tests/unit/autocomplete/autocomplete_methods.js @@ -1,39 +1,30 @@ -/* - * autocomplete_methods.js - */ -(function($) { +(function( $ ) { +module( "autocomplete: methods" ); -module("autocomplete: methods", { - teardown: function() { - $( ":ui-autocomplete" ).autocomplete( "destroy" ); - } +test( "destroy", function() { + expect( 1 ); + domEqual( "#autocomplete", function() { + $( "#autocomplete" ).autocomplete().autocomplete( "destroy" ); + }); }); -test("destroy", function() { - domEqual("#autocomplete", function() { - $("#autocomplete").autocomplete().autocomplete("destroy"); - }); -}) +test( "search", function() { + expect( 3 ); + var data = [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl" ], + element = $( "#autocomplete" ).autocomplete({ + source: data, + minLength: 0 + }), + menu = element.autocomplete( "widget" ); + element.autocomplete( "search" ); + equal( menu.find( ".ui-menu-item" ).length, data.length, "all items for a blank search" ); -var data = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl"]; + element.val( "has" ).autocomplete( "search" ); + equal( menu.find( ".ui-menu-item" ).text(), "haskell", "only one item for set input value" ); -test("search", function() { - var ac = $("#autocomplete").autocomplete({ - source: data, - minLength: 0 - }); - ac.autocomplete("search"); - same( $(".ui-menu .ui-menu-item").length, data.length, "all items for a blank search" ); - - ac.val("has"); - ac.autocomplete("search") - same( $(".ui-menu .ui-menu-item").text(), "haskell", "only one item for set input value" ); - - ac.autocomplete("search", "ja"); - same( $(".ui-menu .ui-menu-item").length, 2, "only java and javascript for 'ja'" ); - - $("#autocomplete").autocomplete("destroy"); -}) + element.autocomplete( "search", "ja" ); + equal( menu.find( ".ui-menu-item" ).length, 2, "only java and javascript for 'ja'" ); +}); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index f2da2f4aa..01c4e9fef 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -1,247 +1,192 @@ -/* - * autocomplete_options.js - */ -(function($) { - -module("autocomplete: options", { - teardown: function() { - $( ":ui-autocomplete" ).autocomplete( "destroy" ); - } -}); - +(function( $ ) { -/* disabled until autocomplete actually has built-in support for caching -// returns at most 4 items -function source(request) { - ok(true, "handling a request"); - switch(request.term) { - case "cha": - return ["Common Pochard", "Common Chiffchaff", "Common Chaffinch", "Iberian Chiffchaff"] - case "chaf": - case "chaff": - return ["Common Chiffchaff", "Common Chaffinch", "Iberian Chiffchaff"] - case "chaffi": - return ["Common Chaffinch"] - case "schi": - return ["schifpre"] - } -} +module( "autocomplete: options" ); -function search(input) { - var autocomplete = input.data("autocomplete"); - autocomplete.search("cha"); - autocomplete.close(); - autocomplete.search("chaf"); - autocomplete.close(); - autocomplete.search("chaff"); - autocomplete.close(); - autocomplete.search("chaffi"); - autocomplete.close(); - autocomplete.search("schi"); -} - -test("cache: default", function() { - expect(2); - search($("#autocomplete").autocomplete({ - source: source - })); -}); - -test("cache: {limit:4}", function() { - expect(3); - search($("#autocomplete").autocomplete({ - cache: { - limit: 4 - }, - source: source - })); -}); - -test("cache: false", function() { - expect(5); - search($("#autocomplete").autocomplete({ - cache: false, - source: source - })); -}); -*/ - -var data = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl"]; +var data = [ "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl" ]; test( "appendTo", function() { - var ac = $( "#autocomplete" ).autocomplete(); - same( ac.autocomplete( "widget" ).parent()[0], document.body, "defaults to body" ); - ac.autocomplete( "destroy" ); - - ac.autocomplete({ - appendTo: "#ac-wrap2" - }); - same( ac.autocomplete( "widget" ).parent()[0], $( "#ac-wrap2" )[0], "id" ); - ac.autocomplete( "destroy" ); + expect( 5 ); + var element = $( "#autocomplete" ).autocomplete(); + equal( element.autocomplete( "widget" ).parent()[0], document.body, "defaults to body" ); + element.autocomplete( "destroy" ); - ac.autocomplete({ + element.autocomplete({ appendTo: ".ac-wrap" }); - same( ac.autocomplete( "widget" ).parent()[0], $( "#ac-wrap1" )[0], "class" ); - same( $( "#ac-wrap2 .ui-autocomplete").length, 0, "class - only appends to one element") - ac.autocomplete( "destroy" ); + equal( element.autocomplete( "widget" ).parent()[0], $( "#ac-wrap1" )[0], "first found element" ); + equal( $( "#ac-wrap2 .ui-autocomplete" ).length, 0, "only appends to one element" ); + element.autocomplete( "destroy" ); - ac.autocomplete({ + element.autocomplete({ appendTo: null }); - same( ac.autocomplete( "widget" ).parent()[0], document.body, "null" ); - ac.autocomplete( "destroy" ); - - ac.autocomplete().autocomplete( "option", "appendTo", "#ac-wrap1" ); - same( ac.autocomplete( "widget" ).parent()[0], $( "#ac-wrap1" )[0], "modified after init" ); - ac.autocomplete( "destroy" ); + equal( element.autocomplete( "widget" ).parent()[0], document.body, "null" ); + element.autocomplete( "destroy" ); + + element.autocomplete().autocomplete( "option", "appendTo", "#ac-wrap1" ); + equal( element.autocomplete( "widget" ).parent()[0], $( "#ac-wrap1" )[0], "modified after init" ); + element.autocomplete( "destroy" ); }); function autoFocusTest( afValue, focusedLength ) { - var ac = $( "#autocomplete" ).autocomplete({ + var element = $( "#autocomplete" ).autocomplete({ autoFocus: afValue, delay: 0, source: data, open: function( event, ui ) { - equal( ac.autocomplete( "widget" ).children( ".ui-menu-item:first .ui-state-focus" ).length, focusedLength, "first item is " + afValue ? "" : "not" + " auto focused" ); - start(); + equal( element.autocomplete( "widget" ).children( ".ui-menu-item:first .ui-state-focus" ).length, + focusedLength, "first item is " + (afValue ? "" : "not") + " auto focused" ); + start(); } }); - ac.val( "ja" ).keydown(); + element.val( "ja" ).keydown(); stop(); } test( "autoFocus: false", function() { + expect( 1 ); autoFocusTest( false, 0 ); }); test( "autoFocus: true", function() { + expect( 1 ); autoFocusTest( true, 1 ); }); -test("delay", function() { - var ac = $("#autocomplete").autocomplete({ - source: data, - delay: 50 - }); - ac.val("ja").keydown(); - - same( $(".ui-menu:visible").length, 0 ); - - // wait half a second for the default delay to open the menu - stop(); - setTimeout(function() { - same( $(".ui-menu:visible").length, 1 ); - ac.autocomplete("destroy"); - start(); - }, 100); -}); +asyncTest( "delay", function() { + expect( 2 ); + var element = $( "#autocomplete" ).autocomplete({ + source: data, + delay: 50 + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).keydown(); + + ok( menu.is( ":hidden" ), "menu is closed immediately after search" ); -test("disabled", function() { - var ac = $("#autocomplete").autocomplete({ - source: data, - delay: 0, - disabled: true - }); - ac.val("ja").keydown(); - - same( $(".ui-menu:visible").length, 0 ); - - stop(); setTimeout(function() { - same( $(".ui-menu:visible").length, 0 ); - ac.autocomplete("destroy"); + ok( menu.is( ":visible" ), "menu is open after delay" ); start(); - }, 50); + }, 100 ); }); -test("minLength", function() { - var ac = $("#autocomplete").autocomplete({ - source: data - }); - ac.autocomplete("search", ""); - same( $(".ui-menu:visible").length, 0, "blank not enough for minLength: 1" ); - - ac.autocomplete("option", "minLength", 0); - ac.autocomplete("search", ""); - same( $(".ui-menu:visible").length, 1, "blank enough for minLength: 0" ); - ac.autocomplete("destroy"); -}); +asyncTest( "disabled", function() { + expect( 2 ); + var element = $( "#autocomplete" ).autocomplete({ + source: data, + delay: 0, + disabled: true + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).keydown(); -test("source, local string array", function() { - var ac = $("#autocomplete").autocomplete({ - source: data - }); - ac.val("ja").autocomplete("search"); - same( $(".ui-menu .ui-menu-item").text(), "javajavascript" ); - ac.autocomplete("destroy"); -}); + ok( menu.is( ":hidden" ) ); -function source_test(source, async) { - var ac = $("#autocomplete").autocomplete({ - source: source - }); - ac.val("ja").autocomplete("search"); - function result(){ - same( $(".ui-menu .ui-menu-item").text(), "javajavascript" ); - ac.autocomplete("destroy"); - async && start(); + setTimeout(function() { + ok( menu.is( ":hidden" ) ); + start(); + }, 50 ); +}); + +test( "minLength", function() { + expect( 2 ); + var element = $( "#autocomplete" ).autocomplete({ + source: data + }), + menu = element.autocomplete( "widget" ); + element.autocomplete( "search", "" ); + ok( menu.is( ":hidden" ), "blank not enough for minLength: 1" ); + + element.autocomplete( "option", "minLength", 0 ); + element.autocomplete( "search", "" ); + ok( menu.is( ":visible" ), "blank enough for minLength: 0" ); +}); + +test( "source, local string array", function() { + expect( 1 ); + var element = $( "#autocomplete" ).autocomplete({ + source: data + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).autocomplete( "search" ); + equal( menu.find( ".ui-menu-item" ).text(), "javajavascript" ); +}); + +function sourceTest( source, async ) { + var element = $( "#autocomplete" ).autocomplete({ + source: source + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).autocomplete( "search" ); + function result() { + equal( menu.find( ".ui-menu-item" ).text(), "javajavascript" ); + element.autocomplete( "destroy" ); + if ( async ) { + start(); + } } - if (async) { + if ( async ) { stop(); - $(document).one("ajaxStop", result); + $( document ).one( "ajaxStop", result ); } else { result(); } } -test("source, local object array, only label property", function() { - source_test([ - {label:"java"}, - {label:"php"}, - {label:"coldfusion"}, - {label:"javascript"} +test( "source, local object array, only label property", function() { + expect( 1 ); + sourceTest([ + { label: "java" }, + { label: "php" }, + { label: "coldfusion" }, + { label: "javascript" } ]); }); -test("source, local object array, only value property", function() { - source_test([ - {value:"java"}, - {value:"php"}, - {value:"coldfusion"}, - {value:"javascript"} +test( "source, local object array, only value property", function() { + expect( 1 ); + sourceTest([ + { value: "java" }, + { value: "php" }, + { value: "coldfusion" }, + { value: "javascript" } ]); }); -test("source, url string with remote json string array", function() { - source_test("remote_string_array.txt", true); +test( "source, url string with remote json string array", function() { + expect( 1 ); + sourceTest( "remote_string_array.txt", true ); }); -test("source, url string with remote json object array, only value properties", function() { - source_test("remote_object_array_values.txt", true); +test( "source, url string with remote json object array, only value properties", function() { + expect( 1 ); + sourceTest( "remote_object_array_values.txt", true ); }); -test("source, url string with remote json object array, only label properties", function() { - source_test("remote_object_array_labels.txt", true); +test( "source, url string with remote json object array, only label properties", function() { + expect( 1 ); + sourceTest( "remote_object_array_labels.txt", true ); }); -test("source, custom", function() { - source_test(function(request, response) { - same( request.term, "ja" ); - response(["java", "javascript"]); +test( "source, custom", function() { + expect( 2 ); + sourceTest(function( request, response ) { + equal( request.term, "ja" ); + response( ["java", "javascript"] ); }); }); -test("source, update after init", function() { - var ac = $("#autocomplete").autocomplete({ - source: ["java", "javascript", "haskell"] - }); - ac.val("ja").autocomplete("search"); - same( $(".ui-menu .ui-menu-item").text(), "javajavascript" ); - ac.autocomplete("option", "source", ["php", "asp"]); - ac.val("ph").autocomplete("search"); - same( $(".ui-menu .ui-menu-item").text(), "php" ); - ac.autocomplete("destroy"); +test( "source, update after init", function() { + expect( 2 ); + var element = $( "#autocomplete" ).autocomplete({ + source: [ "java", "javascript", "haskell" ] + }), + menu = element.autocomplete( "widget" ); + element.val( "ja" ).autocomplete( "search" ); + equal( menu.find( ".ui-menu-item" ).text(), "javajavascript" ); + element.autocomplete( "option", "source", [ "php", "asp" ] ); + element.val( "ph" ).autocomplete( "search" ); + equal( menu.find( ".ui-menu-item" ).text(), "php" ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/effects/effects.html b/tests/unit/effects/effects.html index 84fecd9cc..e3c6d2f4e 100644 --- a/tests/unit/effects/effects.html +++ b/tests/unit/effects/effects.html @@ -28,32 +28,54 @@ <script src="../../jquery.simulate.js"></script> <script src="../testsuite.js"></script> <script src="effects_core.js"></script> - + <script src="effects_scale.js"></script> + <script src="../swarminject.js"></script> <style type="text/css"> - .hidden { - display: none; - } - .test { - background: #000; - border: 0; - width: 100px; - height: 100px; - } - .testAddBorder { - border: 10px solid #000; - } - .testChildren, - .testChangeBackground { - background: #fff; - } - .test h2 { - font-size: 10px; - } - .testChildren h2 { - font-size: 20px; - } + #qunit-fixture { + width: 1000px; + height: 1000px; + } + .hidden { + display: none; + } + .test { + background: #000; + border: 0; + width: 100px; + height: 100px; + } + .testAddBorder { + border: 10px solid #000; + } + .testChildren, + .testChangeBackground { + background: #fff; + } + .test h2 { + font-size: 10px; + } + .testChildren h2 { + font-size: 20px; + } + + .relWidth { + width: 50%; + } + + .relHeight { + height: 50%; + } + + .testScale { + border: 5px solid #000; + padding: 5px; + margin: 5px; + width: 50px; + height: 50px; + } + </style> </head> <body> @@ -70,6 +92,11 @@ <div class="animateClass test"> <h2>Child Element Test</h2> </div> + <div class="relWidth relHeight testAddBorder"> + <h2>Slide with relative width</d2> + </div> + <div class="testScale"> + </div> </div> </body> diff --git a/tests/unit/effects/effects_core.js b/tests/unit/effects/effects_core.js index ed9fbf9ba..4c685ebb6 100644 --- a/tests/unit/effects/effects_core.js +++ b/tests/unit/effects/effects_core.js @@ -54,6 +54,21 @@ $.each( $.effects.effect, function( effect ) { start(); })); }); + + asyncTest( "relative width & height - properties are preserved", function() { + var test = $("div.relWidth.relHeight"), + width = test.width(), height = test.height(), + cssWidth = test[0].style.width, cssHeight = test[0].style.height; + + expect( 4 ); + test.toggle( effect, minDuration, function() { + equal( test[0].style.width, cssWidth, "Inline CSS Width has been reset after animation ended" ); + equal( test[0].style.height, cssHeight, "Inline CSS Height has been rest after animation ended" ); + start(); + }); + equal( test.width(), width, "Width is the same px after animation started" ); + equal( test.height(), height, "Height is the same px after animation started" ); + }); }); module("animateClass"); diff --git a/tests/unit/effects/effects_scale.js b/tests/unit/effects/effects_scale.js new file mode 100644 index 000000000..1436cd030 --- /dev/null +++ b/tests/unit/effects/effects_scale.js @@ -0,0 +1,61 @@ +(function( $ ) { +module( "effect.scale: Scale" ); + +function run( position, v, h, vo, ho ) { + var desc = "End Position Correct: " + position + " (" + v + "," + h + ") - origin: (" + vo + "," + ho + ")"; + asyncTest( desc, function() { + var test = $( ".testScale" ), + css = { + position: position + }, + effect = { + effect: "scale", + mode: "effect", + percent: 200, + origin: [ vo, ho ], + complete: complete, + duration: 1 + }, + target = {}, + relative = position === "relative"; + + css[ h ] = 33; + css[ v ] = 33; + target[ h ] = h === ho ? css[ h ] : ho == "center" ? css[ h ] - 35 : css[ h ] - 70; + target[ v ] = v === vo ? css[ v ] : vo == "middle" ? css[ v ] - 35 : css[ v ] - 70; + if ( relative && h == "right" ) { + target[ h ] += 70; + } + if ( relative && v == "bottom" ) { + target[ v ] += 70; + } + test.css( css ); + test.effect( effect ); + + function complete() { + equal( parseInt( test.css( h ), 10 ), target[ h ], "Horizontal Position Correct " + desc ); + equal( parseInt( test.css( v ), 10 ), target[ v ], "Vertical Position Correct " + desc ); + start(); + } + }); +} + +function suite( position ) { + run( position, "top", "left", "top", "left" ); + run( position, "top", "left", "middle", "center" ); + run( position, "top", "left", "bottom", "right" ); + run( position, "bottom", "right", "top", "left" ); + run( position, "bottom", "right", "middle", "center" ); + run( position, "bottom", "right", "bottom", "right" ); +} + +$(function() { + suite( "absolute" ); + suite( "relative" ); + $.offset.initialize(); + if ( $.offset.supportsFixedPosition ) { + suite( "fixed" ); + } +}); + +})( jQuery ); diff --git a/tests/unit/position/position.html b/tests/unit/position/position.html index 4f2e87e08..d71bae497 100644 --- a/tests/unit/position/position.html +++ b/tests/unit/position/position.html @@ -16,47 +16,54 @@ <script src="../testsuite.js"></script> <script src="position_core.js"></script> + <script src="position_core_within.js"></script> <script src="../swarminject.js"></script> </head> <body> - -<h1 id="qunit-header">jQuery UI Position 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 style="position:relative; z-index:2;"> + <h1 id="qunit-header">jQuery UI Position 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> <!-- elements smaller than 10px have a line-height set on them to avoid a bug in IE6 .height() returns the greater of the height and line-height --> -<div id="qunit-fixture" style="top: 0; left: 0;"> - <div id="el1" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div> - <div id="el2" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div> - <div id="parent" style="position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;"></div> -</div> - -<div style="position: absolute; top: 0px; left: 0px"> - <div id="elx" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> - <div id="parentx" style="position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;"></div> +<div id="qunit-fixture" style="top: 0; left: 0; z-index:1"> + <div id="within-container"> + <div id="el1" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div> + <div id="el2" style="position: absolute; width: 6px; height: 6px; line-height: 6px;"></div> + <div id="parent" style="position: absolute; width: 6px; height: 6px; top: 4px; left: 4px; line-height: 6px;"></div> + + <div style="position: absolute; top: 0px; left: 0px"> + <div id="elx" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> + <div id="parentx" style="position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;"></div> + </div> + + <div style="position: absolute; top: 200px; left: 100px;"> + <div id="el-offset-100-200" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> + <div style="position: absolute; top: 100px; left: 50px;"> + <div id="el-two-offset-150-300" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> + <div id="el-fixed" style="position: fixed; top: 200px; left: 200px;"></div> + </div> + </div> + + <div style="position: absolute; height: 5000px; width: 5000px;"></div> + + <div id="bug-5280" style="height: 30px; width: 201px;"> + <div style="width: 50px; height: 10px;"></div> + </div> + </div> </div> -<div style="position: absolute; top: 200px; left: 100px;"> - <div id="el-offset-100-200" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> - <div style="position: absolute; top: 100px; left: 50px;"> - <div id="el-two-offset-150-300" style="position: absolute; width: 10px; height: 10px; line-height: 10px;"></div> - <div id="el-fixed" style="position: fixed; top: 200px; left: 200px;"></div> - </div> -</div> -<div style="position: absolute; height: 5000px; width: 5000px;"></div> -<div id="bug-5280" style="height: 30px; width: 201px;"> - <div style="width: 50px; height: 10px;"></div> -</div> </body> </html> diff --git a/tests/unit/position/position_core.js b/tests/unit/position/position_core.js index dbbda8a3b..bd8e58612 100644 --- a/tests/unit/position/position_core.js +++ b/tests/unit/position/position_core.js @@ -64,7 +64,6 @@ test( "positions", function() { center: 3, right: 6, top: 0, - center: 3, bottom: 6 }; var start = { left: 4, top: 4 }; @@ -316,6 +315,7 @@ test( "collision: fit, window scrolled", function() { if ( scrollTopSupport() ) { var win = $( window ); win.scrollTop( 300 ).scrollLeft( 200 ); + collisionTest({ collision: "fit", at: "left-100 top-100" @@ -324,6 +324,7 @@ test( "collision: fit, window scrolled", function() { collision: "fit", at: "right+100 bottom+100" }, { top: 300 + win.height() - 10, left: 200 + win.width() - 10 }, "right bottom" ); + win.scrollTop( 0 ).scrollLeft( 0 ); } }); @@ -351,7 +352,7 @@ test( "collision: flip, with offset", function() { collisionTest2({ collision: "flip", - at: "left-2 top-3", + at: "left-2 top-3" }, { top: $( window ).height() + 3, left: $( window ).width() + 2 }, "right bottom, negative offset" ); }); diff --git a/tests/unit/position/position_core_within.js b/tests/unit/position/position_core_within.js new file mode 100644 index 000000000..567c17192 --- /dev/null +++ b/tests/unit/position/position_core_within.js @@ -0,0 +1,441 @@ +(function( $ ) { + +function scrollTopSupport() { + $( window ).scrollTop( 1 ); + return $( window ).scrollTop() === 1; +} + +module( "position - within", { + setup: function(){ + $("#within-container").css({"width": "500px", "height": "500px", "top": "20px", "left": "20px", "position": "relative"}).show(); + } +}); + +var addTop = -20, + addLeft = -20; + +$.fn.addOffsets = function() { + var elOffset = this.offset(), + offset = $("#within-container").offset(); + + elOffset.top -= offset.top; + elOffset.left -= offset.left; + + return {top: elOffset.top - offset.top, left: elOffset.left - offset.left }; +}; + +test( "my, at, of", function() { + var within = $("#within-container"); + + $( "#elx" ).position({ + my: "left top", + at: "left top", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 40, left: addLeft + 40 }, "left top, left top" ); + + $( "#elx" ).position({ + my: "left top", + at: "left bottom", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 60, left: addLeft + 40 }, "left top, left bottom" ); + + $( "#elx" ).position({ + my: "left", + at: "bottom", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 55, left: addLeft + 50 }, "left, bottom" ); + + $( "#elx" ).position({ + my: "left foo", + at: "bar baz", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 45, left: addLeft +50 }, "left foo, bar baz" ); +}); + +test( "multiple elements", function() { + var elements = $( "#el1, #el2" ); + var result = elements.position({ + my: "left top", + at: "left bottom", + of: "#parent", + collision: "none", + within: $("#within-container") + }); + + same( result, elements ); + var expected = { top: addTop + 10, left: addLeft + 4 }; + elements.each(function() { + same( $( this ).addOffsets(), expected ); + }); +}); + +test( "positions", function() { + var definitions = []; + var offsets = { + left: 0, + center: 3, + right: 6, + top: 0, + bottom: 6 + }; + var start = { left: 4, top: 4 }; + $.each( [ 0, 1 ], function( my ) { + $.each( [ "top", "center", "bottom" ], function( vindex, vertical ) { + $.each( [ "left", "center", "right" ], function( hindex, horizontal ) { + definitions.push({ + my: my ? horizontal + " " + vertical : "left top", + at: !my ? horizontal + " " + vertical : "left top", + result: { + top: addTop + (my ? start.top - offsets[ vertical ] : start.top + offsets[ vertical ]), + left: addLeft + (my ? start.left - offsets[ horizontal ] : start.left + offsets[ horizontal ]) + } + }); + }); + }); + }); + var el = $( "#el1" ); + $.each( definitions, function( index, definition ) { + el.position({ + my: definition.my, + at: definition.at, + of: "#parent", + collision: "none", + within: $("#within-container") + }); + same( el.addOffsets(), definition.result, + "Position via " + QUnit.jsDump.parse({ my:definition.my, at:definition.at }) ); + }); +}); + +test( "of", function() { + var within = $("#within-container"); + + $( "#elx" ).position({ + my: "left top", + at: "left top", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 40, left: addLeft + 40 }, "selector" ); + + $( "#elx" ).position({ + my: "left top", + at: "left bottom", + of: $( "#parentx"), + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 60, left: addLeft + 40 }, "jQuery object" ); + + $( "#elx" ).position({ + my: "left top", + at: "left top", + of: $( "#parentx" )[ 0 ], + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 40, left: addLeft + 40 }, "DOM element" ); + + var event = $.extend( $.Event( "someEvent" ), { pageX: 200, pageY: 300 } ); + $( "#elx" ).position({ + my: "left top", + at: "left top", + of: event, + collision: "none", + within: within + }); + same( $( "#elx" ).offset(), { + top: 300, + left: 200 + }, "event - left top, left top" ); + + event = $.extend( $.Event( "someEvent" ), { pageX: 400, pageY: 600 } ); + $( "#elx" ).position({ + my: "left top", + at: "right bottom", + of: event, + collision: "none", + within: within + }); + same( $( "#elx" ).offset(), { + top: 600, + left: 400 + }, "event - left top, right bottom" ); +}); + +test( "within:offsets", function() { + var within = $("#within-container"); + + $( "#elx" ).position({ + my: "left top", + at: "left+10 bottom+10", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 70, left: addLeft + 50 }, "offsets in at" ); + + $( "#elx" ).position({ + my: "left+10 top-10", + at: "left bottom", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 50, left: addLeft + 50 }, "offsets in my" ); + + $( "#elx" ).position({ + my: "left top", + at: "left+50% bottom-10%", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 58, left: addLeft + 50 }, "percentage offsets in at" ); + + $( "#elx" ).position({ + my: "left-30% top+50%", + at: "left bottom", + of: "#parentx", + collision: "none", + within: within + }); + same( $( "#elx" ).addOffsets(), { top: addTop + 65, left: addLeft + 37 }, "percentage offsets in my" ); +}); + +test( "using", function() { + expect( 6 ); + + var within = $("#within-container"); + + var count = 0, + elems = $( "#el1, #el2" ), + expectedPosition = { top: addTop + 40, left: addLeft + 40 }, + originalPosition = elems.position({ + my: "right bottom", + at: "rigt bottom", + of: "#parentx", + collision: "none", + within: within + }).addOffsets(); + + elems.position({ + my: "left top", + at: "left top", + of: "#parentx", + using: function( position ) { + position.top -= within.offset().top; + position.left -= within.offset().left; + same( this, elems[ count ], "correct context for call #" + count ); + same( position, expectedPosition, "correct position for call #" + count ); + count++; + }, + within: within + }); + + elems.each(function() { + same( $( this ).addOffsets(), originalPosition, "elements not moved" ); + }); +}); + +function collisionTest( config, result, msg ) { + var within = $("#within-container"); + + var elem = $( "#elx" ).position( $.extend({ + my: "left top", + at: "right bottom", + of: within[0], + within: within + }, config ) ); + + same( elem.addOffsets(), result, msg ); +} + +function collisionTest2( config, result, msg ) { + collisionTest( $.extend({ + my: "right bottom", + at: "left top" + }, config ), result, msg ); +} + +test( "collision: fit, no offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "fit" + }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" ); + + collisionTest2({ + collision: "fit" + }, { top: addTop + 0, left: addLeft + 0 }, "left top" ); +}); + + +test( "collision: fit, with offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "fit", + at: "right+2 bottom+3" + }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom"); + + collisionTest2({ + collision: "fit", + at: "left+2 top+3" + }, { top: addTop + 0, left: addLeft + 0 }, "left top, positive offset" ); + + collisionTest2({ + collision: "fit", + at: "left-2 top-3" + }, { top: addTop + 0, left: addLeft + 0 }, "left top, negative offset" ); +}); + +test( "collision: fit, within scrolled", function() { + if ( scrollTopSupport() ) { + var within = $("#within-container").css({"width": "1000px", "height": "800px", "overflow": "auto"}); + within.scrollTop( 300 ).scrollLeft( 150 ); + + collisionTest({ + collision: "fit", + at: "left-100 top-100" + }, { top: addTop, left: addLeft }, "top left" ); + collisionTest2({ + collision: "fit", + at: "right+100 bottom+100" + }, { top: addTop + within.height() - 10 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 10 - $.position.getScrollInfo( within ).width }, "right bottom" ); + within.scrollTop( 0 ).scrollLeft( 0 ); + } +}); + +test( "collision: flip, no offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "flip" + }, { top: addTop + -10, left: addLeft + -10 }, "left top" ); + + collisionTest2({ + collision: "flip" + }, { top: addTop + within.height(), left: addLeft + within.width() }, "right bottom" ); +}); + +test( "collision: flip, with offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "flip", + at: "right+2 bottom+3" + }, { top: addTop + -13, left: addLeft + -12 }, "left top, with offset added" ); + + collisionTest2({ + collision: "flip", + at: "left+2 top+3" + }, { top: addTop + within.height() - 3, left: addLeft + within.width() - 2 }, "bottom, positive offset" ); + + collisionTest2({ + collision: "flip", + at: "left-2 top-3" + }, { top: addTop + within.height() + 3, left: addLeft + within.width() + 2 }, "right bottom, negative offset" ); +}); + +test( "collision: none, no offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "none" + }, { top: addTop + within.height(), left: addLeft + within.width() }, "left top" ); + + collisionTest2({ + collision: "none" + }, { top: addTop + -10, left: addLeft + -10 }, "moved to the right bottom" ); +}); + +test( "collision: none, with offset", function() { + var within = $("#within-container"); + + collisionTest({ + collision: "none", + at: "right+2 bottom+3" + }, { top: addTop + within.height() + 3, left: addLeft + within.width() + 2 }, "right bottom, with offset added" ); + + collisionTest2({ + collision: "none", + at: "left+2 top+3" + }, { top: addTop + -7, left: addLeft + -8 }, "left top, positive offset" ); + + collisionTest2({ + collision: "none", + at: "left-2 top-3" + }, { top: addTop + -13, left: addLeft + -12 }, "left top, negative offset" ); +}); + +test( "collision: fit, with margin", function() { + var within = $("#within-container"); + + $( "#elx" ).css( "margin", 10 ); + + collisionTest({ + collision: "fit" + }, { top: addTop + within.height() - 20 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 20 - $.position.getScrollInfo( within ).width }, "right bottom" ); + + collisionTest2({ + collision: "fit" + }, { top: addTop + 10, left: addLeft + 10 }, "left top" ); + + $( "#elx" ).css({ + "margin-left": 5, + "margin-top": 5 + }); + + collisionTest({ + collision: "fit" + }, { top: addTop + within.height() - 20 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 20 - $.position.getScrollInfo( within ).width }, "right bottom" ); + + collisionTest2({ + collision: "fit" + }, { top: addTop + 5, left: addLeft + 5 }, "left top" ); + + $( "#elx" ).css({ + "margin-right": 15, + "margin-bottom": 15 + }); + + collisionTest({ + collision: "fit" + }, { top: addTop + within.height() - 25 - $.position.getScrollInfo( within ).height, left: addLeft + within.width() - 25 - $.position.getScrollInfo( within ).width }, "right bottom" ); + + collisionTest2({ + collision: "fit" + }, { top: addTop + 5, left: addLeft + 5 }, "left top" ); +}); + +test( "collision: flip, with margin", function() { + var within = $("#within-container"); + + $( "#elx" ).css( "margin", 10 ); + + collisionTest({ + collision: "flip", + at: "left top" + }, { top: addTop + within.height() - 10, left: addLeft + within.width() - 10 }, "left top" ); + + collisionTest2({ + collision: "flip", + at: "right bottom" + }, { top: addTop + 0, left: addLeft + 0 }, "right bottom" ); +}); + +}( jQuery ) ); diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 892336c50..bb21b74ea 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -413,6 +413,7 @@ test( ".option() - getter", function() { qux: [ "quux", "quuux" ] }); + same( div.testWidget( "option", "x" ), null, "non-existent option" ); same( div.testWidget( "option", "foo"), "bar", "single option - string" ); same( div.testWidget( "option", "baz"), 5, "single option - number" ); same( div.testWidget( "option", "qux"), [ "quux", "quuux" ], @@ -431,6 +432,24 @@ test( ".option() - getter", function() { "modifying returned options hash does not modify plugin instance" ); }); +test( ".option() - deep option getter", function() { + $.widget( "ui.testWidget", {} ); + var div = $( "<div>" ).testWidget({ + foo: { + bar: "baz", + qux: { + quux: "xyzzy" + } + } + }); + equal( div.testWidget( "option", "foo.bar" ), "baz", "one level deep - string" ); + deepEqual( div.testWidget( "option", "foo.qux" ), { quux: "xyzzy" }, + "one level deep - object" ); + equal( div.testWidget( "option", "foo.qux.quux" ), "xyzzy", "two levels deep - string" ); + equal( div.testWidget( "option", "x.y" ), null, "top level non-existent" ); + equal( div.testWidget( "option", "foo.x.y" ), null, "one level deep - non-existent" ); +}); + test( ".option() - delegate to ._setOptions()", function() { var calls = []; $.widget( "ui.testWidget", { diff --git a/tests/visual/effects.all.css b/tests/visual/effects/effects.all.css index d2ed94026..1d531b026 100644 --- a/tests/visual/effects.all.css +++ b/tests/visual/effects/effects.all.css @@ -5,6 +5,7 @@ body,html { font-size: 12px; font-family: Arial; background: #191919; + color: #fff; } body { margin: 1em; } diff --git a/tests/visual/effects.all.html b/tests/visual/effects/effects.all.html index fed35de8a..a2f8f62ef 100644 --- a/tests/visual/effects.all.html +++ b/tests/visual/effects/effects.all.html @@ -1,25 +1,25 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> - <meta charset="UTF-8" /> + <meta charset="utf-8"> <title>jQuery UI Effects Test Suite</title> - <link rel="stylesheet" href="effects.all.css" type="text/css" /> - <script type="text/javascript" src="../../jquery-1.5.1.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.core.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.blind.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.bounce.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.clip.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.drop.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.explode.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.fade.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.fold.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.highlight.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.pulsate.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.scale.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.shake.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.slide.js"></script> - <script type="text/javascript" src="../../ui/jquery.effects.transfer.js"></script> - <script type="text/javascript" src="effects.all.js"></script> + <link rel="stylesheet" href="effects.all.css" type="text/css"> + <script src="../../../jquery-1.5.1.js"></script> + <script src="../../../ui/jquery.effects.core.js"></script> + <script src="../../../ui/jquery.effects.blind.js"></script> + <script src="../../../ui/jquery.effects.bounce.js"></script> + <script src="../../../ui/jquery.effects.clip.js"></script> + <script src="../../../ui/jquery.effects.drop.js"></script> + <script src="../../../ui/jquery.effects.explode.js"></script> + <script src="../../../ui/jquery.effects.fade.js"></script> + <script src="../../../ui/jquery.effects.fold.js"></script> + <script src="../../../ui/jquery.effects.highlight.js"></script> + <script src="../../../ui/jquery.effects.pulsate.js"></script> + <script src="../../../ui/jquery.effects.scale.js"></script> + <script src="../../../ui/jquery.effects.shake.js"></script> + <script src="../../../ui/jquery.effects.slide.js"></script> + <script src="../../../ui/jquery.effects.transfer.js"></script> + <script src="effects.all.js"></script> </head> <body> diff --git a/tests/visual/effects.all.js b/tests/visual/effects/effects.all.js index a28c41a89..a28c41a89 100644 --- a/tests/visual/effects.all.js +++ b/tests/visual/effects/effects.all.js diff --git a/tests/visual/effects/effects.scale.html b/tests/visual/effects/effects.scale.html new file mode 100644 index 000000000..9521a1872 --- /dev/null +++ b/tests/visual/effects/effects.scale.html @@ -0,0 +1,159 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>jQuery UI Effects Test Suite</title> + <link rel="stylesheet" href="effects.all.css" type="text/css"> + <script src="../../../jquery-1.5.1.js"></script> + <script src="../../../ui/jquery.effects.core.js"></script> + <script src="../../../ui/jquery.effects.scale.js"></script> + <script src="effects.all.js"></script> + <script type="text/javascript" charset="utf-8"> + jQuery(function( $ ) { + var test = $( "#testBox" ), + opts = $( ".arg" ), + optsRev = $( opts.get().reverse() ), + doer = $( "#doAnim" ), + current = $( "#current" ), + cleanStyle = test[0].style, + total = 1; + + opts.each(function() { + total *= this.options.length; + }); + + opts.change( doAnim ); + doer.click( doAnim ); + $( "#cyclePrev" ).click(function() { + cycle( -1 ); + }); + $( "#cycleNext" ).click(function() { + cycle( 1 ); + }); + + function cycle( direction ) { + optsRev.each(function() { + var cur = this.selectedIndex, + next = cur + direction, + len = this.options.length; + + this.selectedIndex = ( next + len ) % len; + + if ( ( next+len ) % len === next ) return false; + }); + doAnim(); + } + + + function doAnim() { + var cur = 0; + opts.each(function() { + cur *= this.options.length + cur += this.selectedIndex; + }); + cur++; + current.text( "Configuration: " + cur + " of " + total ); + run.apply(test, opts.map(function() { + return $(this).val(); + }).get()); + } + + function run( position, v, h, vo, ho ) { + var el = this, + style = el[0].style, + effect = { + effect: "scale", + mode: "effect", + percent: 200, + origin: [ vo, ho ], + duration: 500 + }; + el.stop(true, true); + if ( typeof style === "object" ) { + style.cssText = ""; + } else { + el[0].style = ""; + } + el.css( "position", position ) + .css( h, 5 ) + .css( v, 5 ) + .delay( 100 ) + .effect( effect ); + } + }); + </script> + <style type="text/css"> + #testArea { +/* border: 5px dashed #777;*/ + width: 200px; + height: 200px; + position: relative; + } + #testBox { + width: 50px; + height: 50px; + background-color: #bada55; + color: black; + border: 10px solid #fff; + margin: 10px; + padding: 10px; + } + label { + display: block; + } + #controls { + position: absolute; + z-index: 300; + left: 50%; + top: 50%; + margin-left: -200px; + width: 400px; + opacity: 0.8; + } + </style> +</head> +<body> + <div id="testArea"> + <div id="testBox"> + </div> + </div> + <div id="controls"> + <label for="pos">Positioning + <select id="pos" class="arg"> + <option value="absolute">absolute</option> + <option value="relative">relative</option> + <option value="fixed">fixed</option> + </select> + </label> + <label for="vertPos">Vertical Positioning + <select id="vertPos" class="arg"> + <option value="top">top</option> + <option value="bottom">bottom</option> + </select> + </label> + <label for="horizPos">Horizontal Positioning + <select id="horizPos" class="arg"> + <option value="left">left</option> + <option value="right">right</option> + </select> + </label> + <label for="vertOrigin">Vertical Origin + <select id="vertOrigin" class="arg"> + <option value="top">top</option> + <option value="middle">middle</option> + <option value="bottom">bottom</option> + </select> + </label> + <label for="horizOrigin">Horizontal Origin + <select id="horizOrigin" class="arg"> + <option value="left">left</option> + <option value="center">center</option> + <option value="right">right</option> + </select> + </label><br /> + <label id="current">jQuery UI Scale Animation Test</label> + <button id="cyclePrev">Back</button> + <button id="doAnim">Run Animation</button> + <button id="cycleNext">Forward</button> + </div> +</body>
\ No newline at end of file diff --git a/tests/visual/position/position.html b/tests/visual/position/position.html index da0ff5170..11932da0e 100644 --- a/tests/visual/position/position.html +++ b/tests/visual/position/position.html @@ -35,7 +35,7 @@ <style> input, .ui-menu { position: absolute; } .ui-menu { width: 200px; } - html, body { width: 99%; height: 99% } + html, body { width: 99%; height: 99%; min-height:700px; min-width:700px; } #container { width: 95%; height: 95%; border: 1px solid black; margin: auto; } </style> </head> diff --git a/tests/visual/position/position_within.html b/tests/visual/position/position_within.html new file mode 100644 index 000000000..f120a4b47 --- /dev/null +++ b/tests/visual/position/position_within.html @@ -0,0 +1,189 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>Position Visual Test: Containing Element</title> + + <link rel="stylesheet" href="../visual.css" type="text/css" /> + <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css" type="text/css" title="ui-theme" /> + + <script type="text/javascript" src="../../../jquery-1.5.1.js"></script> + <script type="text/javascript" src="../../../ui/jquery.ui.core.js"></script> + <script type="text/javascript" src="../../../ui/jquery.ui.widget.js"></script> + <script type="text/javascript" src="../../../ui/jquery.ui.mouse.js"></script> + <script type="text/javascript" src="../../../ui/jquery.ui.draggable.js"></script> + <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script> + + <style> + html, body { + height:100%; + width:100%; + margin:0; + /* force scroll bar*/ + min-height:800px; + min-width:800px; + + /* IE6 needs this */ + text-align:center; + } + .demo-description { + text-align:center; + padding:1.5em; + } + .demo-container { + background:#aaa; + width:80%; + height:80%; + + text-align:left; + margin:0 auto; + position:relative; + padding:10px; + } + .demo { + background:#eee; + overflow:hidden; + position:relative; + height:100%; + /* IE6 needs this */ + width:100%; + } + #parent { + width: 60%; + margin: 10px auto; + padding: 5px; + border: 1px solid #777; + background-color: #fbca93; + text-align: center; + cursor:move; + } + .positionable { + width: 75px; + height: 75px; + position: absolute; + display: block; + right: 0; + bottom: 0; + background-color: #bcd5e6; + text-align: center; + border:solid 2px #555; + cursor:move; + } + select, input { + margin-left: 15px; + } + </style> + <script> + $(function() { + function position( using ) { + $( ".positionable" ).position({ + of: $( "#parent" ), + my: $( "#my_horizontal" ).val() + " " + $( "#my_vertical" ).val(), + at: $( "#at_horizontal" ).val() + " " + $( "#at_vertical" ).val(), + offset: $( "#offset" ).val(), + using: using, + within: $( ".demo" ), + collision: $( "#collision_horizontal" ).val() + " " + $( "#collision_vertical" ).val() + }); + } + $( ".demo" ).append("<div style='width:5000px;height:5000px;' />").css("overflow","auto"); + + $( ".positionable" ).css( "opacity", 0.5 ); + + $( ":input" ).bind( "click keyup change", function() { position(); } ); + + $( "#parent" ).draggable({ + drag: function() { position(); } + }); + + $( ".positionable" ).draggable({ + drag: function( event, ui ) { + // reset offset before calculating it + $( "#offset" ).val( "0" ); + position(function( result ) { + var demo = $( ".demo" ); + $( "#offset" ).val( "" + ( ui.offset.left - result.left - demo.offset().left + demo.scrollLeft() ) + + " " + ( ui.offset.top - result.top - demo.offset().top + demo.scrollTop() ) ); + position(); + }); + } + }); + + position(); + }); + </script> +</head> +<body> + +<div class="demo-description"> + Use the form controls to configure the positioning, or drag the positioned element to modify its offset. + <br/>Drag around the parent element to see collision detection in action. +</div><!-- End demo-description --> + +<div class="demo-container"> +<div class="demo"> + + <div id="parent"> + <p>This is the position parent element.</p> + </div> + + <div class="positionable"> + <p>to position</p> + </div> + + <div class="positionable" style="width:120px; height: 40px;"> + <p>to position 2</p> + </div> + + <div style="padding: 20px; margin-top: 75px;"> + position... + <div style="padding-bottom: 20px;"> + <b>my:</b> + <select id="my_horizontal"> + <option value="left">left</option> + <option value="center">center</option> + <option value="right" selected="selected">right</option> + </select> + <select id="my_vertical"> + <option value="top">top</option> + <option value="middle">center</option> + <option value="bottom">bottom</option> + </select> + </div> + <div style="padding-bottom: 20px;"> + <b>at:</b> + <select id="at_horizontal"> + <option value="left">left</option> + <option value="center">center</option> + <option value="right" selected="selected">right</option> + </select> + <select id="at_vertical"> + <option value="top">top</option> + <option value="middle">center</option> + <option value="bottom">bottom</option> + </select> + </div> + <div style="padding-bottom: 20px;"> + <b>offset:</b> + <input id="offset" type="text" size="15"/> + </div> + <div style="padding-bottom: 20px;"> + <b>collision:</b> + <select id="collision_horizontal"> + <option value="flip">flip</option> + <option value="fit">fit</option> + <option value="none">none</option> + </select> + <select id="collision_vertical"> + <option value="flip">flip</option> + <option value="fit">fit</option> + <option value="none">none</option> + </select> + </div> + </div> + +</div><!-- End demo --> +</div> + +</body> +</html> diff --git a/themes/base/jquery.ui.base.css b/themes/base/jquery.ui.base.css index 9a18856c1..a359c2ba4 100644 --- a/themes/base/jquery.ui.base.css +++ b/themes/base/jquery.ui.base.css @@ -15,6 +15,7 @@ @import url("jquery.ui.datepicker.css"); @import url("jquery.ui.dialog.css"); @import url("jquery.ui.menu.css"); +@import url("jquery.ui.menubar.css"); @import url("jquery.ui.progressbar.css"); @import url("jquery.ui.resizable.css"); @import url("jquery.ui.selectable.css"); diff --git a/themes/base/jquery.ui.datepicker.css b/themes/base/jquery.ui.datepicker.css index f457800f4..8d574bac4 100644 --- a/themes/base/jquery.ui.datepicker.css +++ b/themes/base/jquery.ui.datepicker.css @@ -39,7 +39,7 @@ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; } +.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } /* RTL support */ .ui-datepicker-rtl { direction: rtl; } diff --git a/themes/base/jquery.ui.menu.css b/themes/base/jquery.ui.menu.css index ed4b4a13a..c616cf2c5 100644 --- a/themes/base/jquery.ui.menu.css +++ b/themes/base/jquery.ui.menu.css @@ -7,38 +7,14 @@ * * http://docs.jquery.com/UI/Menu#theming */ -.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - outline: none; -} -.ui-menu .ui-menu { - margin-top: -3px; -} -.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - width: 100%; -} -.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding: 2px .4em; - line-height:1.5; - zoom:1; - font-weight: normal; -} +.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; } +.ui-menu .ui-menu { margin-top: -3px; position: absolute; } +.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; } +.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; } .ui-menu .ui-menu-item a.ui-state-focus, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} +.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; } -/* nested menus */ -.ui-menu .ui-menu { position: absolute; } +.ui-menu li.ui-state-disabled { font-weight: normal; padding: .0em .4em; margin: .4em 0 .2em; line-height: 1.5; } /* icon support */ .ui-menu-icons { position: relative; } @@ -48,4 +24,4 @@ .ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; } /* right-aligned */ -.ui-menu .ui-menu-icon { position: static; float: right; }
\ No newline at end of file +.ui-menu .ui-menu-icon { position: static; float: right; } diff --git a/themes/base/jquery.ui.menubar.css b/themes/base/jquery.ui.menubar.css new file mode 100644 index 000000000..95c42ae9e --- /dev/null +++ b/themes/base/jquery.ui.menubar.css @@ -0,0 +1,15 @@ +/* + * jQuery UI Menubar @VERSION + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + */ +.ui-menubar { list-style: none; margin: 0; padding-left: 0; } + +.ui-menubar-item { float: left; } + +.ui-menubar .ui-button { float: left; font-weight: normal; border-top-width: 0 !important; border-bottom-width: 0 !important; margin: 0; outline: none; } +.ui-menubar .ui-menubar-link { border-right: 1px dashed transparent; border-left: 1px dashed transparent; } + +.ui-menubar .ui-menu { width: 200px; position: absolute; z-index: 9999; } diff --git a/themes/base/jquery.ui.theme.css b/themes/base/jquery.ui.theme.css index be2676909..368ebfbb5 100644 --- a/themes/base/jquery.ui.theme.css +++ b/themes/base/jquery.ui.theme.css @@ -182,8 +182,8 @@ .ui-icon-help { background-position: -48px -144px; } .ui-icon-check { background-position: -64px -144px; } .ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } .ui-icon-pin-w { background-position: -128px -144px; } .ui-icon-pin-s { background-position: -144px -144px; } .ui-icon-play { background-position: 0 -160px; } diff --git a/ui/jquery.effects.blind.js b/ui/jquery.effects.blind.js index 8ef544faa..b6485b641 100644 --- a/ui/jquery.effects.blind.js +++ b/ui/jquery.effects.blind.js @@ -21,7 +21,7 @@ $.effects.effect.blind = function( o ) { // Create element var el = $( this ), - props = [ "position", "top", "bottom", "left", "right" ], + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], mode = $.effects.setMode( el, o.mode || "hide" ), direction = o.direction || "up", vertical = rvertical.test( direction ), diff --git a/ui/jquery.effects.bounce.js b/ui/jquery.effects.bounce.js index 9e1117ce9..78fedb0ce 100644 --- a/ui/jquery.effects.bounce.js +++ b/ui/jquery.effects.bounce.js @@ -16,7 +16,7 @@ $.effects.effect.bounce = function(o) { return this.queue( function( next ) { var el = $( this ), - props = [ "position", "top", "bottom", "left", "right" ], + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], // defaults: mode = $.effects.setMode( el, o.mode || "effect" ), diff --git a/ui/jquery.effects.clip.js b/ui/jquery.effects.clip.js index 14b358dfa..dbf0d36c9 100644 --- a/ui/jquery.effects.clip.js +++ b/ui/jquery.effects.clip.js @@ -17,47 +17,52 @@ $.effects.effect.clip = function( o ) { return this.queue( function() { // Create element - var el = $( this ), - props = ['position','top','bottom','left','right','height','width'], - mode = $.effects.setMode( el, o.mode || 'hide' ), - direction = o.direction || 'vertical', - ref = { - size: (direction == 'vertical') ? 'height' : 'width', - position: (direction == 'vertical') ? 'top' : 'left' - }, + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "vertical", + vert = direction === "vertical", + size = vert ? "height" : "width", + position = vert ? "top" : "left", animation = {}, wrapper, animate, distance; // Save & Show - $.effects.save( el, props ); el.show(); + $.effects.save( el, props ); + el.show(); // Create Wrapper - wrapper = $.effects.createWrapper( el ).css({ - overflow: 'hidden' + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" }); - animate = ( el[0].tagName == 'IMG' ) ? wrapper : el; - distance = animate[ ref.size ](); + animate = ( el[0].tagName === "IMG" ) ? wrapper : el; + distance = animate[ size ](); // Shift - if ( mode == 'show' ) { - animate.css( ref.size, 0 ); - animate.css( ref.position, distance / 2 ); + if ( show ) { + animate.css( size, 0 ); + animate.css( position, distance / 2 ); } // Create Animation Object: - animation[ ref.size ] = mode == 'show' ? distance : 0; - animation[ ref.position ] = mode == 'show' ? 0 : distance / 2; + animation[ size ] = show ? distance : 0; + animation[ position ] = show ? 0 : distance / 2; // Animate - animate.animate( animation, { - queue: false, - duration: o.duration, - easing: o.easing, + animate.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, complete: function() { - mode == 'hide' && el.hide(); - $.effects.restore( el, props ); - $.effects.removeWrapper( el ); - $.isFunction( o.complete ) && o.complete.apply( el[ 0 ], arguments ); + if ( !show ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + if ( $.isFunction( o.complete ) ) { + o.complete.apply( el[ 0 ], arguments ); + } el.dequeue(); } }); diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index 7650aa8f4..00a803360 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -410,7 +410,12 @@ $.extend( $.effects, { border: "none", margin: 0, padding: 0 - }); + }), + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }; element.wrap( wrapper ); wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element @@ -438,6 +443,7 @@ $.extend( $.effects, { bottom: "auto" }); } + element.css(size); return wrapper.css( props ).show(); }, diff --git a/ui/jquery.effects.drop.js b/ui/jquery.effects.drop.js index 24fb89db0..4265b737b 100644 --- a/ui/jquery.effects.drop.js +++ b/ui/jquery.effects.drop.js @@ -17,7 +17,7 @@ $.effects.effect.drop = function( o ) { return this.queue( function() { var el = $( this ), - props = [ 'position', 'top', 'bottom', 'left', 'right', 'opacity' ], + props = [ 'position', 'top', 'bottom', 'left', 'right', 'opacity', "height", "width" ], mode = $.effects.setMode( el, o.mode || 'hide' ), direction = o.direction || 'left', ref = ( direction == 'up' || direction == 'down' ) ? 'top' : 'left', diff --git a/ui/jquery.effects.fold.js b/ui/jquery.effects.fold.js index 29da090cb..6100c33a1 100644 --- a/ui/jquery.effects.fold.js +++ b/ui/jquery.effects.fold.js @@ -18,7 +18,7 @@ $.effects.effect.fold = function( o ) { // Create element var el = $( this ), - props = ['position','top','bottom','left','right'], + props = ['position','top','bottom','left','right','height','width'], mode = $.effects.setMode(el, o.mode || 'hide'), size = o.size || 15, percent = /([0-9]+)%/.exec(size), diff --git a/ui/jquery.effects.scale.js b/ui/jquery.effects.scale.js index 00f0151af..e00d82497 100644 --- a/ui/jquery.effects.scale.js +++ b/ui/jquery.effects.scale.js @@ -116,10 +116,13 @@ $.effects.effect.size = function( o ) { // Set options mode = $.effects.setMode( el, o.mode || 'effect' ), - restore = o.restore || false, + restore = o.restore || mode !== "effect", scale = o.scale || 'both', - origin = o.origin, - original, baseline, factor; + origin = o.origin || [ "middle", "center" ], + original, baseline, factor, + position = el.css( "position" ), + originalVerticalPositioning = el.css( "bottom" ) !== "auto" ? "bottom" : "top"; + originalHorizontalPositioning = el.css( "right" ) !== "auto" ? "right" : "left"; if ( mode === "show" ) { el.show(); @@ -249,7 +252,47 @@ $.effects.effect.size = function( o ) { if( mode == 'hide' ) { el.hide(); } - $.effects.restore( el, restore ? props : props1 ); + $.effects.restore( el, restore ? props : props1 ); + + // we need to recalculate our positioning based on the new scaling + if ( position === "static" ) { + el.css({ + position: "relative", + top: el.to.top, + left: el.to.left + }); + } else { + $.each([ originalVerticalPositioning, originalHorizontalPositioning ], function( idx, pos ) { + el.css( pos, function( _, str ) { + var val = parseInt( str, 10 ), + toRef = idx ? el.to.left : el.to.top, + delta = idx ? el.to.outerWidth - el.from.outerWidth: el.to.outerHeight - el.from.outerHeight, + same = origin[ idx ] === pos, + mid = origin[ idx ] === "middle" || origin[ idx ] === "center", + direction = pos == "left" || pos == "top"; + + // if original was "auto", recalculate the new value from wrapper + if ( str === "auto" ) { + return toRef + "px"; + } + + // if not setting left or top + if ( !direction ) { + + // if the position is relative, bottom/right are reversed meaning + if ( position === "relative" ) { + toRef *= -1; + + // otherwise, if its NOT a midpoint origin, compensate for the outerWidth difference + } else if ( !mid ) { + toRef -= delta * ( same ? -1 : 1 ); + } + } + return val + toRef + "px"; + }); + }); + } + $.effects.removeWrapper( el ); $.isFunction( o.complete ) && o.complete.apply( this, arguments ); // Callback el.dequeue(); diff --git a/ui/jquery.effects.shake.js b/ui/jquery.effects.shake.js index 550329ca4..52ab331e8 100644 --- a/ui/jquery.effects.shake.js +++ b/ui/jquery.effects.shake.js @@ -17,7 +17,7 @@ $.effects.effect.shake = function( o ) { return this.queue( function() { var el = $( this ), - props = [ "position", "top", "bottom", "left", "right" ], + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], mode = $.effects.setMode( el, o.mode || "effect" ), direction = o.direction || "left", distance = o.distance || 20, diff --git a/ui/jquery.effects.slide.js b/ui/jquery.effects.slide.js index 6b0296754..ccb13fa1b 100644 --- a/ui/jquery.effects.slide.js +++ b/ui/jquery.effects.slide.js @@ -18,24 +18,26 @@ $.effects.effect.slide = function( o ) { // Create element var el = $( this ), - props = ['position','top','bottom','left','right'], + props = [ "position", "top", "bottom", "left", "right", "width", "height" ], mode = $.effects.setMode( el, o.mode || 'show' ), direction = o.direction || 'left', ref = (direction == 'up' || direction == 'down') ? 'top' : 'left', motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg', distance, - animation = {}; + animation = {}, + size; // Adjust - $.effects.save( el, props ); + $.effects.save( el, props ); el.show(); + distance = o.distance || el[ ref == 'top' ? "outerHeight" : "outerWidth" ]({ + margin: true + }); + $.effects.createWrapper( el ).css({ overflow: 'hidden' - }); - - distance = o.distance || el[ ref == 'top' ? "outerHeight" : "outerWidth" ]({ - margin: true }); + if (mode == 'show') { el.css( ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance ); } diff --git a/ui/jquery.effects.transfer.js b/ui/jquery.effects.transfer.js index 17d23c5fa..f0f9d9fd4 100644 --- a/ui/jquery.effects.transfer.js +++ b/ui/jquery.effects.transfer.js @@ -17,10 +17,14 @@ $.effects.effect.transfer = function( o ) { return this.queue( function() { var elem = $( this ), target = $( o.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $("body"), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, endPosition = target.offset(), animation = { - top: endPosition.top, - left: endPosition.left, + top: endPosition.top - fixTop , + left: endPosition.left - fixLeft , height: target.innerHeight(), width: target.innerWidth() }, @@ -29,11 +33,11 @@ $.effects.effect.transfer = function( o ) { .appendTo( document.body ) .addClass( o.className ) .css({ - top: startPosition.top, - left: startPosition.left, + top: startPosition.top - fixTop , + left: startPosition.left - fixLeft , height: elem.innerHeight(), width: elem.innerWidth(), - position: 'absolute' + position: targetFixed ? "fixed" : "absolute" }) .animate( animation, o.duration, o.easing, function() { transfer.remove(); diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 4c73bdfd8..ee0a86338 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -105,7 +105,8 @@ function Datepicker() { altFormat: '', // The date format to use for the alternate field constrainInput: true, // The input is constrained by the current date format showButtonPanel: false, // True to show button panel, false to not show it - autoSize: false // True to size the input for the date format, false to leave as is + autoSize: false, // True to size the input for the date format, false to leave as is + disabled: false // The initial disabled state }; $.extend(this._defaults, this.regional['']); this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')); @@ -114,6 +115,9 @@ function Datepicker() { $.extend(Datepicker.prototype, { /* Class name added to elements to indicate already configured with a date picker. */ markerClassName: 'hasDatepicker', + + //Keep track of the maximum number of rows displayed (see #7043) + maxRows: 4, /* Debug logging (if enabled). */ log: function () { @@ -194,6 +198,10 @@ $.extend(Datepicker.prototype, { }); this._autoSize(inst); $.data(target, PROP_NAME, inst); + //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } }, /* Make attachments based on settings. */ @@ -273,6 +281,10 @@ $.extend(Datepicker.prototype, { this._setDate(inst, this._getDefaultDate(inst), true); this._updateDatepicker(inst); this._updateAlternate(inst); + //If disabled option is true, disable the datepicker before showing it (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } inst.dpDiv.show(); }, @@ -682,6 +694,7 @@ $.extend(Datepicker.prototype, { /* Generate the date picker content. */ _updateDatepicker: function(inst) { var self = this; + self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) var borders = $.datepicker._getBorders(inst.dpDiv); instActive = inst; // for delegate hover events inst.dpDiv.empty().append(this._generateHTML(inst)); @@ -1471,6 +1484,7 @@ $.extend(Datepicker.prototype, { var html = ''; for (var row = 0; row < numMonths[0]; row++) { var group = ''; + this.maxRows = 4; for (var col = 0; col < numMonths[1]; col++) { var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); var cornerClass = ' ui-corner-all'; @@ -1505,7 +1519,9 @@ $.extend(Datepicker.prototype, { if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; - var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate + var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) + this.maxRows = numRows; var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows calender += '<tr>'; diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 03e14f124..7dd1a9ce0 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -1,6 +1,6 @@ /* * jQuery UI Menu @VERSION - * + * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license @@ -12,10 +12,10 @@ * jquery.ui.widget.js */ (function($) { - + var idIncrement = 0; -$.widget("ui.menu", { +$.widget( "ui.menu", { version: "@VERSION", defaultElement: "<ul>", delay: 150, @@ -29,8 +29,8 @@ $.widget("ui.menu", { var self = this; this.activeMenu = this.element; this.menuId = this.element.attr( "id" ) || "ui-menu-" + idIncrement++; - if (this.element.find(".ui-icon").length) { - this.element.addClass("ui-menu-icons"); + if ( this.element.find( ".ui-icon" ).length ) { + this.element.addClass( "ui-menu-icons" ); } this.element .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) @@ -61,7 +61,7 @@ $.widget("ui.menu", { self.focus( event, target ); } }) - .bind("mouseout.menu", function( event ) { + .bind( "mouseout.menu", function( event ) { if ( self.options.disabled ) { return; } @@ -71,7 +71,7 @@ $.widget("ui.menu", { } }); this.refresh(); - + this.element.attr( "tabIndex", 0 ).bind( "keydown.menu", function( event ) { if ( self.options.disabled ) { return; @@ -110,8 +110,8 @@ $.widget("ui.menu", { event.preventDefault(); break; case $.ui.keyCode.ENTER: - if (self.active.children("a[aria-haspopup='true']").length) { - if (self.right( event )) { + if ( self.active.children( "a[aria-haspopup='true']" ).length ) { + if ( self.right( event ) ) { event.stopImmediatePropagation(); } } @@ -129,35 +129,39 @@ $.widget("ui.menu", { break; default: event.stopPropagation(); - clearTimeout(self.filterTimer); - var prev = self.previousFilter || ""; - var character = String.fromCharCode(event.keyCode); - var skip = false; + clearTimeout( self.filterTimer ); + var match, + prev = self.previousFilter || "", + character = String.fromCharCode( event.keyCode ), + skip = false; + if (character == prev) { skip = true; } else { character = prev + character; } - function escape(value) { - return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + function escape( value ) { + return value.replace( /[-[\]{}()*+?.,\\^$|#\s]/g , "\\$&" ); } - var match = self.activeMenu.children(".ui-menu-item").filter(function() { - return new RegExp("^" + escape(character), "i").test($(this).children("a").text()); + match = self.activeMenu.children( ".ui-menu-item" ).filter( function() { + return new RegExp("^" + escape(character), "i") + .test( $( this ).children( "a" ).text() ); }); - var match = skip && match.index(self.active.next()) != -1 ? self.active.nextAll(".ui-menu-item") : match; - if (!match.length) { + match = skip && match.index(self.active.next()) != -1 ? self.active.nextAll(".ui-menu-item") : match; + if ( !match.length ) { character = String.fromCharCode(event.keyCode); - match = self.activeMenu.children(".ui-menu-item").filter(function() { - return new RegExp("^" + escape(character), "i").test($(this).children("a").text()); + match = self.activeMenu.children(".ui-menu-item").filter( function() { + return new RegExp("^" + escape(character), "i") + .test( $( this ).children( "a" ).text() ); }); } - if (match.length) { - self.focus(event, match); + if ( match.length ) { + self.focus( event, match ); if (match.length > 1) { self.previousFilter = character; - self.filterTimer = setTimeout(function() { + self.filterTimer = setTimeout( function() { delete self.previousFilter; - }, 1000); + }, 1000 ); } else { delete self.previousFilter; } @@ -167,21 +171,21 @@ $.widget("ui.menu", { } }); }, - + _destroy: function() { //destroy (sub)menus this.element .removeAttr( "aria-activedescendant" ) - .find("ul") + .find( "ul" ) .andSelf() .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) .removeAttr( "role" ) - .removeAttr("tabIndex") + .removeAttr( "tabIndex" ) .removeAttr( "aria-labelledby" ) .removeAttr( "aria-expanded" ) .removeAttr( "aria-hidden" ) .show(); - + //destroy menu items this.element.find( ".ui-menu-item" ) .unbind( ".menu" ) @@ -193,143 +197,176 @@ $.widget("ui.menu", { .removeAttr( "role" ) .removeAttr( "aria-haspopup" ) .removeAttr( "id" ) - .children(".ui-icon").remove(); + .children( ".ui-icon" ) + .remove(); }, - + refresh: function() { - var self = this; - // initialize nested menus - var submenus = this.element.find("ul:not(.ui-menu)") - .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) - .attr("role", "menu") - .hide() - .attr("aria-hidden", "true") - .attr("aria-expanded", "false") - ; - + var self = this, + + // initialize nested menus + submenus = this.element.find( "ul:not(.ui-menu)" ) + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .attr( "role", "menu" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ), + // don't refresh list items that are already adapted - var items = submenus.add(this.element).children( "li:not(.ui-menu-item):has(a)" ) - .addClass( "ui-menu-item" ) - .attr( "role", "presentation" ); - + items = submenus.add( this.element ).children( "li:not(.ui-menu-item):has(a)" ) + .addClass( "ui-menu-item" ) + .attr( "role", "presentation" ); + items.children( "a" ) .addClass( "ui-corner-all" ) .attr( "tabIndex", -1 ) .attr( "role", "menuitem" ) - .attr("id", function(i) {return self.element.attr("id") + "-" + i}); - - submenus.each(function() { - var menu = $(this); - var item = menu.prev("a") - item.attr("aria-haspopup", "true") - .prepend('<span class="ui-menu-icon ui-icon ui-icon-carat-1-e"></span>'); - menu.attr("aria-labelledby", item.attr("id")); + .attr( "id", function( i ) { + return self.element.attr( "id" ) + "-" + i; + }); + + submenus.each( function() { + var menu = $( this ), + item = menu.prev( "a" ); + + item.attr( "aria-haspopup", "true" ) + .prepend( '<span class="ui-menu-icon ui-icon ui-icon-carat-1-e"></span>' ); + menu.attr( "aria-labelledby", item.attr( "id" ) ); }); }, focus: function( event, item ) { - var self = this; - + var nested, + self = this; + this.blur(); - + if ( this._hasScroll() ) { - var borderTop = parseFloat( $.curCSS( this.element[0], "borderTopWidth", true) ) || 0, - paddingTop = parseFloat( $.curCSS( this.element[0], "paddingTop", true) ) || 0, + var borderTop = parseFloat( $.curCSS( this.element[0], "borderTopWidth", true ) ) || 0, + paddingTop = parseFloat( $.curCSS( this.element[0], "paddingTop", true ) ) || 0, offset = item.offset().top - this.element.offset().top - borderTop - paddingTop, scroll = this.element.scrollTop(), elementHeight = this.element.height(), itemHeight = item.height(); + if ( offset < 0 ) { this.element.scrollTop( scroll + offset ); } else if ( offset + itemHeight > elementHeight ) { this.element.scrollTop( scroll + offset - elementHeight + itemHeight ); } } - + this.active = item.first() .children( "a" ) .addClass( "ui-state-focus" ) .end(); - self.element.attr("aria-activedescendant", self.active.children("a").attr("id")) + self.element.attr( "aria-activedescendant", self.active.children("a").attr("id") ); // highlight active parent menu item, if any this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"); - - self.timer = setTimeout(function() { + + self.timer = setTimeout( function() { self._close(); - }, self.delay) - var nested = $(">ul", item); - if (nested.length && /^mouse/.test(event.type)) { + }, self.delay ); + + nested = $( ">ul", item ); + if ( nested.length && ( /^mouse/.test( event.type ) ) ) { self._startOpening(nested); } this.activeMenu = item.parent(); - + this._trigger( "focus", event, { item: item } ); }, - blur: function(event) { - if (!this.active) { + blur: function( event ) { + if ( !this.active ) { return; } - - clearTimeout(this.timer); - + + clearTimeout( this.timer ); + this.active.children( "a" ).removeClass( "ui-state-focus" ); this.active = null; }, - _startOpening: function(submenu) { - clearTimeout(this.timer); + _startOpening: function( submenu ) { + clearTimeout( this.timer ); var self = this; - self.timer = setTimeout(function() { + self.timer = setTimeout( function() { self._close(); - self._open(submenu); - }, self.delay); + self._open( submenu ); + }, self.delay ); }, - - _open: function(submenu) { - clearTimeout(this.timer); - this.element.find(".ui-menu").not(submenu.parents()).hide().attr("aria-hidden", "true"); + + _open: function( submenu ) { + clearTimeout( this.timer ); + this.element + .find( ".ui-menu" ) + .not( submenu.parents() ) + .hide() + .attr( "aria-hidden", "true" ); + var position = $.extend({}, { - of: this.active - }, $.type(this.options.position) == "function" - ? this.options.position(this.active) - : this.options.position - ); - submenu.show().removeAttr("aria-hidden").attr("aria-expanded", "true").position(position); + of: this.active + }, $.type(this.options.position) == "function" + ? this.options.position(this.active) + : this.options.position + ); + + submenu.show() + .removeAttr( "aria-hidden" ) + .attr( "aria-expanded", "true" ) + .position( position ); }, - + closeAll: function() { this.element - .find("ul").hide().attr("aria-hidden", "true").attr("aria-expanded", "false").end() - .find("a.ui-state-active").removeClass("ui-state-active"); + .find( "ul" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .end() + .find( "a.ui-state-active" ) + .removeClass( "ui-state-active" ); + this.blur(); this.activeMenu = this.element; }, - + _close: function() { this.active.parent() - .find("ul").hide().attr("aria-hidden", "true").attr("aria-expanded", "false").end() - .find("a.ui-state-active").removeClass("ui-state-active"); + .find( "ul" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .end() + .find( "a.ui-state-active" ) + .removeClass( "ui-state-active" ); }, - left: function(event) { + left: function( event ) { var newItem = this.active && this.active.parents("li:not(.ui-menubar-item)").first(); - if (newItem && newItem.length) { - this.active.parent().attr("aria-hidden", "true").attr("aria-expanded", "false").hide(); - this.focus(event, newItem); + if ( newItem && newItem.length ) { + this.active.parent() + .attr("aria-hidden", "true") + .attr("aria-expanded", "false") + .hide(); + this.focus( event, newItem ); return true; } }, - right: function(event) { - var self= this; - var newItem = this.active && this.active.children("ul").children("li").first(); - if (newItem && newItem.length) { - this._open(newItem.parent()); - var current = this.active; + right: function( event ) { + var self = this, + newItem = this.active && this.active.children("ul").children("li").first(); + + if ( newItem && newItem.length ) { + this._open( newItem.parent() ); + //timeout so Firefox will not hide activedescendant change in expanding submenu from AT - setTimeout(function(){self.focus(event, newItem)}, 20); + setTimeout( function() { + self.focus( event, newItem ); + }, 20 ); return true; } }, @@ -350,19 +387,19 @@ $.widget("ui.menu", { return this.active && !this.active.nextAll( ".ui-menu-item" ).length; }, - _move: function(direction, edge, filter, event) { + _move: function( direction, edge, filter, event ) { if ( !this.active ) { - this.focus( event, this.activeMenu.children(edge)[filter]() ); + this.focus( event, this.activeMenu.children( edge )[ filter ]() ); return; } var next = this.active[ direction + "All" ]( ".ui-menu-item" ).eq( 0 ); if ( next.length ) { this.focus( event, next ); } else { - this.focus( event, this.activeMenu.children(edge)[filter]() ); + this.focus( event, this.activeMenu.children( edge )[ filter ]() ); } }, - + nextPage: function( event ) { if ( this._hasScroll() ) { if ( !this.active || this.last() ) { diff --git a/ui/jquery.ui.menubar.js b/ui/jquery.ui.menubar.js index a0e9afb3c..39e75924e 100644 --- a/ui/jquery.ui.menubar.js +++ b/ui/jquery.ui.menubar.js @@ -21,7 +21,11 @@ $.widget( "ui.menubar", { version: "@VERSION", options: { buttons: false, - menuIcon: false + menuIcon: false, + position: { + my: "left top", + at: "left bottom" + } }, _create: function() { var that = this; @@ -39,6 +43,9 @@ $.widget( "ui.menubar", { this._hoverable( items ); items.next( "ul" ) .menu({ + position: { + within: this.options.position.within + }, select: function( event, ui ) { ui.item.parents( "ul.ui-menu:last" ).hide(); that._trigger( "select", event, ui ); @@ -119,7 +126,7 @@ $.widget( "ui.menubar", { // TODO ui-menubar-link is added above, not needed here? input.addClass( "ui-menubar-link" ).removeClass( "ui-state-default" ); }; - + }); that._bind( { keydown: function( event ) { @@ -210,11 +217,9 @@ $.widget( "ui.menubar", { var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 ); this.active = menu .show() - .position( { - my: "left top", - at: "left bottom", + .position( $.extend({ of: button - }) + }, this.options.position ) ) .removeAttr( "aria-hidden" ) .attr( "aria-expanded", "true" ) .menu("focus", event, menu.children( "li" ).first() ) diff --git a/ui/jquery.ui.popup.js b/ui/jquery.ui.popup.js index c90755fbb..d455346dc 100644 --- a/ui/jquery.ui.popup.js +++ b/ui/jquery.ui.popup.js @@ -13,7 +13,7 @@ * jquery.ui.position.js */ (function($) { - + var idIncrement = 0; $.widget( "ui.popup", { @@ -28,34 +28,34 @@ $.widget( "ui.popup", { if ( !this.options.trigger ) { this.options.trigger = this.element.prev(); } - + if ( !this.element.attr( "id" ) ) { this.element.attr( "id", "ui-popup-" + idIncrement++ ); this.generatedId = true; } - + if ( !this.element.attr( "role" ) ) { // TODO alternatives to tooltip are dialog and menu, all three aren't generic popups - this.element.attr( "role", "tooltip" ); + this.element.attr( "role", "dialog" ); this.generatedRole = true; } - + this.options.trigger .attr( "aria-haspopup", true ) .attr( "aria-owns", this.element.attr( "id" ) ); - + this.element - .addClass("ui-popup") + .addClass( "ui-popup" ) this.close(); this._bind(this.options.trigger, { keydown: function( event ) { - // prevent space-to-open to scroll the page, only hapens for anchor ui.button - if ( this.options.trigger.is( "a:ui-button" ) && event.keyCode == $.ui.keyCode.SPACE) { - event.preventDefault() + // prevent space-to-open to scroll the page, only happens for anchor ui.button + if ( this.options.trigger.is( "a:ui-button" ) && event.keyCode == $.ui.keyCode.SPACE ) { + event.preventDefault(); } // TODO handle SPACE to open popup? only when not handled by ui.button - if ( event.keyCode == $.ui.keyCode.SPACE && this.options.trigger.is("a:not(:ui-button)") ) { + if ( event.keyCode == $.ui.keyCode.SPACE && this.options.trigger.is( "a:not(:ui-button)" ) ) { this.options.trigger.trigger( "click", event ); } // translate keydown to click @@ -79,52 +79,75 @@ $.widget( "ui.popup", { }, 1); } }); - - this._bind(this.element, { - // TODO use focusout so that element itself doesn't need to be focussable - blur: function( event ) { + + if ( !this.element.is( ":ui-menu" ) ) { + //default use case, wrap tab order in popup + this._bind({ keydown : function( event ) { + if ( event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + var tabbables = $( ":tabbable", this.element ), + first = tabbables.first(), + last = tabbables.last(); + if ( event.target === last[ 0 ] && !event.shiftKey ) { + first.focus( 1 ); + event.preventDefault(); + } else if ( event.target === first[ 0 ] && event.shiftKey ) { + last.focus( 1 ); + event.preventDefault(); + } + } + }); + } + + this._bind({ + focusout: function( event ) { var that = this; // use a timer to allow click to clear it and letting that // handle the closing instead of opening again that.closeTimer = setTimeout( function() { that.close( event ); }, 100); + }, + focusin: function( event ) { + clearTimeout( this.closeTimer ); } }); this._bind({ - // TODO only triggerd on element if it can receive focus + // TODO only triggered on element if it can receive focus // bind to document instead? // either element itself or a child should be focusable keyup: function( event ) { - if (event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" )) { + if ( event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" ) ) { this.close( event ); // TODO move this to close()? would allow menu.select to call popup.close, and get focus back to trigger this.options.trigger.focus(); } } }); - + this._bind(document, { click: function( event ) { - if (this.isOpen && !$(event.target).closest(".ui-popup").length) { + if ( this.isOpen && !$(event.target).closest(".ui-popup").length ) { this.close( event ); } } }) }, - + _destroy: function() { this.element .show() .removeClass( "ui-popup" ) .removeAttr( "aria-hidden" ) - .removeAttr( "aria-expanded" ); + .removeAttr( "aria-expanded" ) + .unbind( "keypress.ui-popup"); this.options.trigger .removeAttr( "aria-haspopup" ) .removeAttr( "aria-owns" ); - + if ( this.generatedId ) { this.element.removeAttr( "id" ); } @@ -132,7 +155,7 @@ $.widget( "ui.popup", { this.element.removeAttr( "role" ); } }, - + open: function( event ) { var position = $.extend( {}, { of: this.options.trigger @@ -142,17 +165,28 @@ $.widget( "ui.popup", { .show() .attr( "aria-hidden", false ) .attr( "aria-expanded", true ) - .position( position ) - // TODO find a focussable child, otherwise put focus on element, add tabIndex=0 if not focussable - .focus(); + .position( position ); - if (this.element.is(":ui-menu")) { - this.element.menu("focus", event, this.element.children( "li" ).first() ); + if (this.element.is( ":ui-menu" )) { //popup is a menu + this.element.menu( "focus", event, this.element.children( "li" ).first() ); + this.element.focus(); + } else { + // set focus to the first tabbable element in the popup container + // if there are no tabbable elements, set focus on the popup itself + var tabbables = this.element.find( ":tabbable" ); + this.removeTabIndex = false; + if ( !tabbables.length ) { + if ( !this.element.is(":tabbable") ) { + this.element.attr("tabindex", "0"); + this.removeTabIndex = true; + } + tabbables = tabbables.add( this.element[ 0 ] ); + } + tabbables.first().focus( 1 ); } // take trigger out of tab order to allow shift-tab to skip trigger - this.options.trigger.attr("tabindex", -1); - + this.options.trigger.attr( "tabindex", -1 ); this.isOpen = true; this._trigger( "open", event ); }, @@ -163,13 +197,13 @@ $.widget( "ui.popup", { .attr( "aria-hidden", true ) .attr( "aria-expanded", false ); - this.options.trigger.attr("tabindex", 0); - + this.options.trigger.attr( "tabindex" , 0 ); + if ( this.removeTabIndex ) { + this.element.removeAttr( "tabindex" ); + } this.isOpen = false; this._trigger( "close", event ); } - - }); }(jQuery)); diff --git a/ui/jquery.ui.position.js b/ui/jquery.ui.position.js index 98b8198e2..3bae0d010 100644 --- a/ui/jquery.ui.position.js +++ b/ui/jquery.ui.position.js @@ -19,6 +19,39 @@ var rhorizontal = /left|center|right/, center = "center", _position = $.fn.position; +$.position = { + scrollbarWidth: function() { + var w1, w2, + div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), + innerDiv = div.children()[0]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[0].clientWidth; + } + + div.remove(); + + return w1 - w2; + }, + getScrollInfo: function( within ) { + var that = within[0], + scrollHeight = within.height() < that.scrollHeight, + scrollWidth = within.width() < that.scrollWidth, + scrollbarWidth = $.position.scrollbarWidth(); + + return { + height: scrollHeight ? scrollbarWidth : 0, + width : scrollWidth ? scrollbarWidth : 0 + }; + } +}; + $.fn.position = function( options ) { if ( !options || !options.of ) { return _position.apply( this, arguments ); @@ -28,6 +61,7 @@ $.fn.position = function( options ) { options = $.extend( {}, options ); var target = $( options.of ), + within = $( options.within || window ), targetElem = target[0], collision = ( options.collision || "flip" ).split( " " ), offsets = {}, @@ -56,7 +90,7 @@ $.fn.position = function( options ) { } // force my and at to have valid horizontal and vertical positions - // if a value is missing or invalid, it will be converted to center + // if a value is missing or invalid, it will be converted to center $.each( [ "my", "at" ], function() { var pos = ( options[ this ] || "" ).split( " " ), horizontalOffset, @@ -110,7 +144,7 @@ $.fn.position = function( options ) { parseInt( offsets.at[ 1 ], 10 ) * ( rpercent.test( offsets.at[ 1 ] ) ? targetHeight / 100 : 1 ) ]; - basePosition.left += atOffset[ 0 ], + basePosition.left += atOffset[ 0 ]; basePosition.top += atOffset[ 1 ]; return this.each(function() { @@ -119,10 +153,11 @@ $.fn.position = function( options ) { elemHeight = elem.outerHeight(), marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + scrollInfo = $.position.getScrollInfo( within ), collisionWidth = elemWidth + marginLeft + - ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ) + scrollInfo.width, collisionHeight = elemHeight + marginTop + - ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ) + scrollInfo.height, position = $.extend( {}, basePosition ), myOffset = [ parseInt( offsets.my[ 0 ], 10 ) * @@ -168,7 +203,8 @@ $.fn.position = function( options ) { collisionHeight: collisionHeight, offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], my: options.my, - at: options.at + at: options.at, + within: within }); } }); @@ -183,32 +219,40 @@ $.fn.position = function( options ) { $.ui.position = { fit: { left: function( position, data ) { - var win = $( window ), - overLeft = win.scrollLeft() - data.collisionPosition.left, - overRight = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? win.scrollLeft() : within.offset().left, + outerWidth = isWindow ? win.width() : within.outerWidth(), + overLeft = withinOffset - data.collisionPosition.left, + overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset; // element is wider than window or too far left -> align with left edge - if ( data.collisionWidth > win.width() || overLeft > 0 ) { - position.left = position.left + overLeft; + if ( data.collisionWidth > outerWidth || overLeft > 0 ) { + position.left += overLeft; // too far right -> align with right edge } else if ( overRight > 0 ) { - position.left = position.left - overRight; + position.left -= overRight; // adjust based on position and margin } else { position.left = Math.max( position.left - data.collisionPosition.left, position.left ); } }, top: function( position, data ) { - var win = $( window ), - overTop = win.scrollTop() - data.collisionPosition.top, - overBottom = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? win.scrollTop() : within.offset().top, + outerHeight = isWindow ? win.height() : within.outerHeight(), + overTop = withinOffset - data.collisionPosition.top, + overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset; // element is taller than window or too far up -> align with top edge - if ( data.collisionHeight > win.height() || overTop > 0 ) { - position.top = position.top + overTop; + if ( data.collisionHeight > outerHeight || overTop > 0 ) { + position.top += overTop; // too far down -> align with bottom edge } else if ( overBottom > 0 ) { - position.top = position.top - overBottom; + position.top -= overBottom; // adjust based on position and margin } else { position.top = Math.max( position.top - data.collisionPosition.top, position.top ); @@ -220,8 +264,15 @@ $.ui.position = { if ( data.at[ 0 ] === center ) { return; } - var win = $( window ), - over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? 0 : within.offset().left, + outerWidth = isWindow ? within.width() : within.outerWidth(), + overLeft = data.collisionPosition.left - withinOffset, + overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset, + left = data.my[ 0 ] === "left", myOffset = data.my[ 0 ] === "left" ? -data.elemWidth : data.my[ 0 ] === "right" ? @@ -231,19 +282,23 @@ $.ui.position = { data.targetWidth : -data.targetWidth, offset = -2 * data.offset[ 0 ]; - position.left += data.collisionPosition.left < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; + if ( overLeft < 0 || overRight > 0 ) { + position.left += myOffset + atOffset + offset; + } }, top: function( position, data ) { if ( data.at[ 1 ] === center ) { return; } - var win = $( window ), - over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), - myOffset = data.my[ 1 ] === "top" ? + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? 0 : within.offset().top, + outerHeight = isWindow ? within.height() : within.outerHeight(), + overTop = data.collisionPosition.top - withinOffset, + overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset, + top = data.my[ 1 ] === "top", + myOffset = top ? -data.elemHeight : data.my[ 1 ] === "bottom" ? data.elemHeight : @@ -252,11 +307,9 @@ $.ui.position = { data.targetHeight : -data.targetHeight, offset = -2 * data.offset[ 1 ]; - position.top += data.collisionPosition.top < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; + if ( overTop < 0 || overBottom > 0 ) { + position.top += myOffset + atOffset + offset; + } } } }; @@ -267,7 +320,7 @@ if ( $.uiBackCompat !== false ) { (function( $ ) { var _position = $.fn.position; $.fn.position = function( options ) { - if ( !options || !( "offset" in options ) ) { + if ( !options || !options.offset ) { return _position.call( this, options ); } var offset = options.offset.split( " " ), diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index b4cefc982..951b336ed 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -258,12 +258,29 @@ $.widget( "ui.spinner", { : 2 : 1); + // clamp the new value + newVal = this._trimValue( newVal ); + if ( this._trigger( "spin", event, { value: newVal } ) !== false) { this.value( newVal ); this.counter++; } }, + _trimValue: function( value ) { + var options = this.options; + + if ( value > options.max) { + return options.max; + } + + if ( value < options.min ) { + return options.min; + } + + return value; + }, + _stop: function( event ) { this.counter = 0; if ( this.timer ) { @@ -280,13 +297,7 @@ $.widget( "ui.spinner", { _setOption: function( key, value ) { if ( key === "value") { - value = this._parse( value ); - if ( value < this.options.min ) { - value = this.options.min; - } - if ( value > this.options.max ) { - value = this.options.max; - } + value = this._trimValue( this._parse(value) ); } if ( key === "disabled" ) { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 1c01ef7c9..cf138f774 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -133,7 +133,7 @@ $.widget.bridge = function( name, object ) { } var methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue.jquery ? + returnValue = methodValue && methodValue.jquery ? returnValue.pushStack( methodValue.get() ) : methodValue; return false; @@ -239,9 +239,6 @@ $.Widget.prototype = { } if ( typeof key === "string" ) { - if ( value === undefined ) { - return this.options[ key ]; - } // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } options = {}; parts = key.split( "." ); @@ -252,8 +249,15 @@ $.Widget.prototype = { curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; curOption = curOption[ parts[ i ] ]; } - curOption[ parts.pop() ] = value; + key = parts.pop(); + if ( value === undefined ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; } else { + if ( value === undefined ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } options[ key ] = value; } } |