diff options
-rw-r--r-- | demos/button/default.html | 2 | ||||
-rw-r--r-- | external/qunit.css | 12 | ||||
-rw-r--r-- | external/qunit.js | 155 | ||||
-rw-r--r-- | tests/unit/button/button_core.js | 14 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker.html | 1 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker_events.js | 5 | ||||
-rw-r--r-- | tests/unit/datepicker/datepicker_tickets.js | 5 | ||||
-rw-r--r-- | tests/unit/effects/effects.html | 20 | ||||
-rw-r--r-- | tests/unit/effects/effects_core.js | 88 | ||||
-rw-r--r-- | tests/unit/tabs/tabs.html | 10 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_deprecated.html | 10 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_deprecated.js | 58 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_events.js | 96 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_methods.js | 89 | ||||
-rw-r--r-- | themes/base/jquery.ui.tabs.css | 4 | ||||
-rw-r--r-- | themes/base/jquery.ui.theme.css | 13 | ||||
-rw-r--r-- | ui/jquery.effects.core.js | 190 | ||||
-rw-r--r-- | ui/jquery.ui.button.js | 37 | ||||
-rw-r--r-- | ui/jquery.ui.datepicker.js | 31 | ||||
-rw-r--r-- | ui/jquery.ui.dialog.js | 8 | ||||
-rw-r--r-- | ui/jquery.ui.draggable.js | 9 | ||||
-rw-r--r-- | ui/jquery.ui.spinner.js | 367 | ||||
-rw-r--r-- | ui/jquery.ui.tabs.js | 165 |
23 files changed, 841 insertions, 548 deletions
diff --git a/demos/button/default.html b/demos/button/default.html index 1ea3fa796..969ec6838 100644 --- a/demos/button/default.html +++ b/demos/button/default.html @@ -11,7 +11,7 @@ <link rel="stylesheet" href="../demos.css"> <script> $(function() { - $( "button, input:submit, a", ".demo" ).button(); + $( "input:submit, a, button", ".demo" ).button(); $( "a", ".demo" ).click(function() { return false; }); }); </script> diff --git a/external/qunit.css b/external/qunit.css index be37520ae..b3c6db523 100644 --- a/external/qunit.css +++ b/external/qunit.css @@ -1,6 +1,6 @@ /** * QUnit - A JavaScript Unit Testing Framework - * + * * http://docs.jquery.com/QUnit * * Copyright (c) 2011 John Resig, Jörn Zaefferer @@ -37,7 +37,7 @@ font-size: 1.5em; line-height: 1em; font-weight: normal; - + border-radius: 15px 15px 0 0; -moz-border-radius: 15px 15px 0 0; -webkit-border-top-right-radius: 15px; @@ -105,13 +105,13 @@ #qunit-tests ol { margin-top: 0.5em; padding: 0.5em; - + background-color: #fff; - + border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; - + box-shadow: inset 0px 2px 13px #999; -moz-box-shadow: inset 0px 2px 13px #999; -webkit-box-shadow: inset 0px 2px 13px #999; @@ -174,7 +174,7 @@ #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } #qunit-tests .pass .test-name { color: #366097; } - + #qunit-tests .pass .test-actual, #qunit-tests .pass .test-expected { color: #999999; } diff --git a/external/qunit.js b/external/qunit.js index 135e80978..d56936ee2 100644 --- a/external/qunit.js +++ b/external/qunit.js @@ -1,6 +1,6 @@ /** * QUnit - A JavaScript Unit Testing Framework - * + * * http://docs.jquery.com/QUnit * * Copyright (c) 2011 John Resig, Jörn Zaefferer @@ -78,7 +78,7 @@ Test.prototype = { // allow utility functions to access the current test environment // TODO why?? QUnit.current_testEnvironment = this.testEnvironment; - + try { if ( !config.pollution ) { saveGlobal(); @@ -114,8 +114,8 @@ Test.prototype = { }, teardown: function() { try { - checkPollution(); this.testEnvironment.teardown.call(this.testEnvironment); + checkPollution(); } catch(e) { QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); } @@ -124,7 +124,7 @@ Test.prototype = { if ( this.expected && this.expected != this.assertions.length ) { QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); } - + var good = 0, bad = 0, tests = id("qunit-tests"); @@ -166,17 +166,17 @@ Test.prototype = { var b = document.createElement("strong"); b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>"; - + var a = document.createElement("a"); a.innerHTML = "Rerun"; a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); - + addEvent(b, "click", function() { var next = b.nextSibling.nextSibling, display = next.style.display; next.style.display = display === "none" ? "block" : "none"; }); - + addEvent(b, "dblclick", function(e) { var target = e && e.target ? e.target : window.event.srcElement; if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { @@ -217,7 +217,7 @@ Test.prototype = { total: this.assertions.length } ); }, - + queue: function() { var test = this; synchronize(function() { @@ -246,7 +246,7 @@ Test.prototype = { synchronize(run); }; } - + }; var QUnit = { @@ -265,7 +265,7 @@ var QUnit = { QUnit.test(testName, expected, callback, true); }, - + test: function(testName, expected, callback, async) { var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg; @@ -286,13 +286,13 @@ var QUnit = { if ( !validTest(config.currentModule + ": " + testName) ) { return; } - + var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); test.module = config.currentModule; test.moduleTestEnvironment = config.currentModuleTestEnviroment; test.queue(); }, - + /** * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. */ @@ -337,7 +337,7 @@ var QUnit = { notEqual: function(actual, expected, message) { QUnit.push(expected != actual, actual, expected, message); }, - + deepEqual: function(actual, expected, message) { QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); }, @@ -356,34 +356,34 @@ var QUnit = { raises: function(block, expected, message) { var actual, ok = false; - + if (typeof expected === 'string') { message = expected; expected = null; } - + try { block(); } catch (e) { actual = e; } - + if (actual) { // we don't want to validate thrown error if (!expected) { ok = true; - // expected is a regexp + // expected is a regexp } else if (QUnit.objectType(expected) === "regexp") { ok = expected.test(actual); - // expected is a constructor + // expected is a constructor } else if (actual instanceof expected) { ok = true; - // expected is a validation function which returns true is validation passed + // expected is a validation function which returns true is validation passed } else if (expected.call({}, actual) === true) { ok = true; } } - + QUnit.ok(ok, message); }, @@ -412,7 +412,7 @@ var QUnit = { process(); } }, - + stop: function(timeout) { config.semaphore++; config.blocking = true; @@ -438,7 +438,7 @@ var config = { // block until document ready blocking: true, - + // by default, run previously failed tests first // very useful in combination with "Hide passed tests" checked reorder: true, @@ -519,7 +519,7 @@ extend(QUnit, { if ( result ) { result.parentNode.removeChild( result ); } - + if ( tests ) { result = document.createElement( "p" ); result.id = "qunit-testresult"; @@ -528,10 +528,10 @@ extend(QUnit, { result.innerHTML = 'Running...<br/> '; } }, - + /** * Resets the test setup. Useful for tests that modify the DOM. - * + * * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. */ reset: function() { @@ -544,7 +544,7 @@ extend(QUnit, { } } }, - + /** * Trigger an event on an element. * @@ -564,12 +564,12 @@ extend(QUnit, { elem.fireEvent("on"+type); } }, - + // Safe object type checking is: function( type, obj ) { return QUnit.objectType( obj ) == type; }, - + objectType: function( obj ) { if (typeof obj === "undefined") { return "undefined"; @@ -603,7 +603,7 @@ extend(QUnit, { } return undefined; }, - + push: function(result, actual, expected, message) { var details = { result: result, @@ -611,7 +611,7 @@ extend(QUnit, { actual: actual, expected: expected }; - + message = escapeHtml(message) || (result ? "okay" : "failed"); message = '<span class="test-message">' + message + "</span>"; expected = escapeHtml(QUnit.jsDump.parse(expected)); @@ -629,15 +629,15 @@ extend(QUnit, { } } output += "</table>"; - + QUnit.log(details); - + config.current.assertions.push({ result: !!result, message: output }); }, - + url: function( params ) { params = extend( extend( {}, QUnit.urlParams ), params ); var querystring = "?", @@ -648,7 +648,7 @@ extend(QUnit, { } return window.location.pathname + querystring.slice( 0, -1 ); }, - + // Logging callbacks; all receive a single argument with the listed properties // run test/logs.html for any related changes begin: function() {}, @@ -672,7 +672,7 @@ if ( typeof document === "undefined" || document.readyState === "complete" ) { addEvent(window, "load", function() { QUnit.begin({}); - + // Initialize the config, saving the execution queue var oldconfig = extend({}, config); QUnit.init(); @@ -695,7 +695,7 @@ addEvent(window, "load", function() { window.location = QUnit.url( params ); }); } - + var toolbar = id("qunit-testrunner-toolbar"); if ( toolbar ) { var filter = document.createElement("input"); @@ -774,18 +774,19 @@ function done() { banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); } - if ( tests ) { + if ( tests ) { id( "qunit-testresult" ).innerHTML = html; } if ( typeof document !== "undefined" && document.title ) { - // TODO what are the unicode codes for these? as-is fails if qunit.js isn't served with the right mimetype/charset - document.title = (config.stats.bad ? "✖" : "✔") + " " + document.title; + // show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8-charset + document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title; } QUnit.done( { failed: config.stats.bad, - passed: passed, + passed: passed, total: config.stats.all, runtime: runtime } ); @@ -799,7 +800,7 @@ function validTest( name ) { return true; } - not = filter.charAt( 0 ) === "!"; + var not = filter.charAt( 0 ) === "!"; if ( not ) { filter = filter.slice( 1 ); } @@ -874,7 +875,7 @@ function process() { function saveGlobal() { config.pollution = []; - + if ( config.noglobals ) { for ( var key in window ) { config.pollution.push( key ); @@ -885,7 +886,7 @@ function saveGlobal() { function checkPollution( name ) { var old = config.pollution; saveGlobal(); - + var newGlobals = diff( config.pollution, old ); if ( newGlobals.length > 0 ) { ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); @@ -971,7 +972,7 @@ QUnit.equiv = function () { } } } - + var callbacks = function () { // for string, boolean, number and null @@ -1025,13 +1026,13 @@ QUnit.equiv = function () { // b could be an object literal here if ( ! (QUnit.objectType(b) === "array")) { return false; - } - + } + len = a.length; if (len !== b.length) { // safe and faster return false; } - + //track reference to avoid circular references parents.push(a); for (i = 0; i < len; i++) { @@ -1064,7 +1065,7 @@ QUnit.equiv = function () { callers.push(a.constructor); //track reference to avoid circular references parents.push(a); - + for (i in a) { // be strict: don't ensures hasOwnProperty and go deep loop = false; for(j=0;j<parents.length;j++){ @@ -1130,7 +1131,7 @@ QUnit.jsDump = (function() { return '"' + str.toString().replace(/"/g, '\\"') + '"'; }; function literal( o ) { - return o + ''; + return o + ''; }; function join( pre, arr, post ) { var s = jsDump.separator(), @@ -1143,21 +1144,21 @@ QUnit.jsDump = (function() { return [ pre, inner + arr, base + post ].join(s); }; function array( arr ) { - var i = arr.length, ret = Array(i); + var i = arr.length, ret = Array(i); this.up(); while ( i-- ) - ret[i] = this.parse( arr[i] ); + ret[i] = this.parse( arr[i] ); this.down(); return join( '[', ret, ']' ); }; - + var reName = /^function (\w+)/; - + var jsDump = { parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance var parser = this.parsers[ type || this.typeOf(obj) ]; - type = typeof parser; - + type = typeof parser; + return type == 'function' ? parser.call( this, obj ) : type == 'string' ? parser : this.parsers.error; @@ -1208,7 +1209,7 @@ QUnit.jsDump = (function() { this.parsers[name] = parser; }, // The next 3 are exposed so you can use them - quote:quote, + quote:quote, literal:literal, join:join, // @@ -1227,7 +1228,7 @@ QUnit.jsDump = (function() { if ( name ) ret += ' ' + name; ret += '('; - + ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); }, @@ -1245,10 +1246,10 @@ QUnit.jsDump = (function() { node:function( node ) { var open = QUnit.jsDump.HTML ? '<' : '<', close = QUnit.jsDump.HTML ? '>' : '>'; - + var tag = node.nodeName.toLowerCase(), ret = open + tag; - + for ( var a in QUnit.jsDump.DOMAttrs ) { var val = node[QUnit.jsDump.DOMAttrs[a]]; if ( val ) @@ -1258,8 +1259,8 @@ QUnit.jsDump = (function() { }, functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function var l = fn.length; - if ( !l ) return ''; - + if ( !l ) return ''; + var args = Array(l); while ( l-- ) args[l] = String.fromCharCode(97+l);//97 is 'a' @@ -1316,34 +1317,34 @@ function getText( elems ) { * * More Info: * http://ejohn.org/projects/javascript-diff-algorithm/ - * + * * Usage: QUnit.diff(expected, actual) - * + * * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over" */ QUnit.diff = (function() { function diff(o, n){ var ns = new Object(); var os = new Object(); - + for (var i = 0; i < n.length; i++) { - if (ns[n[i]] == null) + if (ns[n[i]] == null) ns[n[i]] = { rows: new Array(), o: null }; ns[n[i]].rows.push(i); } - + for (var i = 0; i < o.length; i++) { - if (os[o[i]] == null) + if (os[o[i]] == null) os[o[i]] = { rows: new Array(), n: null }; os[o[i]].rows.push(i); } - + for (var i in ns) { if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { n[ns[i].rows[0]] = { @@ -1356,7 +1357,7 @@ QUnit.diff = (function() { }; } } - + for (var i = 0; i < n.length - 1; i++) { if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) { @@ -1370,7 +1371,7 @@ QUnit.diff = (function() { }; } } - + for (var i = n.length - 1; i > 0; i--) { if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && n[i - 1] == o[n[i].row - 1]) { @@ -1384,20 +1385,20 @@ QUnit.diff = (function() { }; } } - + return { o: o, n: n }; } - + return function(o, n){ o = o.replace(/\s+$/, ''); n = n.replace(/\s+$/, ''); var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); var str = ""; - + var oSpace = o.match(/\s+/g); if (oSpace == null) { oSpace = [" "]; @@ -1412,7 +1413,7 @@ QUnit.diff = (function() { else { nSpace.push(" "); } - + if (out.n.length == 0) { for (var i = 0; i < out.o.length; i++) { str += '<del>' + out.o[i] + oSpace[i] + "</del>"; @@ -1424,14 +1425,14 @@ QUnit.diff = (function() { str += '<del>' + out.o[n] + oSpace[n] + "</del>"; } } - + for (var i = 0; i < out.n.length; i++) { if (out.n[i].text == null) { str += '<ins>' + out.n[i] + nSpace[i] + "</ins>"; } else { var pre = ""; - + for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { pre += '<del>' + out.o[n] + oSpace[n] + "</del>"; } @@ -1439,7 +1440,7 @@ QUnit.diff = (function() { } } } - + return str; }; })(); diff --git a/tests/unit/button/button_core.js b/tests/unit/button/button_core.js index 5b30aa860..692c40320 100644 --- a/tests/unit/button/button_core.js +++ b/tests/unit/button/button_core.js @@ -67,4 +67,18 @@ test("buttonset", function() { ok( set.children("label:eq(2)").is(".ui-button.ui-corner-right:not(.ui-corner-all)") ); }); +test("buttonset (rtl)", function() { + var parent = $("#radio1").parent(); + // Set to rtl + parent.attr("dir", "rtl"); + + var set = $("#radio1").buttonset(); + ok( set.is(".ui-buttonset") ); + same( set.children(".ui-button").length, 3 ); + same( set.children("input:radio.ui-helper-hidden-accessible").length, 3 ); + ok( set.children("label:eq(0)").is(".ui-button.ui-corner-right:not(.ui-corner-all)") ); + ok( set.children("label:eq(1)").is(".ui-button:not(.ui-corner-all)") ); + ok( set.children("label:eq(2)").is(".ui-button.ui-corner-left:not(.ui-corner-all)") ); +}); + })(jQuery); diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html index fa346c6c9..d0c2c8c8c 100644 --- a/tests/unit/datepicker/datepicker.html +++ b/tests/unit/datepicker/datepicker.html @@ -49,6 +49,7 @@ <div id="qunit-fixture"> <p><input type="text" id="inp"/><input type="text" id="alt"/><div id="inl"></div></p> + <p><input type="text" id="inp2"/></p> </div> </body> diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index 84ca2f98e..bf48c9c8a 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -112,6 +112,11 @@ test('events', function() { inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.simulate.VK_END}); equals(selectedDate, '', 'Callback close date - ctrl+end'); + + var inp2 = init('#inp2'); + inp2.datepicker().datepicker('option', {onClose: callback}).datepicker('show'); + inp.datepicker('show'); + equals(selectedThis, inp2[0], 'Callback close this'); }); })(jQuery); diff --git a/tests/unit/datepicker/datepicker_tickets.js b/tests/unit/datepicker/datepicker_tickets.js index 7e6dc5f00..2b9ce05de 100644 --- a/tests/unit/datepicker/datepicker_tickets.js +++ b/tests/unit/datepicker/datepicker_tickets.js @@ -24,4 +24,9 @@ test('beforeShowDay-getDate', function() { inp.datepicker('hide'); }); +test('Ticket 6827: formatDate day of year calculation is wrong during day lights savings time', function(){ + var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT")); + equals(time, "089"); +}); + })(jQuery); diff --git a/tests/unit/effects/effects.html b/tests/unit/effects/effects.html index 2cffda7ec..0879a98b2 100644 --- a/tests/unit/effects/effects.html +++ b/tests/unit/effects/effects.html @@ -35,6 +35,22 @@ .hidden { display: none; } + .test { + background: #000; + border: 0; + } + .testAddBorder { + border: 10px solid #000; + } + .testChangeBackground { + background: #fff; + } + .test h2 { + font-size: 10px; + } + .testChildren h2 { + font-size: 20px; + } </style> </head> <body> @@ -48,7 +64,9 @@ <div id="qunit-fixture"> <div class="hidden test"></div> - <div class="shown test"></div> + <div class="animateClass test"> + <h2>Child Element Test</h2> + </div> </div> </body> diff --git a/tests/unit/effects/effects_core.js b/tests/unit/effects/effects_core.js index 0359b73d3..8d2e8f8df 100644 --- a/tests/unit/effects/effects_core.js +++ b/tests/unit/effects/effects_core.js @@ -1,6 +1,21 @@ (function($) { -var animateTime = 15; +function present( value, array, message ) { + QUnit.push( jQuery.inArray( value, array ) !== -1 , value, array, message ); +} + +function notPresent( value, array, message ) { + QUnit.push( jQuery.inArray( value, array ) === -1 , value, array, message ); +} + +// minDuration is used for "short" animate tests where we are only concerned about the final +var minDuration = 15, + + // duration is used for "long" animates where we plan on testing properties during animation + duration = 200, + + // mid is used for testing in the "middle" of the "duration" animations + mid = duration / 2; module( "effects.core" ); @@ -8,12 +23,10 @@ $.each( $.effects.effect, function( effect ) { if ( effect === "transfer" ) { return; } - QUnit.reset(); module( "effect."+effect ); - test( "show/hide", function() { + asyncTest( "show/hide", function() { var hidden = $( "div.hidden" ); expect( 8 ); - stop(); var count = 0, test = 0; @@ -23,24 +36,75 @@ $.each( $.effects.effect, function( effect ) { var point = count; return function( next ) { test++; - equals( point, test, "Queue function fired in order" ); + equal( point, test, "Queue function fired in order" ); if ( fn ) { - fn () + fn(); } else { - setTimeout( next, animateTime ); + setTimeout( next, minDuration ); } - } + }; } - - hidden.queue( queueTest() ).show( effect, animateTime, queueTest(function() { + + hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() { equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" ); - })).queue( queueTest() ).hide( effect, animateTime, queueTest(function() { + })).queue( queueTest() ).hide( effect, minDuration, queueTest(function() { equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" ); })).queue( queueTest(function(next) { - deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains") + deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains"); start(); })); }); }); +module("animateClass"); + +asyncTest( "animateClass works with borderStyle", function() { + var test = $("div.animateClass"), + count = 0; + expect(3); + test.toggleClass("testAddBorder", minDuration, function() { + test.toggleClass("testAddBorder", minDuration, function() { + equal( test.css("borderLeftStyle"), "none", "None border set" ); + start(); + }); + equal( test.css("borderLeftStyle"), "solid", "None border not immedately set" ); + }); + equal( test.css("borderLeftStyle"), "solid", "Solid border immedately set" ); +}); + +asyncTest( "animateClass works with colors", function() { + var test = $("div.animateClass"), + count = 0; + expect(2); + test.toggleClass("testChangeBackground", duration, function() { + present( test.css("backgroundColor"), [ "#ffffff", "rgb(255, 255, 255)" ], "Color is final" ); + start(); + }); + setTimeout(function() { + var color = test.css("backgroundColor"); + notPresent( color, [ "#000000", "#ffffff", "rgb(0, 0, 0)", "rgb(255,255,255)" ], + "Color is not endpoints in middle." ); + }, mid); +}); + +asyncTest( "animateClass works with children", function() { + var test = $("div.animateClass"), + h2 = test.find("h2"); + + expect(4); + test.toggleClass("testChildren", { children: true, duration: duration, complete: function() { + equal( h2.css("fontSize"), "20px", "Text size is final during complete"); + test.toggleClass("testChildren", duration, function() { + equal( h2.css("fontSize"), "10px", "Text size revertted after class removed"); + start(); + }); + setTimeout(function() { + equal( h2.css("fontSize"), "20px", "Text size unchanged with children: undefined" ); + }, mid); + }}); + setTimeout(function() { + notPresent( h2.css("fontSize"), ["10px","20px"], "Font size is neither endpoint when in middle."); + }, mid); +}); + })(jQuery); diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 34ec28bc4..60f5e972e 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -81,16 +81,6 @@ same( actual, expected ); } </script> - <script> - // disable this stale testsuite for testswarm only - var url = window.location.search; - url = decodeURIComponent( url.slice( url.indexOf("swarmURL=") + 9 ) ); - if ( url && url.indexOf("http") == 0 ) { - // reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script - QUnit.init(); - test("tabs", function() { ok(true, "disabled tabs testsuite"); }); - } - </script> <script src="../swarminject.js"></script> </head> <body> diff --git a/tests/unit/tabs/tabs_deprecated.html b/tests/unit/tabs/tabs_deprecated.html index 89d08f4d0..ed6518be3 100644 --- a/tests/unit/tabs/tabs_deprecated.html +++ b/tests/unit/tabs/tabs_deprecated.html @@ -80,16 +80,6 @@ same( actual, expected ); } </script> - <script> - // disable this stale testsuite for testswarm only - var url = window.location.search; - url = decodeURIComponent( url.slice( url.indexOf("swarmURL=") + 9 ) ); - if ( url && url.indexOf("http") == 0 ) { - // reset config to kill previous tests; make sure testsuite.js is loaded afterwards to init the testswarm script - QUnit.init(); - test("tabs", function() { ok(true, "disabled tabs testsuite"); }); - } - </script> <script src="../swarminject.js"></script> </head> <body> diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 4b50df405..1323c774a 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -35,7 +35,7 @@ asyncTest( "ajaxOptions", function() { } }); element.one( "tabsload", function( event, ui ) { - equals( ui.panel.html(), "test" ); + equals( $( ui.panel ).html(), "test" ); start(); }); element.tabs( "option", "active", 2 ); @@ -220,6 +220,62 @@ test( "selected", function() { module( "tabs (deprecated): events" ); +asyncTest( "load", function() { + expect( 15 ); + + var tab, panelId, panel, + element = $( "#tabs2" ); + + // init + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav a" ).eq( 2 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + strictEqual( ui.tab, tab[ 0 ], "tab" ); + strictEqual( ui.panel, panel[ 0 ], "panel" ); + equals( $( ui.panel ).find( "p" ).length, 1, "panel html" ); + tabs_state( element, 0, 0, 1, 0, 0 ); + tabsload1(); + }); + element.tabs({ active: 2 }); + + function tabsload1() { + // .option() + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav a" ).eq( 3 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + strictEqual( ui.tab, tab[ 0 ], "tab" ); + strictEqual( ui.panel, panel[ 0 ], "panel" ); + equals( $( ui.panel ).find( "p" ).length, 1, "panel html" ); + tabs_state( element, 0, 0, 0, 1, 0 ); + tabsload2(); + }); + element.tabs( "option", "active", 3 ); + } + + function tabsload2() { + // click, change panel content + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav a" ).eq( 4 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + equals( event.originalEvent.type, "click", "originalEvent" ); + strictEqual( ui.tab, tab[ 0 ], "tab" ); + strictEqual( ui.panel, panel[ 0 ], "panel" ); + equals( $( ui.panel ).find( "p" ).length, 1, "panel html" ); + tabs_state( element, 0, 0, 0, 0, 1 ); + start(); + }); + element.find( ".ui-tabs-nav a" ).eq( 4 ).click(); + } +}); + test( "enable", function() { expect( 3 ); diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index 2fabaafca..12c9bb87b 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -209,66 +209,68 @@ test( "beforeLoad", function() { equals( panel.html(), "<p>testing</p>", "panel html after" ); }); -asyncTest( "load", function() { - expect( 21 ); +if ( $.uiBackCompat === false ) { + asyncTest( "load", function() { + expect( 21 ); - var tab, panelId, panel, - element = $( "#tabs2" ); - - // init - element.one( "tabsload", function( event, ui ) { - tab = element.find( ".ui-tabs-nav a" ).eq( 2 ); - panelId = tab.attr( "aria-controls" ); - panel = $( "#" + panelId ); - - ok( !( "originalEvent" in event ), "originalEvent" ); - equals( ui.tab.size(), 1, "tab size" ); - strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); - equals( ui.panel.size(), 1, "panel size" ); - strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); - equals( ui.panel.find( "p" ).length, 1, "panel html" ); - tabs_state( element, 0, 0, 1, 0, 0 ); - tabsload1(); - }); - element.tabs({ active: 2 }); + var tab, panelId, panel, + element = $( "#tabs2" ); - function tabsload1() { - // .option() + // init element.one( "tabsload", function( event, ui ) { - tab = element.find( ".ui-tabs-nav a" ).eq( 3 ); + tab = element.find( ".ui-tabs-nav a" ).eq( 2 ); panelId = tab.attr( "aria-controls" ); panel = $( "#" + panelId ); - + ok( !( "originalEvent" in event ), "originalEvent" ); equals( ui.tab.size(), 1, "tab size" ); strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); equals( ui.panel.size(), 1, "panel size" ); strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); equals( ui.panel.find( "p" ).length, 1, "panel html" ); - tabs_state( element, 0, 0, 0, 1, 0 ); - tabsload2(); + tabs_state( element, 0, 0, 1, 0, 0 ); + tabsload1(); }); - element.tabs( "option", "active", 3 ); - } + element.tabs({ active: 2 }); - function tabsload2() { - // click, change panel content - element.one( "tabsload", function( event, ui ) { - tab = element.find( ".ui-tabs-nav a" ).eq( 4 ); - panelId = tab.attr( "aria-controls" ); - panel = $( "#" + panelId ); + function tabsload1() { + // .option() + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav a" ).eq( 3 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); - equals( event.originalEvent.type, "click", "originalEvent" ); - equals( ui.tab.size(), 1, "tab size" ); - strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); - equals( ui.panel.size(), 1, "panel size" ); - strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); - equals( ui.panel.find( "p" ).length, 1, "panel html" ); - tabs_state( element, 0, 0, 0, 0, 1 ); - start(); - }); - element.find( ".ui-tabs-nav a" ).eq( 4 ).click(); - } -}); + ok( !( "originalEvent" in event ), "originalEvent" ); + equals( ui.tab.size(), 1, "tab size" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equals( ui.panel.size(), 1, "panel size" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equals( ui.panel.find( "p" ).length, 1, "panel html" ); + tabs_state( element, 0, 0, 0, 1, 0 ); + tabsload2(); + }); + element.tabs( "option", "active", 3 ); + } + + function tabsload2() { + // click, change panel content + element.one( "tabsload", function( event, ui ) { + tab = element.find( ".ui-tabs-nav a" ).eq( 4 ); + panelId = tab.attr( "aria-controls" ); + panel = $( "#" + panelId ); + + equals( event.originalEvent.type, "click", "originalEvent" ); + equals( ui.tab.size(), 1, "tab size" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equals( ui.panel.size(), 1, "panel size" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + equals( ui.panel.find( "p" ).length, 1, "panel html" ); + tabs_state( element, 0, 0, 0, 0, 1 ); + start(); + }); + element.find( ".ui-tabs-nav a" ).eq( 4 ).click(); + } + }); +} }( jQuery ) ); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 221b0d39d..ec21e2de7 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -145,8 +145,93 @@ test( "refresh", function() { tabs_disabled( element, false ); }); -test('load', function() { - ok(false, "missing test - untested code is broken code."); +asyncTest( "load", function() { + expect( 30 ); + + var element = $( "#tabs2" ).tabs(); + + // load content of inactive tab + // useful for preloading content with custom caching + element.one( "tabsbeforeload", function( event, ui ) { + var tab = element.find( ".ui-tabs-nav a" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equals( ui.tab.size(), 1, "tab size" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equals( ui.panel.size(), 1, "panel size" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + tabs_state( element, 1, 0, 0, 0, 0 ); + }); + element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 + var uiTab = $( ui.tab ), + uiPanel = $( ui.panel ); + + var tab = element.find( ".ui-tabs-nav a" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equals( uiTab.size(), 1, "tab size" ); + strictEqual( uiTab[ 0 ], tab[ 0 ], "tab" ); + equals( uiPanel.size(), 1, "panel size" ); + strictEqual( uiPanel[ 0 ], panel[ 0 ], "panel" ); + equals( uiPanel.find( "p" ).length, 1, "panel html" ); + tabs_state( element, 1, 0, 0, 0, 0 ); + setTimeout( tabsload1, 1 ); + }); + element.tabs( "load", 3 ); + tabs_state( element, 1, 0, 0, 0, 0 ); + + function tabsload1() { + // no need to test details of event (tested in events tests) + element.one( "tabsbeforeload", function() { + ok( true, "tabsbeforeload invoked" ); + }); + element.one( "tabsload", function() { + ok( true, "tabsload invoked" ); + setTimeout( tabsload2, 1 ); + }); + element.tabs( "option", "active", 3 ); + tabs_state( element, 0, 0, 0, 1, 0 ); + } + + function tabsload2() { + // reload content of active tab + element.one( "tabsbeforeload", function( event, ui ) { + var tab = element.find( ".ui-tabs-nav a" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equals( ui.tab.size(), 1, "tab size" ); + strictEqual( ui.tab[ 0 ], tab[ 0 ], "tab" ); + equals( ui.panel.size(), 1, "panel size" ); + strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); + tabs_state( element, 0, 0, 0, 1, 0 ); + }); + element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 + var uiTab = $( ui.tab ), + uiPanel = $( ui.panel ); + + var tab = element.find( ".ui-tabs-nav a" ).eq( 3 ), + panelId = tab.attr( "aria-controls" ), + panel = $( "#" + panelId ); + + ok( !( "originalEvent" in event ), "originalEvent" ); + equals( uiTab.size(), 1, "tab size" ); + strictEqual( uiTab[ 0 ], tab[ 0 ], "tab" ); + equals( uiPanel.size(), 1, "panel size" ); + strictEqual( uiPanel[ 0 ], panel[ 0 ], "panel" ); + tabs_state( element, 0, 0, 0, 1, 0 ); + start(); + }); + element.tabs( "load", 3 ); + tabs_state( element, 0, 0, 0, 1, 0 ); + } }); }( jQuery ) ); diff --git a/themes/base/jquery.ui.tabs.css b/themes/base/jquery.ui.tabs.css index d4c039f30..b6429cf72 100644 --- a/themes/base/jquery.ui.tabs.css +++ b/themes/base/jquery.ui.tabs.css @@ -9,9 +9,9 @@ */ .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } -.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; } .ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; } .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } diff --git a/themes/base/jquery.ui.theme.css b/themes/base/jquery.ui.theme.css index 7d4398465..81f6051f2 100644 --- a/themes/base/jquery.ui.theme.css +++ b/themes/base/jquery.ui.theme.css @@ -237,15 +237,10 @@ ----------------------------------*/ /* Corner radius */ -.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } -.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } -.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } -.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } -.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } -.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } -.ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } -.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } -.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } /* Overlays */ .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index 2ed89653d..638119579 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -20,8 +20,8 @@ $.effects = { /******************************************************************************/ // override the animation for color styles -$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', - 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], +$.each(["backgroundColor", "borderBottomColor", "borderLeftColor", + "borderRightColor", "borderTopColor", "borderColor", "color", "outlineColor"], function(i, attr) { $.fx.step[attr] = function(fx) { if (!fx.colorInit) { @@ -30,10 +30,10 @@ function(i, attr) { fx.colorInit = true; } - fx.elem.style[attr] = 'rgb(' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; + fx.elem.style[attr] = "rgb(" + + Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + "," + + Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + "," + + Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ")"; }; }); @@ -46,7 +46,7 @@ function getRGB(color) { var result; // Check if we're already dealing with an array of colors - if ( color && color.constructor == Array && color.length == 3 ) + if ( color && color.constructor === Array && color.length === 3 ) return color; // Look for rgb(num,num,num) @@ -67,7 +67,7 @@ function getRGB(color) { // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) - return colors['transparent']; + return colors["transparent"]; // Otherwise, we're most likely dealing with a named color return colors[$.trim(color).toLowerCase()]; @@ -80,7 +80,7 @@ function getColor(elem, attr) { color = $.curCSS(elem, attr); // Keep going until we find an element that has color, or we hit the body - if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) + if ( color != "" && color !== "transparent" || $.nodeName(elem, "body") ) break; attr = "backgroundColor"; @@ -160,7 +160,7 @@ var classAnimationActions = [ "add", "remove", "toggle" ], }, // prefix used for storing data on .data() dataSpace = "ec.storage."; - + $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function(_, prop) { $.fx.step[ prop ] = function( fx ) { if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { @@ -168,7 +168,7 @@ $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopS fx.setAttr = true; } }; -}) +}); function getElementStyles() { var style = document.defaultView @@ -225,63 +225,93 @@ $.effects.animateClass = function( value, duration, easing, callback ) { var animated = $( this ), baseClass = animated.attr( "class" ), finalClass, - originalStyleAttr = animated.attr( "style" ) || ' ', - originalStyle = getElementStyles.call( this ), - newStyle, - diff, - prop; + allAnimations = o.children ? animated.find( "*" ).andSelf() : animated; + + // map the animated objects to store the original styles. + allAnimations = allAnimations.map(function() { + var el = $( this ); + return { + el: el, + originalStyleAttr: el.attr( "style" ) || " ", + start: getElementStyles.call( this ) + }; + }); + // apply class change $.each( classAnimationActions, function(i, action) { if ( value[ action ] ) { animated[ action + "Class" ]( value[ action ] ); } }); - newStyle = getElementStyles.call( this ); finalClass = animated.attr( "class" ); + + // map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map(function() { + this.end = getElementStyles.call( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + }); + + // apply original class animated.attr( "class", baseClass ); - diff = styleDifference( originalStyle, newStyle ); - animated - .animate( diff, { - duration: duration, + // map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map(function() { + var styleInfo = this, + dfd = $.Deferred(); + + this.el.animate( this.diff, { + duration: o.duration, easing: o.easing, queue: false, complete: function() { - animated.attr( "class", finalClass ); + dfd.resolve( styleInfo ); + } + }); + return dfd.promise(); + }); - if ( typeof animated.attr( 'style' ) == 'object' ) { - animated.attr( 'style' ).cssText = ''; - animated.attr( 'style' ).cssText = originalStyleAttr; - } else { - animated.attr( 'style', originalStyleAttr ); - } + // once all animations have completed: + $.when.apply( $, allAnimations.get() ).done(function() { + + // set the final class + animated.attr( "class", finalClass ); - // this is guarnteed to be there if you use jQuery.speed() - // it also handles dequeuing the next anim... - o.complete.call( this ); + // for each animated element + $.each( arguments, function() { + if ( typeof this.el.attr( "style" ) === "object" ) { + this.el.attr( "style" ).cssText = ""; + this.el.attr( "style" ).cssText = this.originalStyleAttr; + } else { + this.el.attr( "style", this.originalStyleAttr ); } }); + + // this is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + }); }); }; $.fn.extend({ _addClass: $.fn.addClass, addClass: function( classNames, speed, easing, callback ) { - return speed ? + return speed ? $.effects.animateClass.apply( this, [{ add: classNames }, speed, easing, callback ]) : this._addClass(classNames); }, _removeClass: $.fn.removeClass, removeClass: function( classNames, speed, easing, callback ) { - return speed ? + return speed ? $.effects.animateClass.apply( this, [{ remove: classNames }, speed, easing, callback ]) : this._removeClass(classNames); }, _toggleClass: $.fn.toggleClass, toggleClass: function( classNames, force, speed, easing, callback ) { - if ( typeof force == "boolean" || force === undefined ) { + if ( typeof force === "boolean" || force === undefined ) { if ( !speed ) { // without speed parameter; return this._toggleClass( classNames, force ); @@ -295,9 +325,9 @@ $.fn.extend({ }, switchClass: function( remove, add, speed, easing, callback) { - return $.effects.animateClass.apply( this, [{ - add: add, - remove: remove + return $.effects.animateClass.apply( this, [{ + add: add, + remove: remove }, speed, easing, callback ]); } }); @@ -330,26 +360,26 @@ $.extend( $.effects, { }, setMode: function( el, mode ) { - if (mode == 'toggle') { - mode = el.is( ':hidden' ) ? 'show' : 'hide'; + if (mode === "toggle") { + mode = el.is( ":hidden" ) ? "show" : "hide"; } return mode; }, // Translates a [top,left] array into a baseline value // this should be a little more flexible in the future to handle a string & hash - getBaseline: function( origin, original ) { + getBaseline: function( origin, original ) { var y, x; switch ( origin[ 0 ] ) { - case 'top': y = 0; break; - case 'middle': y = 0.5; break; - case 'bottom': y = 1; break; + case "top": y = 0; break; + case "middle": y = 0.5; break; + case "bottom": y = 1; break; default: y = origin[ 0 ] / original.height; }; switch ( origin[ 1 ] ) { - case 'left': x = 0; break; - case 'center': x = 0.5; break; - case 'right': x = 1; break; + case "left": x = 0; break; + case "center": x = 0.5; break; + case "right": x = 1; break; default: x = origin[ 1 ] / original.width; }; return { @@ -362,7 +392,7 @@ $.extend( $.effects, { createWrapper: function( element ) { // if the element is already wrapped, return it - if ( element.parent().is( '.ui-effects-wrapper' )) { + if ( element.parent().is( ".ui-effects-wrapper" )) { return element.parent(); } @@ -370,14 +400,14 @@ $.extend( $.effects, { var props = { width: element.outerWidth(true), height: element.outerHeight(true), - 'float': element.css( 'float' ) + "float": element.css( "float" ) }, - wrapper = $( '<div></div>' ) - .addClass( 'ui-effects-wrapper' ) + wrapper = $( "<div></div>" ) + .addClass( "ui-effects-wrapper" ) .css({ - fontSize: '100%', - background: 'transparent', - border: 'none', + fontSize: "100%", + background: "transparent", + border: "none", margin: 0, padding: 0 }); @@ -386,26 +416,26 @@ $.extend( $.effects, { wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element // transfer positioning properties to the wrapper - if ( element.css( 'position' ) == 'static' ) { - wrapper.css({ position: 'relative' }); - element.css({ position: 'relative' }); + if ( element.css( "position" ) === "static" ) { + wrapper.css({ position: "relative" }); + element.css({ position: "relative" }); } else { $.extend( props, { - position: element.css( 'position' ), - zIndex: element.css( 'z-index' ) + position: element.css( "position" ), + zIndex: element.css( "z-index" ) }); - $.each([ 'top', 'left', 'bottom', 'right' ], function(i, pos) { + $.each([ "top", "left", "bottom", "right" ], function(i, pos) { props[ pos ] = element.css( pos ); if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { - props[ pos ] = 'auto'; + props[ pos ] = "auto"; } }); element.css({ - position: 'relative', + position: "relative", top: 0, left: 0, - right: 'auto', - bottom: 'auto' + right: "auto", + bottom: "auto" }); } @@ -413,7 +443,7 @@ $.extend( $.effects, { }, removeWrapper: function( element ) { - if ( element.parent().is( '.ui-effects-wrapper' ) ) + if ( element.parent().is( ".ui-effects-wrapper" ) ) return element.parent().replaceWith( element ); return element; }, @@ -452,7 +482,7 @@ function _normalizeArguments( effect, options, speed, callback ) { } // catch (effect, speed, ?) - if ( $.type( options ) == 'number' || $.fx.speeds[ options ]) { + if ( $.type( options ) === "number" || $.fx.speeds[ options ]) { callback = speed; speed = options; options = {}; @@ -468,9 +498,9 @@ function _normalizeArguments( effect, options, speed, callback ) { if ( options ) { $.extend( effect, options ); } - + speed = speed || options.duration; - effect.duration = $.fx.off ? 0 : typeof speed == 'number' + effect.duration = $.fx.off ? 0 : typeof speed === "number" ? speed : speed in $.fx.speeds ? $.fx.speeds[ speed ] : $.fx.speeds._default; effect.complete = callback || options.complete; @@ -483,7 +513,7 @@ function standardSpeed( speed ) { if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { return true; } - + // invalid strings - treat as "normal" speed if ( typeof speed === "string" && !$.effects.effect[ speed ] ) { // TODO: remove in 2.0 (#7115) @@ -492,7 +522,7 @@ function standardSpeed( speed ) { } return true; } - + return false; } @@ -538,7 +568,7 @@ $.fn.extend({ return this._show.apply( this, arguments ); } else { var args = _normalizeArguments.apply( this, arguments ); - args.mode = 'show'; + args.mode = "show"; return this.effect.call( this, args ); } }, @@ -549,7 +579,7 @@ $.fn.extend({ return this._hide.apply( this, arguments ); } else { var args = _normalizeArguments.apply( this, arguments ); - args.mode = 'hide'; + args.mode = "hide"; return this.effect.call( this, args ); } }, @@ -561,7 +591,7 @@ $.fn.extend({ return this.__toggle.apply( this, arguments ); } else { var args = _normalizeArguments.apply( this, arguments ); - args.mode = 'toggle'; + args.mode = "toggle"; return this.effect.call( this, args ); } }, @@ -571,7 +601,7 @@ $.fn.extend({ var style = this.css( key ), val = []; - $.each( [ 'em', 'px', '%', 'pt' ], function( i, unit ) { + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { if ( style.indexOf( unit ) > 0 ) val = [ parseFloat( style ), unit ]; }); @@ -626,7 +656,7 @@ $.fn.extend({ $.easing.jswing = $.easing.swing; $.extend( $.easing, { - def: 'easeOutQuad', + def: "easeOutQuad", swing: function ( x, t, b, c, d ) { return $.easing[ $.easing.def ]( x, t, b, c, d ); }, @@ -707,9 +737,9 @@ $.extend( $.easing, { a = c; if ( t == 0 ) return b; if ( ( t /= d ) == 1 ) return b+c; - if ( a < Math.abs( c ) ) { - a = c; - s = p / 4; + if ( a < Math.abs( c ) ) { + a = c; + s = p / 4; } else { s = p / ( 2 * Math.PI ) * Math.asin( c / a ); } @@ -722,8 +752,8 @@ $.extend( $.easing, { if ( t == 0 ) return b; if ( ( t /= d ) == 1 ) return b+c; if ( a < Math.abs( c ) ) { - a = c; - s = p / 4; + a = c; + s = p / 4; } else { s = p / ( 2 * Math.PI ) * Math.asin( c / a ); } @@ -735,7 +765,7 @@ $.extend( $.easing, { a = c; if ( t == 0 ) return b; if ( ( t /= d / 2 ) == 2 ) return b+c; - if ( a < Math.abs( c ) ) { + if ( a < Math.abs( c ) ) { a = c; s = p / 4; } else { diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index 031ac2091..e5eedc3e5 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -13,7 +13,7 @@ */ (function( $, undefined ) { -var lastActive, +var lastActive, startXPos, startYPos, clickDragged, baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", stateClasses = "ui-state-hover ui-state-active ", typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", @@ -112,13 +112,36 @@ $.widget( "ui.button", { if ( toggleButton ) { this.element.bind( "change.button", function() { + if ( clickDragged ) { + return; + } self.refresh(); }); + // if mouse moves between mousedown and mouseup (drag) set clickDragged flag + // prevents issue where button state changes but checkbox/radio checked state + // does not in Firefox (see ticket #6970) + this.buttonElement + .bind( "mousedown.button", function( event ) { + if ( options.disabled ) { + return; + } + clickDragged = false; + startXPos = event.pageX; + startYPos = event.pageY; + }) + .bind( "mouseup.button", function( event ) { + if ( options.disabled ) { + return; + } + if ( startXPos !== event.pageX || startYPos !== event.pageY ) { + clickDragged = true; + } + }); } if ( this.type === "checkbox" ) { this.buttonElement.bind( "click.button", function() { - if ( options.disabled ) { + if ( options.disabled || clickDragged ) { return false; } $( this ).toggleClass( "ui-state-active" ); @@ -126,7 +149,7 @@ $.widget( "ui.button", { }); } else if ( this.type === "radio" ) { this.buttonElement.bind( "click.button", function() { - if ( options.disabled ) { + if ( options.disabled || clickDragged ) { return false; } $( this ).addClass( "ui-state-active" ); @@ -185,6 +208,7 @@ $.widget( "ui.button", { // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can // be overridden by individual plugins this._setOption( "disabled", options.disabled ); + this._resetButton(); }, _determineButtonType: function() { @@ -250,6 +274,7 @@ $.widget( "ui.button", { } else { this.element.removeAttr( "disabled" ); } + return; } this._resetButton(); }, @@ -352,6 +377,8 @@ $.widget( "ui.buttonset", { }, refresh: function() { + var ltr = this.element.css( "direction" ) === "ltr"; + this.buttons = this.element.find( this.options.items ) .filter( ":ui-button" ) .button( "refresh" ) @@ -364,10 +391,10 @@ $.widget( "ui.buttonset", { }) .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) .filter( ":first" ) - .addClass( "ui-corner-left" ) + .addClass( ltr ? "ui-corner-left" : "ui-corner-right" ) .end() .filter( ":last" ) - .addClass( "ui-corner-right" ) + .addClass( ltr ? "ui-corner-right" : "ui-corner-left" ) .end() .end(); }, diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index de2df6064..021041202 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -614,6 +614,9 @@ $.extend(Datepicker.prototype, { return; var inst = $.datepicker._getInst(input); if ($.datepicker._curInst && $.datepicker._curInst != inst) { + if ( $.datepicker._datepickerShowing ) { + $.datepicker._triggerOnClose($.datepicker._curInst); + } $.datepicker._curInst.dpDiv.stop(true, true); } var beforeShow = $.datepicker._get(inst, 'beforeShow'); @@ -707,7 +710,7 @@ $.extend(Datepicker.prototype, { var origyearshtml = inst.yearshtml; setTimeout(function(){ //assure that inst.yearshtml didn't change. - if( origyearshtml === inst.yearshtml ){ + if( origyearshtml === inst.yearshtml && inst.yearshtml ){ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); } origyearshtml = inst.yearshtml = null; @@ -759,6 +762,14 @@ $.extend(Datepicker.prototype, { return [position.left, position.top]; }, + /* Trigger custom callback of onClose. */ + _triggerOnClose: function(inst) { + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); + }, + /* Hide the date picker from view. @param input element - the input field attached to the date picker */ _hideDatepicker: function(input) { @@ -781,10 +792,7 @@ $.extend(Datepicker.prototype, { (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); if (!showAnim) postProcess(); - var onClose = this._get(inst, 'onClose'); - if (onClose) - onClose.apply((inst.input ? inst.input[0] : null), - [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback + $.datepicker._triggerOnClose(inst); this._datepickerShowing = false; this._lastInput = null; if (this._inDialog) { @@ -1185,7 +1193,7 @@ $.extend(Datepicker.prototype, { break; case 'o': output += formatNumber('o', - (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3); + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); break; case 'm': output += formatNumber('m', date.getMonth() + 1, 2); @@ -1606,14 +1614,9 @@ $.extend(Datepicker.prototype, { '>' + year + '</option>'; } inst.yearshtml += '</select>'; - //when showing there is no need for later update - if( ! $.browser.mozilla ){ - html += inst.yearshtml; - inst.yearshtml = null; - } else { - // will be replaced later with inst.yearshtml - html += '<select class="ui-datepicker-year"><option value="' + drawYear + '" selected="selected">' + drawYear + '</option></select>'; - } + + html += inst.yearshtml; + inst.yearshtml = null; } } html += this._get(inst, 'yearSuffix'); diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 2e8fb7f18..dc2849155 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -281,10 +281,10 @@ $.widget("ui.dialog", { options = self.options, uiDialog = self.uiDialog; - self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null; self._size(); self._position( options.position ); uiDialog.show( options.show ); + self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null; self.moveToTop( true ); // prevent tabbing out of modal dialogs @@ -742,7 +742,7 @@ $.extend( $.ui.dialog.overlay, { $( [ document, window ] ).unbind( ".dialog-overlay" ); } - $el.remove(); + $el.height( 0 ).width( 0 ).remove(); // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) var maxZ = 0; @@ -755,8 +755,8 @@ $.extend( $.ui.dialog.overlay, { height: function() { var scrollHeight, offsetHeight; - // handle IE 6 - if ( $.browser.msie && $.browser.version < 7 ) { + // handle IE + if ( $.browser.msie ) { scrollHeight = Math.max( document.documentElement.scrollHeight, document.body.scrollHeight diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index d7bc09578..c16833eb0 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -355,8 +355,8 @@ $.widget("ui.draggable", $.ui.mouse, { var o = this.options; if(o.containment == 'parent') o.containment = this.helper[0].parentNode; if(o.containment == 'document' || o.containment == 'window') this.containment = [ - (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left, - (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top, + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top ]; @@ -436,10 +436,11 @@ $.widget("ui.draggable", $.ui.mouse, { } if(o.grid) { - var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; } diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index b8cca7dcd..2709175b5 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -11,11 +11,11 @@ * jquery.ui.core.js * jquery.ui.widget.js */ -(function($) { +(function( $ ) { -$.widget('ui.spinner', { +$.widget( "ui.spinner", { defaultElement: "<input>", - widgetEventPrefix: "spin", + widgetEventPrefix: "spin", options: { incremental: true, max: null, @@ -25,218 +25,227 @@ $.widget('ui.spinner', { step: null, value: null }, - + _create: function() { this._draw(); this._markupOptions(); this._mousewheel(); this._aria(); }, - + _markupOptions: function() { - var _this = this; + var that = this; $.each({ min: -Number.MAX_VALUE, max: Number.MAX_VALUE, step: 1 - }, function(attr, defaultValue) { - if (_this.options[attr] === null) { - var value = _this.element.attr(attr); - _this.options[attr] = typeof value == "string" && value.length > 0 ? _this._parse(value) : defaultValue; + }, function( attr, defaultValue ) { + if ( that.options[ attr ] === null ) { + var value = that.element.attr( attr ); + that.options[ attr ] = typeof value === "string" && value.length > 0 ? + that._parse( value ) : + defaultValue; } }); - this.value(this.options.value !== null ? this.options.value : this.element.val() || 0); + this.value( this.options.value !== null ? this.options.value : this.element.val() || 0 ); }, - + _draw: function() { var self = this, options = self.options; var uiSpinner = this.uiSpinner = self.element - .addClass('ui-spinner-input') - .attr('autocomplete', 'off') - .wrap(self._uiSpinnerHtml()) + .addClass( "ui-spinner-input" ) + .attr( "autocomplete", "off" ) + .wrap( self._uiSpinnerHtml() ) .parent() // add buttons - .append(self._buttonHtml()) + .append( self._buttonHtml() ) // add behaviours + // TODO: user ._hoverable .hover(function() { - if (!options.disabled) { - $(this).addClass('ui-state-hover'); + if ( !options.disabled ) { + $( this ).addClass( "ui-state-hover" ); } self.hovered = true; }, function() { - $(this).removeClass('ui-state-hover'); + $( this ).removeClass( "ui-state-hover" ); self.hovered = false; }); + // TODO: use ._bind() this.element .attr( "role", "spinbutton" ) - .bind('keydown.spinner', function(event) { - if (self.options.disabled) { + .bind( "keydown.spinner", function( event ) { + if ( options.disabled ) { return; } - if (self._start(event)) { - return self._keydown(event); + if ( self._start( event ) ) { + return self._keydown( event ); } return true; }) - .bind('keyup.spinner', function(event) { - if (self.options.disabled) { + .bind( "keyup.spinner", function( event ) { + if ( options.disabled ) { return; } - if (self.spinning) { - self._stop(event); - self._change(event); + if ( self.spinning ) { + self._stop( event ); + self._change( event ); } }) - .bind('focus.spinner', function() { - uiSpinner.addClass('ui-state-active'); + .bind( "focus.spinner", function() { + uiSpinner.addClass( "ui-state-active" ); self.focused = true; }) - .bind('blur.spinner', function(event) { - self.value(self.element.val()); - if (!self.hovered) { - uiSpinner.removeClass('ui-state-active'); - } + .bind( "blur.spinner", function( event ) { + self.value( self.element.val() ); + if ( !self.hovered ) { + uiSpinner.removeClass( "ui-state-active" ); + } self.focused = false; }); // button bindings - this.buttons = uiSpinner.find('.ui-spinner-button') - .attr("tabIndex", -1) + this.buttons = uiSpinner.find( ".ui-spinner-button" ) + .attr( "tabIndex", -1 ) .button() - .removeClass("ui-corner-all") - .bind('mousedown', function(event) { - if (self.options.disabled) { + .removeClass( "ui-corner-all" ) + .bind( "mousedown", function( event ) { + if ( options.disabled ) { return; } - if (self._start(event) === false) { + if ( self._start( event ) === false ) { return false; } - self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event); + self._repeat( null, $( this ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); }) - .bind('mouseup', function(event) { - if (self.options.disabled) { + .bind( "mouseup", function( event ) { + if ( options.disabled ) { return; } - if (self.spinning) { - self._stop(event); - self._change(event); + if ( self.spinning ) { + self._stop( event ); + self._change( event ); } }) - .bind("mouseenter", function() { - if (self.options.disabled) { + .bind( "mouseenter", function() { + if ( self.options.disabled ) { return; } // button will add ui-state-active if mouse was down while mouseleave and kept down - if ($(this).hasClass("ui-state-active")) { - if (self._start(event) === false) { + if ( $( this ).hasClass( "ui-state-active" ) ) { + if ( self._start( event ) === false ) { return false; } - self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event); + self._repeat( null, $( this ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); } }) - .bind("mouseleave", function() { - if (self.spinning) { - self._stop(event); - self._change(event); + .bind( "mouseleave", function() { + if ( self.spinning ) { + self._stop( event ); + self._change( event ); } }); - + // disable spinner if element was already disabled - if (options.disabled) { + if ( options.disabled ) { this.disable(); } }, - - _keydown: function(event) { - var o = this.options, - KEYS = $.ui.keyCode; - - switch (event.keyCode) { - case KEYS.UP: - this._repeat(null, 1, event); + + _keydown: function( event ) { + var options = this.options, + keyCode = $.ui.keyCode; + + switch ( event.keyCode ) { + case keyCode.UP: + this._repeat( null, 1, event ); return false; - case KEYS.DOWN: - this._repeat(null, -1, event); + case keyCode.DOWN: + this._repeat( null, -1, event ); return false; - case KEYS.PAGE_UP: - this._repeat(null, this.options.page, event); + case keyCode.PAGE_UP: + this._repeat( null, options.page, event ); return false; - case KEYS.PAGE_DOWN: - this._repeat(null, -this.options.page, event); + case keyCode.PAGE_DOWN: + this._repeat( null, -options.page, event ); return false; - - case KEYS.ENTER: - this.value(this.element.val()); + case keyCode.ENTER: + this.value( this.element.val() ); } - + return true; }, - + _mousewheel: function() { // need the delta normalization that mousewheel plugin provides - if (!$.fn.mousewheel) { + if ( !$.fn.mousewheel ) { return; } var self = this; - this.element.bind("mousewheel.spinner", function(event, delta) { - if (self.options.disabled || !delta) { + this.element.bind( "mousewheel.spinner", function( event, delta ) { + if ( self.options.disabled || !delta ) { return; } - if (!self.spinning && !self._start(event)) { + if ( !self.spinning && !self._start( event ) ) { return false; } - self._spin((delta > 0 ? 1 : -1) * self.options.step, event); - clearTimeout(self.timeout); + self._spin( (delta > 0 ? 1 : -1) * self.options.step, event ); + clearTimeout( self.timeout ); self.timeout = setTimeout(function() { - if (self.spinning) { - self._stop(event); - self._change(event); + if ( self.spinning ) { + self._stop( event ); + self._change( event ); } }, 100); event.preventDefault(); }); }, - + _uiSpinnerHtml: function() { - return '<span class="ui-spinner ui-state-default ui-widget ui-widget-content ui-corner-all"></span>'; + return "<span class='ui-spinner ui-state-default ui-widget ui-widget-content ui-corner-all'></span>"; }, - + _buttonHtml: function() { - return '<a class="ui-spinner-button ui-spinner-up ui-corner-tr"><span class="ui-icon ui-icon-triangle-1-n">▲</span></a>' + - '<a class="ui-spinner-button ui-spinner-down ui-corner-br"><span class="ui-icon ui-icon-triangle-1-s">▼</span></a>'; + return "" + + "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + + "<span class='ui-icon ui-icon-triangle-1-n'>▲</span>" + + "</a>" + + "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + + "<span class='ui-icon ui-icon-triangle-1-s'>▼</span>" + + "</a>"; }, - - _start: function(event) { - if (!this.spinning && this._trigger('start', event) !== false) { - if (!this.counter) { - this.counter = 1; - } - this.spinning = true; - return true; + + _start: function( event ) { + if ( !this.spinning && this._trigger( "start", event ) === false ) { + return false; + } + + if ( !this.counter ) { + this.counter = 1; } - return false; + this.spinning = true; + return true; }, - - _repeat: function(i, steps, event) { + + _repeat: function( i, steps, event ) { var self = this; i = i || 500; - clearTimeout(this.timer); + clearTimeout( this.timer ); this.timer = setTimeout(function() { - self._repeat(40, steps, event); - }, i); - - self._spin(steps * self.options.step, event); + self._repeat( 40, steps, event ); + }, i ); + + self._spin( steps * self.options.step, event ); }, - - _spin: function(step, event) { - if (!this.counter) { + + _spin: function( step, event ) { + if ( !this.counter ) { this.counter = 1; } - + // TODO refactor, maybe figure out some non-linear math var newVal = this.value() + step * (this.options.incremental && this.counter > 20 @@ -246,49 +255,51 @@ $.widget('ui.spinner', { : 10 : 2 : 1); - - if (this._trigger('spin', event, { value: newVal }) !== false) { - this.value(newVal); - this.counter++; + + if ( this._trigger( "spin", event, { value: newVal } ) !== false) { + this.value( newVal ); + this.counter++; } }, - - _stop: function(event) { + + _stop: function( event ) { this.counter = 0; - if (this.timer) { - window.clearTimeout(this.timer); + if ( this.timer ) { + clearTimeout( this.timer ); } this.element.focus(); this.spinning = false; - this._trigger('stop', event); + this._trigger( "stop", event ); }, - - _change: function(event) { - this._trigger('change', event); + + _change: function( event ) { + this._trigger( "change", event ); }, - - _setOption: function(key, value) { - if (key == 'value') { - value = this._parse(value); - if (value < this.options.min) { + + _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) { + if ( value > this.options.max ) { value = this.options.max; } } - if (key == 'disabled') { - if (value) { - this.element.attr("disabled", true); - this.buttons.button("disable"); + + if ( key === "disabled" ) { + if ( value ) { + this.element.attr( "disabled", true ); + this.buttons.button( "disable" ); } else { - this.element.removeAttr("disabled"); - this.buttons.button("enable"); + this.element.removeAttr( "disabled" ); + this.buttons.button( "enable" ); } } + this._super( "_setOption", key, value ); }, - + _setOptions: function( options ) { this._super( "_setOptions", options ); if ( "value" in options ) { @@ -296,62 +307,62 @@ $.widget('ui.spinner', { } this._aria(); }, - + _aria: function() { - this.element - .attr('aria-valuemin', this.options.min) - .attr('aria-valuemax', this.options.max) - .attr('aria-valuenow', this.options.value); + this.element.attr({ + "aria-valuemin": this.options.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this.options.value + }); }, - - _parse: function(val) { - var input = val; - if (typeof val == 'string') { - val = $.global && this.options.numberformat ? $.global.parseFloat(val) : +val; + + _parse: function( val ) { + if ( typeof val === "string" ) { + val = $.global && this.options.numberformat ? $.global.parseFloat( val ) : +val; } - return isNaN(val) ? null : val; + return isNaN( val ) ? null : val; }, - - _format: function(num) { - this.element.val( $.global && this.options.numberformat ? $.global.format(num, this.options.numberformat) : num ); + + _format: function( num ) { + this.element.val( $.global && this.options.numberformat ? $.global.format( num, this.options.numberformat ) : num ); }, - + destroy: function() { this.element - .removeClass('ui-spinner-input') - .removeAttr('disabled') - .removeAttr('autocomplete') - .removeAttr('role') - .removeAttr('aria-valuemin') - .removeAttr('aria-valuemax') - .removeAttr('aria-valuenow'); + .removeClass( "ui-spinner-input" ) + .removeAttr( "disabled" ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); this._super( "destroy" ); - this.uiSpinner.replaceWith(this.element); + this.uiSpinner.replaceWith( this.element ); }, - - stepUp: function(steps) { - this._spin((steps || 1) * this.options.step); + + stepUp: function( steps ) { + this._spin( (steps || 1) * this.options.step ); }, - - stepDown: function(steps) { - this._spin((steps || 1) * -this.options.step); + + stepDown: function( steps ) { + this._spin( (steps || 1) * -this.options.step ); }, - - pageUp: function(pages) { - this.stepUp((pages || 1) * this.options.page); + + pageUp: function( pages ) { + this.stepUp( (pages || 1) * this.options.page ); }, - - pageDown: function(pages) { - this.stepDown((pages || 1) * this.options.page); + + pageDown: function( pages ) { + this.stepDown( (pages || 1) * this.options.page ); }, - - value: function(newVal) { - if (!arguments.length) { - return this._parse(this.element.val()); + + value: function( newVal ) { + if ( !arguments.length ) { + return this._parse( this.element.val() ); } - this.option('value', newVal); + this.option( "value", newVal ); }, - + widget: function() { return this.uiSpinner; } @@ -359,4 +370,4 @@ $.widget('ui.spinner', { $.ui.spinner.version = "@VERSION"; -})(jQuery); +}( jQuery ) ); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 76f4fb274..239805b14 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -13,7 +13,7 @@ */ (function( $, undefined ) { -var tabId = 0 +var tabId = 0; function getNextTabId() { return ++tabId; } @@ -144,7 +144,7 @@ $.widget( "ui.tabs", { _sanitizeSelector: function( hash ) { // we need this because an id may contain a ":" - return hash ? hash.replace( /:/g, "\\:" ) : ""; + return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@[\]^`{|}~]/g, "\\$&" ) : ""; }, refresh: function() { @@ -286,61 +286,13 @@ $.widget( "ui.tabs", { } }, - // Reset certain styles left over from animation - // and prevent IE's ClearType bug... + // TODO: remove once jQuery core properly removes filters - see #4621 _resetStyle: function ( $el, fx ) { - $el.css( "display", "" ); if ( !$.support.opacity && fx.opacity ) { $el[ 0 ].style.removeAttribute( "filter" ); } }, - _showTab: function( event, eventData ) { - var that = this; - - $( eventData.newTab ).closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); - - if ( that.showFx ) { - that.running = true; - eventData.newPanel - // TODO: why are we hiding? old code? - .hide() - .animate( that.showFx, that.showFx.duration || "normal", function() { - that._resetStyle( $( this ), that.showFx ); - that.running = false; - that._trigger( "activate", event, eventData ); - }); - } else { - eventData.newPanel.show(); - that._trigger( "activate", event, eventData ); - } - }, - - // TODO: combine with _showTab() - _hideTab: function( event, eventData ) { - var that = this; - - if ( that.hideFx ) { - that.running = true; - eventData.oldPanel.animate( that.hideFx, that.hideFx.duration || "normal", function() { - that.running = false; - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); - that._resetStyle( $( this ), that.hideFx ); - that.element.dequeue( "tabs" ); - if ( !eventData.newPanel.length ) { - that._trigger( "activate", event, eventData ); - } - }); - } else { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); - eventData.oldPanel.hide(); - that.element.dequeue( "tabs" ); - if ( !eventData.newPanel.length ) { - that._trigger( "activate", event, eventData ); - } - } - }, - _setupEvents: function( event ) { // attach tab event handler, unbind to avoid duplicates from former tabifying... this.anchors.unbind( ".tabs" ); @@ -399,22 +351,56 @@ $.widget( "ui.tabs", { throw "jQuery UI Tabs: Mismatching fragment identifier."; } - if ( toHide.length ) { - that.element.queue( "tabs", function() { - that._hideTab( event, eventData ); - }); - } if ( toShow.length ) { - that.element.queue( "tabs", function() { - that._showTab( event, eventData ); - }); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 that.load( that.anchors.index( clicked ), event ); clicked[ 0 ].blur(); + } + that._toggle( event, eventData ); + }, + + // handles show/hide for selecting tabs + _toggle: function( event, eventData ) { + var that = this, + options = that.options, + toShow = eventData.newPanel, + toHide = eventData.oldPanel; + + that.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && that.showFx ) { + toShow + .animate( that.showFx, that.showFx.duration || "normal", function() { + that._resetStyle( $( this ), that.showFx ); + complete(); + }); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && that.hideFx ) { + toHide.animate( that.hideFx, that.hideFx.duration || "normal", function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + that._resetStyle( $( this ), that.hideFx ); + show(); + }); } else { - that.element.dequeue( "tabs" ); + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); } }, @@ -537,24 +523,19 @@ $.widget( "ui.tabs", { load: function( index, event ) { index = this._getIndex( index ); var self = this, - o = this.options, - a = this.anchors.eq( index )[ 0 ], - panel = self._getPanelForTab( a ), + options = this.options, + anchor = this.anchors.eq( index ), + panel = self._getPanelForTab( anchor ), // TODO until #3808 is fixed strip fragment identifier from url // (IE fails to load from such url) - url = $( a ).attr( "href" ).replace( /#.*$/, "" ), + url = anchor.attr( "href" ).replace( /#.*$/, "" ), eventData = { - tab: $( a ), + tab: anchor, panel: panel }; - if ( this.xhr ) { - this.xhr.abort(); - } - // not remote if ( !url ) { - this.element.dequeue( "tabs" ); return; } @@ -567,7 +548,6 @@ $.widget( "ui.tabs", { }); if ( this.xhr ) { - // load remote from here on this.lis.eq( index ).addClass( "ui-tabs-loading" ); this.xhr @@ -577,24 +557,17 @@ $.widget( "ui.tabs", { }) .complete(function( jqXHR, status ) { if ( status === "abort" ) { - // stop possibly running animations - self.element.queue( [] ); self.panels.stop( false, true ); - - // "tabs" queue must not contain more than two elements, - // which are the callbacks for the latest clicked tab... - self.element.queue( "tabs", self.element.queue( "tabs" ).splice( -2, 2 ) ); } self.lis.eq( index ).removeClass( "ui-tabs-loading" ); - delete self.xhr; + if ( jqXHR === self.xhr ) { + delete self.xhr; + } }); } - // last, so that load event is fired before show... - self.element.dequeue( "tabs" ); - return this; }, @@ -793,20 +766,30 @@ if ( $.uiBackCompat !== false ) { li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); li.find( "a" ).attr( "aria-controls", id ); + var doInsertAfter = index >= this.lis.length; + // try to find an existing element before creating a new one var panel = this.element.find( "#" + id ); if ( !panel.length ) { panel = this._createPanel( id ); + if ( doInsertAfter ) { + if ( index > 0 ) { + panel.insertAfter( this.panels.eq( -1 ) ); + } else { + panel.appendTo( this.element ); + } + } else { + panel.insertBefore( this.panels[ index ] ); + } } panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); - if ( index >= this.lis.length ) { + if ( doInsertAfter ) { li.appendTo( this.list ); - panel.appendTo( this.list[ 0 ].parentNode ); } else { li.insertBefore( this.lis[ index ] ); - panel.insertBefore( this.panels[ index ] ); } + options.disabled = $.map( options.disabled, function( n ) { return n >= index ? ++n : n; }); @@ -938,7 +921,7 @@ if ( $.uiBackCompat !== false ) { this._trigger( "show", null, this._ui( this.active[ 0 ], this._getPanelForTab( this.active )[ 0 ] ) ); } - } + }; prototype._trigger = function( type, event, data ) { var ret = _trigger.apply( this, arguments ); if ( !ret ) { @@ -1024,6 +1007,18 @@ if ( $.uiBackCompat !== false ) { } } }); + + // load event + $.widget( "ui.tabs", $.ui.tabs, { + _trigger: function( type, event, data ) { + var _data = $.extend( {}, data ); + if ( type === "load" ) { + _data.panel = _data.panel[ 0 ]; + _data.tab = _data.tab[ 0 ]; + } + return this._super( "_trigger", type, event, _data ); + } + }); } })( jQuery ); |