diff options
author | Scott González <scott.gonzalez@gmail.com> | 2011-01-31 22:04:09 -0500 |
---|---|---|
committer | Scott González <scott.gonzalez@gmail.com> | 2011-01-31 22:04:09 -0500 |
commit | cb8f5b7f2679ab5473229cac432f28c72521048c (patch) | |
tree | 60b63ec0b7f190832dcadef9e04a195985e61621 | |
parent | bb857ddd8d6d4ac7620b49bf765352cd064494c0 (diff) | |
parent | effbb2c0ec2e60bea6ec5e5822ee52f8ea9e18bc (diff) | |
download | jquery-ui-cb8f5b7f2679ab5473229cac432f28c72521048c.tar.gz jquery-ui-cb8f5b7f2679ab5473229cac432f28c72521048c.zip |
Merge branch 'master' into widget-events
Conflicts:
ui/jquery.ui.widget.js
29 files changed, 1845 insertions, 958 deletions
diff --git a/demos/datepicker/date-range.html b/demos/datepicker/date-range.html index 1e3beb2a2..6bce3f776 100644 --- a/demos/datepicker/date-range.html +++ b/demos/datepicker/date-range.html @@ -17,7 +17,7 @@ numberOfMonths: 3, onSelect: function( selectedDate ) { var option = this.id == "from" ? "minDate" : "maxDate", - instance = $( this ).data( "datepicker" ); + instance = $( this ).data( "datepicker" ), date = $.datepicker.parseDate( instance.settings.dateFormat || $.datepicker._defaults.dateFormat, diff --git a/demos/datepicker/localization.html b/demos/datepicker/localization.html index 33d03c98c..767cdaa54 100644 --- a/demos/datepicker/localization.html +++ b/demos/datepicker/localization.html @@ -10,6 +10,7 @@ <script src="../../ui/jquery.ui.datepicker.js"></script> <script src="../../ui/i18n/jquery.ui.datepicker-af.js"></script> <script src="../../ui/i18n/jquery.ui.datepicker-ar.js"></script> + <script src="../../ui/i18n/jquery.ui.datepicker-ar-DZ.js"></script> <script src="../../ui/i18n/jquery.ui.datepicker-az.js"></script> <script src="../../ui/i18n/jquery.ui.datepicker-bg.js"></script> <script src="../../ui/i18n/jquery.ui.datepicker-bs.js"></script> @@ -87,6 +88,7 @@ <select id="locale"> <option value="af">Afrikaans</option> <option value="sq">Albanian (Gjuha shqipe)</option> + <option value="ar-DZ">Algerian Arabic</option> <option value="ar">Arabic (‫(لعربي</option> <option value="hy">Armenian (Հայերեն)</option> <option value="az">Azerbaijani (Azərbaycan dili)</option> diff --git a/demos/index.html b/demos/index.html index c1efefe73..e1f4eec91 100644 --- a/demos/index.html +++ b/demos/index.html @@ -44,6 +44,7 @@ <script src="../ui/jquery.effects.transfer.js"></script> <script src="../ui/i18n/jquery.ui.datepicker-af.js"></script> <script src="../ui/i18n/jquery.ui.datepicker-ar.js"></script> + <script src="../ui/i18n/jquery.ui.datepicker-ar-DZ.js"></script> <script src="../ui/i18n/jquery.ui.datepicker-az.js"></script> <script src="../ui/i18n/jquery.ui.datepicker-bs.js"></script> <script src="../ui/i18n/jquery.ui.datepicker-bg.js"></script> diff --git a/external/jquery.global.js b/external/jquery.global.js index fcaacf9c7..29ae5c637 100644 --- a/external/jquery.global.js +++ b/external/jquery.global.js @@ -151,14 +151,24 @@ Globalization.format = function(value, format, culture) { Globalization.parseInt = function(value, radix, culture) { return Math.floor( this.parseFloat( value, radix, culture ) ); } -Globalization.parseCurrency = function(value, culture) { - return this.parseFloat(value.replace(/[^\d,.-]/g, ""), 10, culture); -} Globalization.parseFloat = function(value, radix, culture) { + // make radix optional + if (typeof radix === "string") { + culture = radix; + radix = 10; + } + culture = this.findClosestCulture( culture ); var ret = NaN, nf = culture.numberFormat; + if (value.indexOf(culture.numberFormat.currency.symbol) > -1) { + // remove currency symbol + value = value.replace(culture.numberFormat.currency.symbol, ""); + // replace decimal seperator + value = value.replace(culture.numberFormat.currency["."], culture.numberFormat["."]); + } + // trim leading and trailing whitespace value = trim( value ); diff --git a/external/qunit.css b/external/qunit.css index a4daa27e4..500d404e3 100644 --- a/external/qunit.css +++ b/external/qunit.css @@ -10,7 +10,7 @@ /** Resets */ -#qunit-tests, #qunit-tests li ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { +#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { margin: 0; padding: 0; } @@ -20,10 +20,13 @@ #qunit-header { padding: 0.5em 0 0.5em 1em; - - color: #fff; - text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px; + + color: #8699a4; background-color: #0d3349; + + font-size: 1.5em; + line-height: 1em; + font-weight: normal; border-radius: 15px 15px 0 0; -moz-border-radius: 15px 15px 0 0; @@ -33,7 +36,12 @@ #qunit-header a { text-decoration: none; - color: white; + color: #c2ccd1; +} + +#qunit-header a:hover, +#qunit-header a:focus { + color: #fff; } #qunit-banner { @@ -41,7 +49,9 @@ } #qunit-testrunner-toolbar { - padding: 0em 0 0.5em 2em; + padding: 0.5em 0 0.5em 2em; + color: #5E740B; + background-color: #eee; } #qunit-userAgent { @@ -68,7 +78,7 @@ cursor: pointer; } -#qunit-tests li ol { +#qunit-tests ol { margin-top: 0.5em; padding: 0.5em; @@ -83,6 +93,45 @@ -webkit-box-shadow: inset 0px 2px 13px #999; } +#qunit-tests table { + border-collapse: collapse; + margin-top: .2em; +} + +#qunit-tests th { + text-align: right; + vertical-align: top; + padding: 0 .5em 0 0; +} + +#qunit-tests td { + vertical-align: top; +} + +#qunit-tests pre { + margin: 0; + white-space: pre-wrap; + word-wrap: break-word; +} + +#qunit-tests del { + background-color: #e0f2be; + color: #374e0c; + text-decoration: none; +} + +#qunit-tests ins { + background-color: #ffcaca; + color: #500; + text-decoration: none; +} + +/*** Test Counts */ + +#qunit-tests b.counts { color: black; } +#qunit-tests b.passed { color: #5E740B; } +#qunit-tests b.failed { color: #710909; } + #qunit-tests li li { margin: 0.5em; padding: 0.4em 0.5em 0.4em 0.5em; @@ -99,13 +148,11 @@ border-left: 26px solid #C6E746; } -#qunit-tests li.pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests li.pass span.test-name { color: #366097; } +#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } +#qunit-tests .pass .test-name { color: #366097; } -#qunit-tests li li.pass span.test-actual, -#qunit-tests li li.pass span.test-expected { color: #999999; } - -strong b.pass { color: #5E740B; } +#qunit-tests .pass .test-actual, +#qunit-tests .pass .test-expected { color: #999999; } #qunit-banner.qunit-pass { background-color: #C6E746; } @@ -117,31 +164,28 @@ strong b.pass { color: #5E740B; } border-left: 26px solid #EE5757; } -#qunit-tests li.fail { color: #000000; background-color: #EE5757; } -#qunit-tests li.fail span.test-name, -#qunit-tests li.fail span.module-name { color: #000000; } - -#qunit-tests li li.fail span.test-actual { color: #EE5757; } -#qunit-tests li li.fail span.test-expected { color: green; } +#qunit-tests .fail { color: #000000; background-color: #EE5757; } +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { color: #000000; } -strong b.fail { color: #710909; } +#qunit-tests .fail .test-actual { color: #EE5757; } +#qunit-tests .fail .test-expected { color: green; } -#qunit-banner.qunit-fail, -#qunit-testrunner-toolbar { background-color: #EE5757; } +#qunit-banner.qunit-fail { background-color: #EE5757; } /** Footer */ #qunit-testresult { padding: 0.5em 0.5em 0.5em 2.5em; - + color: #2b81af; background-color: #D2E0E6; border-radius: 0 0 15px 15px; -moz-border-radius: 0 0 15px 15px; -webkit-border-bottom-right-radius: 15px; - -webkit-border-bottom-left-radius: 15px; + -webkit-border-bottom-left-radius: 15px; } /** Fixture */ @@ -150,4 +194,4 @@ strong b.fail { color: #710909; } position: absolute; top: -10000px; left: -10000px; -} +}
\ No newline at end of file diff --git a/external/qunit.js b/external/qunit.js index 45ad1dcf8..3d7e7c1f3 100644 --- a/external/qunit.js +++ b/external/qunit.js @@ -3,229 +3,289 @@ * * http://docs.jquery.com/QUnit * - * Copyright (c) 2009 John Resig, Jörn Zaefferer + * Copyright (c) 2011 John Resig, Jörn Zaefferer * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. + * or GPL (GPL-LICENSE.txt) licenses. */ (function(window) { -var QUnit = { +var defined = { + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function() { + try { + return !!sessionStorage.getItem; + } catch(e){ + return false; + } + })() +} - // call on start of module test to prepend name to all tests - module: function(name, testEnvironment) { - config.currentModule = name; +var testId = 0; - synchronize(function() { - if ( config.currentModule ) { - QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); +var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { + this.name = name; + this.testName = testName; + this.expected = expected; + this.testEnvironmentArg = testEnvironmentArg; + this.async = async; + this.callback = callback; + this.assertions = []; +}; +Test.prototype = { + init: function() { + var tests = id("qunit-tests"); + if (tests) { + var b = document.createElement("strong"); + b.innerHTML = "Running " + this.name; + var li = document.createElement("li"); + li.appendChild( b ); + li.id = this.id = "test-output" + testId++; + tests.appendChild( li ); + } + }, + setup: function() { + if (this.module != config.previousModule) { + if ( config.previousModule ) { + QUnit.moduleDone( { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + } ); } - - config.currentModule = name; - config.moduleTestEnvironment = testEnvironment; + config.previousModule = this.module; config.moduleStats = { all: 0, bad: 0 }; + QUnit.moduleStart( { + name: this.module + } ); + } - QUnit.moduleStart( name, testEnvironment ); - }); - }, - - asyncTest: function(testName, expected, callback) { - if ( arguments.length === 2 ) { - callback = expected; - expected = 0; + config.current = this; + this.testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, this.moduleTestEnvironment); + if (this.testEnvironmentArg) { + extend(this.testEnvironment, this.testEnvironmentArg); } - QUnit.test(testName, expected, callback, true); - }, - - test: function(testName, expected, callback, async) { - var name = '<span class="test-name">' + testName + '</span>', testEnvironment, testEnvironmentArg; + QUnit.testStart( { + name: this.testName + } ); - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - // is 2nd argument a testEnvironment? - if ( expected && typeof expected === 'object') { - testEnvironmentArg = expected; - expected = null; - } + // allow utility functions to access the current test environment + // TODO why?? + QUnit.current_testEnvironment = this.testEnvironment; + + try { + if ( !config.pollution ) { + saveGlobal(); + } - if ( config.currentModule ) { - name = '<span class="module-name">' + config.currentModule + "</span>: " + name; + this.testEnvironment.setup.call(this.testEnvironment); + } catch(e) { + QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message ); + } + }, + run: function() { + if ( this.async ) { + QUnit.stop(); } - if ( !validTest(config.currentModule + ": " + testName) ) { + if ( config.notrycatch ) { + this.callback.call(this.testEnvironment); return; } + try { + this.callback.call(this.testEnvironment); + } catch(e) { + fail("Test " + this.testName + " died, exception and test follows", e, this.callback); + QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + start(); + } + } + }, + teardown: function() { + try { + checkPollution(); + this.testEnvironment.teardown.call(this.testEnvironment); + } catch(e) { + QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); + } + }, + finish: function() { + 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"); - synchronize(function() { + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; - testEnvironment = extend({ - setup: function() {}, - teardown: function() {} - }, config.moduleTestEnvironment); - if (testEnvironmentArg) { - extend(testEnvironment,testEnvironmentArg); - } + if ( tests ) { + var ol = document.createElement("ol"); - QUnit.testStart( testName, testEnvironment ); + for ( var i = 0; i < this.assertions.length; i++ ) { + var assertion = this.assertions[i]; - // allow utility functions to access the current test environment - QUnit.current_testEnvironment = testEnvironment; - - config.assertions = []; - config.expected = expected; - - var tests = id("qunit-tests"); - if (tests) { - var b = document.createElement("strong"); - b.innerHTML = "Running " + name; var li = document.createElement("li"); - li.appendChild( b ); - li.id = "current-test-output"; - tests.appendChild( li ) + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } } - try { - if ( !config.pollution ) { - saveGlobal(); - } + // store result when possible + defined.sessionStorage && sessionStorage.setItem("qunit-" + this.testName, bad); - testEnvironment.setup.call(testEnvironment); - } catch(e) { - QUnit.ok( false, "Setup failed on " + name + ": " + e.message ); - } - }); - - synchronize(function() { - if ( async ) { - QUnit.stop(); + if (bad == 0) { + ol.style.display = "none"; } - try { - callback.call(testEnvironment); - } catch(e) { - fail("Test " + name + " died, exception and test follows", e, callback); - QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message ); - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - start(); + 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>"; + + addEvent(b, "click", function() { + var next = b.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" ) { + target = target.parentNode; } - } - }); + if ( window.location && target.nodeName.toLowerCase() === "strong" ) { + window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, "")); + } + }); - synchronize(function() { - try { - checkPollution(); - testEnvironment.teardown.call(testEnvironment); - } catch(e) { - QUnit.ok( false, "Teardown failed on " + name + ": " + e.message ); - } - }); - - synchronize(function() { - try { - QUnit.reset(); - } catch(e) { - fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset); - } + var li = id(this.id); + li.className = bad ? "fail" : "pass"; + li.style.display = resultDisplayStyle(!bad); + li.removeChild( li.firstChild ); + li.appendChild( b ); + li.appendChild( ol ); - if ( config.expected && config.expected != config.assertions.length ) { - QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" ); + } else { + for ( var i = 0; i < this.assertions.length; i++ ) { + if ( !this.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } } + } - var good = 0, bad = 0, - tests = id("qunit-tests"); - - config.stats.all += config.assertions.length; - config.moduleStats.all += config.assertions.length; - - if ( tests ) { - var ol = document.createElement("ol"); - - for ( var i = 0; i < config.assertions.length; i++ ) { - var assertion = config.assertions[i]; + try { + QUnit.reset(); + } catch(e) { + fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset); + } - var li = document.createElement("li"); - li.className = assertion.result ? "pass" : "fail"; - li.innerHTML = assertion.message || "(no message)"; - ol.appendChild( li ); + QUnit.testDone( { + name: this.testName, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length + } ); + }, + + queue: function() { + var test = this; + synchronize(function() { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function() { + test.setup(); + }); + synchronize(function() { + test.run(); + }); + synchronize(function() { + test.teardown(); + }); + synchronize(function() { + test.finish(); + }); + } + // defer when previous test run passed, if storage is available + var bad = defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.testName); + if (bad) { + run(); + } else { + synchronize(run); + }; + } + +} - if ( assertion.result ) { - good++; - } else { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - if (bad == 0) { - ol.style.display = "none"; - } +var QUnit = { - var b = document.createElement("strong"); - b.innerHTML = name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + config.assertions.length + ")</b>"; - - addEvent(b, "click", function() { - var next = b.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" ) { - target = target.parentNode; - } - if ( window.location && target.nodeName.toLowerCase() === "strong" ) { - window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, "")); - } - }); + // call on start of module test to prepend name to all tests + module: function(name, testEnvironment) { + config.currentModule = name; + config.currentModuleTestEnviroment = testEnvironment; + }, - var li = id("current-test-output"); - li.id = ""; - li.className = bad ? "fail" : "pass"; - li.removeChild( li.firstChild ); - li.appendChild( b ); - li.appendChild( ol ); - - if ( bad ) { - var toolbar = id("qunit-testrunner-toolbar"); - if ( toolbar ) { - toolbar.style.display = "block"; - id("qunit-filter-pass").disabled = null; - id("qunit-filter-missing").disabled = null; - } - } + asyncTest: function(testName, expected, callback) { + if ( arguments.length === 2 ) { + callback = expected; + expected = 0; + } - } else { - for ( var i = 0; i < config.assertions.length; i++ ) { - if ( !config.assertions[i].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - } + QUnit.test(testName, expected, callback, true); + }, + + test: function(testName, expected, callback, async) { + var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg; - QUnit.testDone( testName, bad, config.assertions.length ); + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + // is 2nd argument a testEnvironment? + if ( expected && typeof expected === 'object') { + testEnvironmentArg = expected; + expected = null; + } - if ( !window.setTimeout && !config.queue.length ) { - done(); - } - }); + if ( config.currentModule ) { + name = '<span class="module-name">' + config.currentModule + "</span>: " + name; + } - synchronize( done ); + 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. */ expect: function(asserts) { - config.expected = asserts; + config.current.expected = asserts; }, /** @@ -233,11 +293,15 @@ var QUnit = { * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); */ ok: function(a, msg) { + a = !!a; + var details = { + result: a, + message: msg + }; msg = escapeHtml(msg); - QUnit.log(a, msg); - - config.assertions.push({ - result: !!a, + QUnit.log(details); + config.current.assertions.push({ + result: a, message: msg }); }, @@ -255,42 +319,74 @@ var QUnit = { * @param String message (optional) */ equal: function(actual, expected, message) { - push(expected == actual, actual, expected, message); + QUnit.push(expected == actual, actual, expected, message); }, notEqual: function(actual, expected, message) { - push(expected != actual, actual, expected, message); + QUnit.push(expected != actual, actual, expected, message); }, deepEqual: function(actual, expected, message) { - push(QUnit.equiv(actual, expected), actual, expected, message); + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); }, notDeepEqual: function(actual, expected, message) { - push(!QUnit.equiv(actual, expected), actual, expected, message); + QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); }, strictEqual: function(actual, expected, message) { - push(expected === actual, actual, expected, message); + QUnit.push(expected === actual, actual, expected, message); }, notStrictEqual: function(actual, expected, message) { - push(expected !== actual, actual, expected, message); + QUnit.push(expected !== actual, actual, expected, message); }, - raises: function(fn, message) { + raises: function(block, expected, message) { + var actual, ok = false; + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + try { - fn(); - ok( false, message ); + block(); + } catch (e) { + actual = e; } - catch (e) { - ok( true, message ); + + if (actual) { + // we don't want to validate thrown error + if (!expected) { + ok = true; + // expected is a regexp + } else if (QUnit.objectType(expected) === "regexp") { + ok = expected.test(actual); + // expected is a constructor + } else if (actual instanceof expected) { + ok = true; + // expected is a validation function which returns true is validation passed + } else if (expected.call({}, actual) === true) { + ok = true; + } } + + QUnit.ok(ok, message); }, start: function() { + config.semaphore--; + if (config.semaphore > 0) { + // don't start until equal number of stop-calls + return; + } + if (config.semaphore < 0) { + // ignore if start is called more often then stop + config.semaphore = 0; + } // A slight delay, to avoid any current callbacks - if ( window.setTimeout ) { + if ( defined.setTimeout ) { window.setTimeout(function() { if ( config.timeout ) { clearTimeout(config.timeout); @@ -306,9 +402,11 @@ var QUnit = { }, stop: function(timeout) { + config.semaphore++; config.blocking = true; - if ( timeout && window.setTimeout ) { + if ( timeout && defined.setTimeout ) { + clearTimeout(config.timeout); config.timeout = window.setTimeout(function() { QUnit.ok( false, "Test timed out" ); QUnit.start(); @@ -342,6 +440,10 @@ var config = { GETParams.splice( i, 1 ); i--; config.noglobals = true; + } else if ( GETParams[i] === "notrycatch" ) { + GETParams.splice( i, 1 ); + i--; + config.notrycatch = true; } else if ( GETParams[i].search('=') > -1 ) { GETParams.splice( i, 1 ); i--; @@ -379,9 +481,9 @@ extend(QUnit, { blocking: false, autostart: true, autorun: false, - assertions: [], filters: [], - queue: [] + queue: [], + semaphore: 0 }); var tests = id("qunit-tests"), @@ -403,10 +505,17 @@ extend(QUnit, { /** * Resets the test setup. Useful for tests that modify the DOM. + * + * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. */ reset: function() { if ( window.jQuery ) { - jQuery("#main, #qunit-fixture").html( config.fixture ); + jQuery( "#main, #qunit-fixture" ).html( config.fixture ); + } else { + var main = id( 'main' ) || id( 'qunit-fixture' ); + if ( main ) { + main.innerHTML = config.fixture; + } } }, @@ -469,14 +578,55 @@ extend(QUnit, { return undefined; }, - // Logging callbacks + push: function(result, actual, expected, message) { + var details = { + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeHtml(message) || (result ? "okay" : "failed"); + message = '<span class="test-message">' + message + "</span>"; + expected = escapeHtml(QUnit.jsDump.parse(expected)); + actual = escapeHtml(QUnit.jsDump.parse(actual)); + var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>'; + if (actual != expected) { + output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>'; + output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>'; + } + if (!result) { + var source = sourceFromStacktrace(); + if (source) { + details.source = source; + output += '<tr class="test-source"><th>Source: </th><td><pre>' + source +'</pre></td></tr>'; + } + } + output += "</table>"; + + QUnit.log(details); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + // Logging callbacks; all receive a single argument with the listed properties + // run test/logs.html for any related changes begin: function() {}, - done: function(failures, total) {}, - log: function(result, message) {}, - testStart: function(name, testEnvironment) {}, - testDone: function(name, failures, total) {}, - moduleStart: function(name, testEnvironment) {}, - moduleDone: function(name, failures, total) {} + // done: { failed, passed, total, runtime } + done: function() {}, + // log: { result, actual, expected, message } + log: function() {}, + // testStart: { name } + testStart: function() {}, + // testDone: { name, failed, passed, total } + testDone: function() {}, + // moduleStart: { name } + moduleStart: function() {}, + // moduleDone: { name, failed, passed, total } + moduleDone: function() {} }); if ( typeof document === "undefined" || document.readyState === "complete" ) { @@ -484,7 +634,7 @@ if ( typeof document === "undefined" || document.readyState === "complete" ) { } addEvent(window, "load", function() { - QUnit.begin(); + QUnit.begin({}); // Initialize the config, saving the execution queue var oldconfig = extend({}, config); @@ -499,17 +649,23 @@ addEvent(window, "load", function() { } var banner = id("qunit-header"); if ( banner ) { - banner.innerHTML = '<a href="' + location.href + '">' + banner.innerHTML + '</a>'; + var paramsIndex = location.href.lastIndexOf(location.search); + if ( paramsIndex > -1 ) { + var mainPageLocation = location.href.slice(0, paramsIndex); + if ( mainPageLocation == location.href ) { + banner.innerHTML = '<a href=""> ' + banner.innerHTML + '</a> '; + } else { + var testName = decodeURIComponent(location.search.slice(1)); + banner.innerHTML = '<a href="' + mainPageLocation + '">' + banner.innerHTML + '</a> › <a href="">' + testName + '</a>'; + } + } } var toolbar = id("qunit-testrunner-toolbar"); if ( toolbar ) { - toolbar.style.display = "none"; - var filter = document.createElement("input"); filter.type = "checkbox"; filter.id = "qunit-filter-pass"; - filter.disabled = true; addEvent( filter, "click", function() { var li = document.getElementsByTagName("li"); for ( var i = 0; i < li.length; i++ ) { @@ -517,32 +673,19 @@ addEvent(window, "load", function() { li[i].style.display = filter.checked ? "none" : ""; } } + if ( defined.sessionStorage ) { + sessionStorage.setItem("qunit-filter-passed-tests", filter.checked ? "true" : ""); + } }); + if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { + filter.checked = true; + } toolbar.appendChild( filter ); var label = document.createElement("label"); label.setAttribute("for", "qunit-filter-pass"); label.innerHTML = "Hide passed tests"; toolbar.appendChild( label ); - - var missing = document.createElement("input"); - missing.type = "checkbox"; - missing.id = "qunit-filter-missing"; - missing.disabled = true; - addEvent( missing, "click", function() { - var li = document.getElementsByTagName("li"); - for ( var i = 0; i < li.length; i++ ) { - if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) { - li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block"; - } - } - }); - toolbar.appendChild( missing ); - - label = document.createElement("label"); - label.setAttribute("for", "qunit-filter-missing"); - label.innerHTML = "Hide missing tests (untested code is broken code)"; - toolbar.appendChild( label ); } var main = id('main') || id('qunit-fixture'); @@ -556,35 +699,34 @@ addEvent(window, "load", function() { }); function done() { - if ( config.doneTimer && window.clearTimeout ) { - window.clearTimeout( config.doneTimer ); - config.doneTimer = null; - } - - if ( config.queue.length ) { - config.doneTimer = window.setTimeout(function(){ - if ( !config.queue.length ) { - done(); - } else { - synchronize( done ); - } - }, 13); - - return; - } - config.autorun = true; // Log the last module results if ( config.currentModule ) { - QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); + QUnit.moduleDone( { + name: config.currentModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + } ); } var banner = id("qunit-banner"), tests = id("qunit-tests"), - html = ['Tests completed in ', - +new Date - config.started, ' milliseconds.<br/>', - '<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join(''); + runtime = +new Date - config.started, + passed = config.stats.all - config.stats.bad, + html = [ + 'Tests completed in ', + runtime, + ' milliseconds.<br/>', + '<span class="passed">', + passed, + '</span> tests of <span class="total">', + config.stats.all, + '</span> passed, <span class="failed">', + config.stats.bad, + '</span> failed.' + ].join(''); if ( banner ) { banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); @@ -603,7 +745,12 @@ function done() { result.innerHTML = html; } - QUnit.done( config.stats.bad, config.stats.all ); + QUnit.done( { + failed: config.stats.bad, + passed: passed, + total: config.stats.all, + runtime: runtime + } ); } function validTest( name ) { @@ -634,8 +781,31 @@ function validTest( name ) { return run; } +// so far supports only Firefox, Chrome and Opera (buggy) +// could be extended in the future to use something like https://github.com/csnover/TraceKit +function sourceFromStacktrace() { + try { + throw new Error(); + } catch ( e ) { + if (e.stacktrace) { + // Opera + return e.stacktrace.split("\n")[6]; + } else if (e.stack) { + // Firefox, Chrome + return e.stack.split("\n")[4]; + } + } +} + +function resultDisplayStyle(passed) { + return passed && id("qunit-filter-pass") && id("qunit-filter-pass").checked ? 'none' : ''; +} + function escapeHtml(s) { - s = s === null ? "" : s + ""; + if (!s) { + return ""; + } + s = s + ""; return s.replace(/[\&"<>\\]/g, function(s) { switch(s) { case "&": return "&"; @@ -648,24 +818,6 @@ function escapeHtml(s) { }); } -function push(result, actual, expected, message) { - message = escapeHtml(message) || (result ? "okay" : "failed"); - message = '<span class="test-message">' + message + "</span>"; - expected = escapeHtml(QUnit.jsDump.parse(expected)); - actual = escapeHtml(QUnit.jsDump.parse(actual)); - var output = message + ', expected: <span class="test-expected">' + expected + '</span>'; - if (actual != expected) { - output += ' result: <span class="test-actual">' + actual + '</span>, diff: ' + QUnit.diff(expected, actual); - } - - // can't use ok, as that would double-escape messages - QUnit.log(result, output); - config.assertions.push({ - result: !!result, - message: output - }); -} - function synchronize( callback ) { config.queue.push( callback ); @@ -680,12 +832,14 @@ function process() { while ( config.queue.length && !config.blocking ) { if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) { config.queue.shift()(); - } else { - setTimeout( process, 13 ); + window.setTimeout( process, 13 ); break; } } + if (!config.blocking && !config.queue.length) { + done(); + } } function saveGlobal() { @@ -705,13 +859,13 @@ function checkPollution( name ) { var newGlobals = diff( old, config.pollution ); if ( newGlobals.length > 0 ) { ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); - config.expected++; + config.current.expected++; } var deletedGlobals = diff( config.pollution, old ); if ( deletedGlobals.length > 0 ) { ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); - config.expected++; + config.current.expected++; } } @@ -988,7 +1142,7 @@ QUnit.jsDump = (function() { type = "date"; } else if (QUnit.is("Function", obj)) { type = "function"; - } else if (obj.setInterval && obj.document && !obj.nodeType) { + } else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") { type = "window"; } else if (obj.nodeType === 9) { type = "document"; @@ -1042,31 +1196,31 @@ QUnit.jsDump = (function() { ret += ' ' + name; ret += '('; - ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join(''); - return join( ret, this.parse(fn,'functionCode'), '}' ); + ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); + return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); }, array: array, nodelist: array, arguments: array, object:function( map ) { var ret = [ ]; - this.up(); + QUnit.jsDump.up(); for ( var key in map ) - ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) ); - this.down(); + ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); + QUnit.jsDump.down(); return join( '{', ret, '}' ); }, node:function( node ) { - var open = this.HTML ? '<' : '<', - close = this.HTML ? '>' : '>'; + var open = QUnit.jsDump.HTML ? '<' : '<', + close = QUnit.jsDump.HTML ? '>' : '>'; var tag = node.nodeName.toLowerCase(), ret = open + tag; - for ( var a in this.DOMAttrs ) { - var val = node[this.DOMAttrs[a]]; + for ( var a in QUnit.jsDump.DOMAttrs ) { + var val = node[QUnit.jsDump.DOMAttrs[a]]; if ( val ) - ret += ' ' + a + '=' + this.parse( val, 'attribute' ); + ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); } return ret + close + open + '/' + tag + close; }, @@ -1094,8 +1248,8 @@ QUnit.jsDump = (function() { 'class':'className' }, HTML:false,//if true, entities are escaped ( <, >, \t, space and \n ) - indentChar:' ',//indentation unit - multiline:false //if true, items in a collection, are separated by a \n, else just a space. + indentChar:' ',//indentation unit + multiline:true //if true, items in a collection, are separated by a \n, else just a space. }; return jsDump; @@ -1255,7 +1409,7 @@ QUnit.diff = (function() { } return str; - } + }; })(); -})(this); +})(this);
\ No newline at end of file diff --git a/tests/unit/accordion/accordio.html b/tests/unit/accordion/accordio.html new file mode 100644 index 000000000..db202fe43 --- /dev/null +++ b/tests/unit/accordion/accordio.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>jQuery UI Accordion Test Suite</title> + + <link rel="stylesheet" href="../../../themes/base/jquery.ui.accordion.css"> + + <script src="../../../jquery-1.4.4.js"></script> + <script src="../../../ui/jquery.ui.core.js"></script> + <script src="../../../ui/jquery.ui.widget.js"></script> + <script src="../../../ui/jquery.ui.accordion.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> + function state( accordion ) { + var expected = $.makeArray( arguments ).slice( 1 ); + var actual = accordion.find( ".ui-accordion-content" ).map(function() { + return $( this ).css( "display" ) === "none" ? 0 : 1; + }).get(); + same( actual, expected ); + } + function 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 ] ); + } + function accordionSetupTeardown() { + var animated = $.ui.accordion.prototype.options.animated; + return { + setup: function() { + $.ui.accordion.prototype.options.animated = false; + }, + teardown: function() { + $.ui.accordion.prototype.options.animated = animated; + } + }; + } + </script> + <script src="accordion_defaults_deprecated.js"></script> + <script src="accordion_core.js"></script> + <script src="accordion_events.js"></script> + <script src="accordion_methods.js"></script> + <script src="accordion_options.js"></script> + <script src="accordion_tickets.js"></script> + <script src="accordion_deprecated.js"></script> + + <script src="../swarminject.js"></script> + <style> + #main { font-size: 10pt; font-family: "trebuchet ms", verdana, arial; } + #list, #list1 *, #navigation, #navigation * { margin: 0; padding: 0; font-size: 12px; } + </style> +</head> +<body> + +<h1 id="qunit-header">jQuery UI Accordion Test Suite</h1> +<h2 id="qunit-banner"></h2> +<h2 id="qunit-userAgent"></h2> +<ol id="qunit-tests"> +</ol> + +<div id="main" style="position: absolute; top: -10000px; left: -10000px;"> + + <div> + <div id="list1" class="foo"> + <h3 class="bar"><a class="anchor">There is one obvious advantage:</a></h3> + <div class="foo"> + <p> + You've seen it coming! + <br/> + Buy now and get nothing for free! + <br/> + Well, at least no free beer. Perhaps a bear, if you can afford it. + </p> + </div> + <h3 class="bar"><a class="anchor">Now that you've got...</a></h3> + <div class="foo"> + <p> + your bear, you have to admit it! + <br/> + No, we aren't selling bears. + </p> + <p> + We could talk about renting one. + </p> + </div> + <h3 class="bar"><a class="anchor">Rent one bear, ...</a></h3> + <div class="foo"> + <p> + get two for three beer. + </p> + <p> + And now, for something completely different. + </p> + </div> + </div> + </div> + +<div id="navigationWrapper"> + <ul id="navigation"> + <li> + <h2><a href="?p=1.1.1">Guitar</a></h2> + <ul> + <li><a href="?p=1.1.1.1">Electric</a></li> + <li><a href="?p=1.1.1.2">Acoustic</a></li> + <li><a href="?p=1.1.1.3">Amps</a></li> + <li><a href="?p=1.1.1.4">Effects</a></li> + <li><a href="?p=1.1.1.5">Accessories</a></li> + </ul> + </li> + <li> + <h2><a href="?p=1.1.2"><span>Bass</span></a></h2> + <ul> + <li><a href="?p=1.1.2.1">Electric</a></li> + <li><a href="?p=1.1.2.2">Acoustic</a></li> + <li><a href="?p=1.1.2.3">Amps</a></li> + <li><a href="?p=1.1.2.4">Effects</a></li> + <li><a href="?p=1.1.2.5">Accessories</a></li> + <li><a href="?p=1.1.2.5">Accessories</a></li> + <li><a href="?p=1.1.2.5">Accessories</a></li> + </ul> + </li> + <li> + <h2><a href="?p=1.1.3">Drums</a></h2> + <ul> + <li><a href="?p=1.1.3.2">Acoustic Drums</a></li> + <li><a href="?p=1.1.3.3">Electronic Drums</a></li> + <li><a href="?p=1.1.3.6">Accessories</a></li> + </ul> + </li> + </ul> +</div> + +</div> + +</body> +</html> diff --git a/tests/unit/accordion/accordion.html b/tests/unit/accordion/accordion.html index 61d168386..23380000e 100644 --- a/tests/unit/accordion/accordion.html +++ b/tests/unit/accordion/accordion.html @@ -1,55 +1,65 @@ <!DOCTYPE html> <html lang="en"> <head> - <meta charset="UTF-8" /> + <meta charset="utf-8"> <title>jQuery UI Accordion Test Suite</title> - <link type="text/css" href="../../../themes/base/jquery.ui.accordion.css" rel="stylesheet" /> + <link rel="stylesheet" href="../../../themes/base/jquery.ui.accordion.css"> - <script type="text/javascript" src="../../../jquery-1.4.4.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.accordion.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 src="../../../jquery-1.4.4.js"></script> + <script> + $.uiBackCompat = false; + </script> + <script src="../../../ui/jquery.ui.core.js"></script> + <script src="../../../ui/jquery.ui.widget.js"></script> + <script src="../../../ui/jquery.ui.accordion.js"></script> - <script type="text/javascript"> - $.ui.accordion.prototype.options.animated = false; + <link rel="stylesheet" href="../../../external/qunit.css"> + <script src="../../../external/qunit.js"></script> + <script src="../../jquery.simulate.js"></script> + <script src="../testsuite.js"></script> - function state(accordion) { - var args = $.makeArray(arguments).slice(1); - var result = []; - $.each(args, function(i, n) { - result.push( accordion.find(".ui-accordion-content").eq(i).filter(function() { - return $(this).css("display") != "none" - }).length ? 1 : 0 ); - }); - same(args, result) - } - function 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]); - } + <script> + function state( accordion ) { + var expected = $.makeArray( arguments ).slice( 1 ); + var actual = accordion.find( ".ui-accordion-content" ).map(function() { + return $( this ).css( "display" ) === "none" ? 0 : 1; + }).get(); + same( actual, expected ); + } + function 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 ] ); + } + function accordionSetupTeardown() { + var animated = $.ui.accordion.prototype.options.animated; + return { + setup: function() { + $.ui.accordion.prototype.options.animated = false; + }, + teardown: function() { + $.ui.accordion.prototype.options.animated = animated; + } + }; + } </script> - <script type="text/javascript" src="accordion_core.js"></script> - <script type="text/javascript" src="accordion_defaults.js"></script> - <script type="text/javascript" src="accordion_events.js"></script> - <script type="text/javascript" src="accordion_methods.js"></script> - <script type="text/javascript" src="accordion_options.js"></script> - <script type="text/javascript" src="accordion_tickets.js"></script> - - <script type="text/javascript" src="../swarminject.js"></script> + <script src="accordion_defaults.js"></script> + <script src="accordion_core.js"></script> + <script src="accordion_events.js"></script> + <script src="accordion_methods.js"></script> + <script src="accordion_options.js"></script> + <script src="accordion_tickets.js"></script> + + <script src="../swarminject.js"></script> <style> - #main { font-size: 10pt; font-family: 'trebuchet ms', verdana, arial; } - #list, #list1 *, #navigation, #navigation * { margin: 0; padding: 0; font-size: 12px; } + #main { font-size: 10pt; font-family: "trebuchet ms", verdana, arial; } + #list, #list1 *, #navigation, #navigation * { margin: 0; padding: 0; font-size: 12px; } </style> </head> <body> diff --git a/tests/unit/accordion/accordion_core.js b/tests/unit/accordion/accordion_core.js index 40a711abf..24dc0146b 100644 --- a/tests/unit/accordion/accordion_core.js +++ b/tests/unit/accordion/accordion_core.js @@ -1,40 +1,47 @@ -/* - * accordion_core.js - */ - - -(function($) { - -module("accordion: core"); - -test("handle click on header-descendant", function() { - var ac = $('#navigation').accordion({ autoHeight: false }); - $('#navigation h2:eq(1) a').trigger("click"); - state(ac, 0, 1, 0); +(function( $ ) { + +module( "accordion: core", accordionSetupTeardown() ); + +test( "markup structure", function() { + var ac = $( "#navigation" ).accordion(); + ok( ac.hasClass( "ui-accordion" ), "main element is .ui-accordion" ); + equal( ac.find( ".ui-accordion-header" ).length, 3, + ".ui-accordion-header elements exist, correct number" ); + equal( ac.find( ".ui-accordion-content" ).length, 3, + ".ui-accordion-content elements exist, correct number" ); + same( ac.find( ".ui-accordion-header" ).next().get(), + ac.find( ".ui-accordion-content" ).get(), + "content panels come immediately after headers" ); }); -test("ui-accordion-heading class added to headers anchor", function() { - expect(1); - var ac = $("#list1").accordion(); - var anchors = $(".ui-accordion-heading"); - equals( anchors.length, "3"); +test( "handle click on header-descendant", function() { + var ac = $( "#navigation" ).accordion(); + $( "#navigation h2:eq(1) a" ).click(); + state( ac, 0, 1, 0 ); }); -test("accessibility", function () { - expect(9); - var ac = $('#list1').accordion().accordion("option", "active", 1); - var headers = $(".ui-accordion-header"); +test( "ui-accordion-heading class added to headers anchor", function() { + expect( 1 ); + var ac = $( "#list1" ).accordion(); + var anchors = $( ".ui-accordion-heading" ); + equals( anchors.length, 3 ); +}); - 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( ac.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"); - ac.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"); +test( "accessibility", function () { + expect( 9 ); + var ac = $( "#list1" ).accordion().accordion( "option", "active", 1 ); + var headers = $( ".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( ac.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" ); + ac.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" ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/accordion/accordion_defaults.js b/tests/unit/accordion/accordion_defaults.js index d29c1e848..95a478057 100644 --- a/tests/unit/accordion/accordion_defaults.js +++ b/tests/unit/accordion/accordion_defaults.js @@ -1,23 +1,15 @@ -/* - * accordion_defaults.js - */ - -var accordion_defaults = { - active: 0, - animated: false, - autoHeight: true, - clearStyle: false, - collapsible: false, - disabled: false, - event: "click", - fillSpace: false, - header: "> li > :first-child,> :not(li):even", - heightStyle: null, - icons: { "header": "ui-icon-triangle-1-e", - "activeHeader": null, - "headerSelected": "ui-icon-triangle-1-s" }, - navigation: false, - navigationFilter: function() {} -}; - -commonWidgetTests('accordion', { defaults: accordion_defaults }); +commonWidgetTests( "accordion", { + defaults: { + active: 0, + animated: "slide", + collapsible: false, + disabled: false, + event: "click", + header: "> li > :first-child,> :not(li):even", + heightStyle: "auto", + icons: { + "activeHeader": "ui-icon-triangle-1-s", + "header": "ui-icon-triangle-1-e" + } + } +}); diff --git a/tests/unit/accordion/accordion_defaults_deprecated.js b/tests/unit/accordion/accordion_defaults_deprecated.js new file mode 100644 index 000000000..b90b472e2 --- /dev/null +++ b/tests/unit/accordion/accordion_defaults_deprecated.js @@ -0,0 +1,21 @@ +commonWidgetTests( "accordion", { + defaults: { + active: 0, + animated: "slide", + autoHeight: true, + clearStyle: false, + collapsible: false, + disabled: false, + event: "click", + fillSpace: false, + header: "> li > :first-child,> :not(li):even", + heightStyle: null, + icons: { + "activeHeader": null, + "header": "ui-icon-triangle-1-e", + "headerSelected": "ui-icon-triangle-1-s" + }, + navigation: false, + navigationFilter: function() {} + } +}); diff --git a/tests/unit/accordion/accordion_deprecated.js b/tests/unit/accordion/accordion_deprecated.js new file mode 100644 index 000000000..07974e75e --- /dev/null +++ b/tests/unit/accordion/accordion_deprecated.js @@ -0,0 +1,320 @@ +(function( $ ) { + +module( "accordion (deprecated): expanded active option, activate method", accordionSetupTeardown() ); + +test( "activate, numeric", function() { + var ac = $( "#list1" ).accordion({ active: 1 }); + state( ac, 0, 1, 0 ); + ac.accordion( "activate", 2 ); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", 0 ); + state( ac, 1, 0, 0 ); + ac.accordion( "activate", 1 ); + state( ac, 0, 1, 0 ); + ac.accordion( "activate", 2 ); + state( ac, 0, 0, 1 ); +}); + +test( "activate, numeric, collapsible:true", function() { + var ac = $( "#list1" ).accordion({ collapsible: true }); + ac.accordion( "activate", 2 ); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", 0 ); + state( ac, 1, 0, 0 ); + ac.accordion( "activate", -1 ); + state( ac, 0, 0, 0 ); +}); + +test( "activate, boolean, collapsible: true", function() { + var ac = $( "#list1" ).accordion({ collapsible: true }); + ac.accordion( "activate", 2 ); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", false ); + state( ac, 0, 0, 0 ); +}); + +test( "activate, boolean, collapsible: false", function() { + var ac = $( "#list1" ).accordion(); + ac.accordion( "activate", 2 ); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", false ); + state( ac, 0, 0, 1 ); +}); + +test( "activate, string expression", function() { + var ac = $( "#list1" ).accordion({ active: "h3:last" }); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", ":first" ); + state( ac, 1, 0, 0 ); + ac.accordion( "activate", ":eq(1)" ); + state( ac, 0, 1, 0 ); + ac.accordion( "activate", ":last" ); + state( ac, 0, 0, 1 ); +}); + +test( "activate, jQuery or DOM element", function() { + var ac = $( "#list1" ).accordion({ active: $( "#list1 h3:last" ) }); + state( ac, 0, 0, 1 ); + ac.accordion( "activate", $( "#list1 h3:first" ) ); + state( ac, 1, 0, 0 ); + ac.accordion( "activate", $( "#list1 h3" )[ 1 ] ); + state( ac, 0, 1, 0 ); +}); + +test( "{ active: Selector }", function() { + var ac = $("#list1").accordion({ + active: "h3:last" + }); + state( ac, 0, 0, 1 ); + ac.accordion( "option", "active", "h3:eq(1)" ); + state( ac, 0, 1, 0 ); +}); + +test( "{ active: Element }", function() { + var ac = $( "#list1" ).accordion({ + active: $( "#list1 h3:last" )[ 0 ] + }); + state( ac, 0, 0, 1 ); + ac.accordion( "option", "active", $( "#list1 h3:eq(1)" )[ 0 ] ); + state( ac, 0, 1, 0 ); +}); + +test( "{ active: jQuery Object }", function() { + var ac = $( "#list1" ).accordion({ + active: $( "#list1 h3:last" ) + }); + state( ac, 0, 0, 1 ); + ac.accordion( "option", "active", $( "#list1 h3:eq(1)" ) ); + state( ac, 0, 1, 0 ); +}); + + + + + +module( "accordion (deprecated) - height options", accordionSetupTeardown() ); + +test( "{ autoHeight: true }, default", function() { + equalHeights($('#navigation').accordion({ autoHeight: true }), 95, 130); +}); + +test("{ autoHeight: false }", function() { + var accordion = $('#navigation').accordion({ autoHeight: false }); + var sizes = []; + accordion.find(".ui-accordion-content").each(function() { + sizes.push($(this).height()); + }); + ok( sizes[0] >= 70 && sizes[0] <= 90, "was " + sizes[0] ); + ok( sizes[1] >= 98 && sizes[1] <= 126, "was " + sizes[1] ); + ok( sizes[2] >= 42 && sizes[2] <= 54, "was " + sizes[2] ); +}); + +test( "{ fillSpace: true }", function() { + $( "#navigationWrapper" ).height( 500 ); + var ac = $( "#navigation" ).accordion({ fillSpace: true }); + equalHeights( ac, 446, 458 ); +}); + +test( "{ fillSapce: true } with sibling", function() { + $( "#navigationWrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#navigationWrapper" ); + var ac = $( "#navigation" ).accordion({ fillSpace: true }); + equalHeights( ac , 346, 358); +}); + +test( "{ fillSpace: true } with multiple siblings", function() { + $( "#navigationWrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#navigationWrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30, + position: "absolute" + }) + .prependTo( "#navigationWrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 25, + marginTop: 10, + marginBottom: 15 + }) + .prependTo( "#navigationWrapper" ); + var ac = $( "#navigation" ).accordion({ fillSpace: true }); + equalHeights( ac, 296, 308 ); +}); + + + + + +module( "accordion (deprecated) - icons", accordionSetupTeardown() ); + +test( "icons, headerSelected", function() { + var list = $( "#list1" ).accordion({ + icons: { headerSelected: "a1", header: "h1" } + }); + ok( list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a1" ) ); + list.accordion( "option", "icons", { headerSelected: "a2", header: "h2" } ); + ok( !list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a1" ) ); + ok( list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a2" ) ); +}); + + + + + +module( "accordion (deprecated) - resize", accordionSetupTeardown() ); + +test( "resize", function() { + var expected = $( "#navigation" ) + .parent() + .height( 300 ) + .end() + .accordion({ + heightStyle: "fill" + }); + equalHeights( expected, 246, 258 ); + + expected.parent().height( 500 ); + expected.accordion( "resize" ); + equalHeights( expected, 446, 458 ); +}); + + + + + +module( "accordion (deprecated) - navigation", accordionSetupTeardown() ); + +test( "{ navigation: true, navigationFilter: header }", function() { + var ac = $( "#navigation" ).accordion({ + navigation: true, + navigationFilter: function() { + return /\?p=1\.1\.3$/.test( this.href ); + } + }); + equal( ac.accordion( "option", "active" ), 2 ); + state( ac, 0, 0, 1 ); +}); + +test( "{ navigation: true, navigationFilter: content }", function() { + var ac = $("#navigation").accordion({ + navigation: true, + navigationFilter: function() { + return /\?p=1\.1\.3\.2$/.test(this.href); + } + }); + equal( ac.accordion( "option", "active" ), 2 ); + state( ac, 0, 0, 1 ); +}); + + + + + +module( "accordion (deprecated) - changestart/change events", accordionSetupTeardown() ); + +test( "changestart", function() { + expect( 26 ); + var ac = $( "#list1" ).accordion({ + active: false, + collapsible: true + }); + var headers = ac.find( ".ui-accordion-header" ); + var content = ac.find( ".ui-accordion-content" ); + + ac.one( "accordionchangestart", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + state( ac, 0, 0, 0 ); + }); + ac.accordion( "option", "active", 0 ); + state( ac, 1, 0, 0 ); + + ac.one( "accordionchangestart", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + state( ac, 1, 0, 0 ); + }); + headers.eq( 1 ).click(); + state( ac, 0, 1, 0 ); + + ac.one( "accordionchangestart", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); + equals( ui.newHeader.size(), 0 ); + equals( ui.newContent.size(), 0 ); + state( ac, 0, 1, 0 ); + }); + ac.accordion( "option", "active", false ); + state( ac, 0, 0, 0 ); +}); + +test( "change", function() { + expect( 20 ); + var ac = $( "#list1" ).accordion({ + active: false, + collapsible: true + }); + var headers = ac.find( ".ui-accordion-header" ); + var content = ac.find( ".ui-accordion-content" ); + + ac.one( "accordionchange", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + }); + ac.accordion( "option", "active", 0 ); + + ac.one( "accordionchange", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + }); + headers.eq( 1 ).click(); + + ac.one( "accordionchange", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); + equals( ui.newHeader.size(), 0 ); + equals( ui.newContent.size(), 0 ); + }); + ac.accordion( "option", "active", false ); +}); + +})(jQuery); diff --git a/tests/unit/accordion/accordion_events.js b/tests/unit/accordion/accordion_events.js index 4798f7404..0b9f14706 100644 --- a/tests/unit/accordion/accordion_events.js +++ b/tests/unit/accordion/accordion_events.js @@ -1,30 +1,121 @@ -/* - * accordion_events.js - */ -(function($) { +(function( $ ) { -module("accordion: events"); +module( "accordion: events", accordionSetupTeardown() ); -test("accordionchange event, open closed and close again", function() { - expect(8); - $("#list1").accordion({ +test( "beforeActivate", function() { + expect( 42 ); + var ac = $( "#list1" ).accordion({ active: false, collapsible: true - }) - .one("accordionchange", function(event, ui) { + }); + var headers = ac.find( ".ui-accordion-header" ); + var content = ac.find( ".ui-accordion-content" ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + state( ac, 0, 0, 0 ); + }); + ac.accordion( "option", "active", 0 ); + state( ac, 1, 0, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + state( ac, 1, 0, 0 ); + }); + headers.eq( 1 ).click(); + state( ac, 0, 1, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); + equals( ui.newHeader.size(), 0 ); + equals( ui.newContent.size(), 0 ); + state( ac, 0, 1, 0 ); + }); + ac.accordion( "option", "active", false ); + state( ac, 0, 0, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + event.preventDefault(); + state( ac, 0, 0, 0 ); + }); + ac.accordion( "option", "active", 1 ); + state( ac, 0, 0, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 2 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 2 ] ); + event.preventDefault(); + state( ac, 0, 0, 0 ); + }); + headers.eq( 2 ).click(); + state( ac, 0, 0, 0 ); +}); + +test( "activate", function() { + expect( 20 ); + var ac = $( "#list1" ).accordion({ + active: false, + collapsible: true + }); + var headers = ac.find( ".ui-accordion-header" ); + var content = ac.find( ".ui-accordion-content" ); + + ac.one( "accordionactivate", function( event, ui ) { equals( ui.oldHeader.size(), 0 ); equals( ui.oldContent.size(), 0 ); equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); equals( ui.newContent.size(), 1 ); - }) - .accordion("option", "active", 0) - .one("accordionchange", function(event, ui) { + strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + }); + ac.accordion( "option", "active", 0 ); + + ac.one( "accordionactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); + equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + }); + headers.eq( 1 ).click(); + + ac.one( "accordionactivate", function( event, ui ) { equals( ui.oldHeader.size(), 1 ); + strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); equals( ui.oldContent.size(), 1 ); + strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); equals( ui.newHeader.size(), 0 ); equals( ui.newContent.size(), 0 ); - }) - .accordion("option", "active", false); + }); + ac.accordion( "option", "active", false ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/accordion/accordion_methods.js b/tests/unit/accordion/accordion_methods.js index c801851d0..e0ed734f6 100644 --- a/tests/unit/accordion/accordion_methods.js +++ b/tests/unit/accordion/accordion_methods.js @@ -1,128 +1,48 @@ -/* - * accordion_methods.js - */ -(function($) { - -module("accordion: methods"); - -test("init", function() { - $("<div></div>").appendTo('body').accordion().remove(); - ok(true, '.accordion() called on element'); - - $([]).accordion().remove(); - ok(true, '.accordion() called on empty collection'); - - $('<div></div>').accordion().remove(); - ok(true, '.accordion() called on disconnected DOMElement - never connected'); - - $('<div></div>').appendTo('body').remove().accordion().remove(); - ok(true, '.accordion() called on disconnected DOMElement - removed'); - - var el = $('<div></div>').accordion(); - var foo = el.accordion("option", "foo"); - el.remove(); - ok(true, 'arbitrary option getter after init'); - - $('<div></div>').accordion().accordion("option", "foo", "bar").remove(); - ok(true, 'arbitrary option setter after init'); -}); - -test("destroy", function() { - var beforeHtml = $("#list1").find("div").css("font-style", "normal").end().parent().html(); - var afterHtml = $("#list1").accordion().accordion("destroy").parent().html(); - // Opera 9 outputs role="" instead of removing the attribute like everyone else - if ($.browser.opera) { - afterHtml = afterHtml.replace(/ role=""/g, ""); - } +(function( $ ) { + +module( "accordion: methods", accordionSetupTeardown() ); + +test( "destroy", function() { + var beforeHtml = $( "#list1" ) + .find( "div" ) + .css( "font-style", "normal" ) + .end() + .parent() + .html(); + var afterHtml = $( "#list1" ) + .accordion() + .accordion( "destroy" ) + .parent() + .html() + // Opera 9 outputs role="" instead of removing the attribute like everyone else + .replace( / role=""/g, "" ); equal( afterHtml, beforeHtml ); }); -test("enable", function() { - var expected = $('#list1').accordion(), - actual = expected.accordion('enable'); - equals(actual, expected, 'enable is chainable'); - state(expected, 1, 0, 0) -}); - -test("disable", function() { - var expected = $('#list1').accordion(), - actual = expected.accordion('disable'); - equals(actual, expected, 'disable is chainable'); - - state(expected, 1, 0, 0) - expected.accordion("option", "active", 1); - state(expected, 1, 0, 0) - expected.accordion("enable"); - expected.accordion("option", "active", 1); - state(expected, 0, 1, 0) +test( "enable/disable", function() { + var accordion = $('#list1').accordion(); + state( accordion, 1, 0, 0 ); + accordion.accordion( "disable" ); + accordion.accordion( "option", "active", 1 ); + state( accordion, 1, 0, 0 ); + accordion.accordion( "enable" ); + accordion.accordion( "option", "active", 1 ); + state( accordion, 0, 1, 0 ); }); -test("activate", function() { - var expected = $('#list1').accordion(), - actual = expected.accordion('activate', 2); - equals(actual, expected, 'activate is chainable'); -}); - -test("activate, numeric", function() { - var ac = $('#list1').accordion({ active: 1 }); - state(ac, 0, 1, 0); - ac.accordion("activate", 2); - state(ac, 0, 0, 1); - ac.accordion("activate", 0); - state(ac, 1, 0, 0); - ac.accordion("activate", 1); - state(ac, 0, 1, 0); - ac.accordion("activate", 2); - state(ac, 0, 0, 1); -}); - -test("activate, boolean and numeric, collapsible:true", function() { - var ac = $('#list1').accordion({collapsible: true}).accordion("activate", 2); - state(ac, 0, 0, 1); - ok("x", "----"); - ac.accordion("activate", 0); - state(ac, 1, 0, 0); - ok("x", "----"); - ac.accordion("activate", -1); - state(ac, 0, 0, 0); -}); - -test("activate, boolean, collapsible: false", function() { - var ac = $('#list1').accordion().accordion("activate", 2); - state(ac, 0, 0, 1); - ac.accordion("activate", false); - state(ac, 0, 0, 1); -}); - -test("activate, string expression", function() { - var ac = $('#list1').accordion({ active: "h3:last" }); - state(ac, 0, 0, 1); - ac.accordion("activate", ":first"); - state(ac, 1, 0, 0); - ac.accordion("activate", ":eq(1)"); - state(ac, 0, 1, 0); - ac.accordion("activate", ":last"); - state(ac, 0, 0, 1); -}); - -test("activate, jQuery or DOM element", function() { - var ac = $('#list1').accordion({ active: $("#list1 h3:last") }); - state(ac, 0, 0, 1); - ac.accordion("activate", $("#list1 h3:first")); - state(ac, 1, 0, 0); - ac.accordion("activate", $("#list1 h3")[1]); - state(ac, 0, 1, 0); -}); +test( "refresh", function() { + var expected = $( "#navigation" ) + .parent() + .height( 300 ) + .end() + .accordion({ + heightStyle: "fill" + }); + equalHeights( expected, 246, 258 ); -test("refresh", function() { - var expected = $('#navigation').parent().height(300).end().accordion({ - fillSpace: true - }); - equalHeights(expected, 246, 258); - - expected.parent().height(500); - expected.accordion("refresh"); - equalHeights(expected, 446, 458); + expected.parent().height( 500 ); + expected.accordion( "refresh" ); + equalHeights( expected, 446, 458 ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/accordion/accordion_options.js b/tests/unit/accordion/accordion_options.js index abfb82d78..8fcfdb172 100644 --- a/tests/unit/accordion/accordion_options.js +++ b/tests/unit/accordion/accordion_options.js @@ -1,203 +1,212 @@ -/* - * accordion_options.js - */ -(function($) { +(function( $ ) { -module("accordion: options"); +module( "accordion: options", accordionSetupTeardown() ); -test("{ active: first child }, default", function() { - var ac = $("#list1").accordion(); - equals( ac.accordion('option', 'active'), 0); - state(ac, 1, 0, 0) +test( "{ active: default }", function() { + var ac = $( "#list1" ).accordion(); + equals( ac.accordion( "option", "active" ), 0 ); + state( ac, 1, 0, 0 ); }); -test("{ active: Selector }", function() { - var ac = $("#list1").accordion({ - active: "h3:last" - }); - state(ac, 0, 0, 1); - ac.accordion('option', 'active', "h3:eq(1)"); - state(ac, 0, 1, 0); -}); - -test("{ active: Element }", function() { - var ac = $("#list1").accordion({ - active: $("#list1 h3:last")[0] - }); - state(ac, 0, 0, 1); - ac.accordion('option', 'active', $("#list1 h3:eq(1)")[0]); - state(ac, 0, 1, 0); -}); - -test("{ active: jQuery Object }", function() { - var ac = $("#list1").accordion({ - active: $("#list1 h3:last") - }); - state(ac, 0, 0, 1); - ac.accordion('option', 'active', $("#list1 h3:eq(1)")); - state(ac, 0, 1, 0); -}); - -test("{ active: false }", function() { - var ac = $("#list1").accordion({ +test( "{ active: false }", function() { + var ac = $( "#list1" ).accordion({ active: false, collapsible: true }); - state(ac, 0, 0, 0); - equals( $("#list1 .ui-accordion-header.ui-state-active").size(), 0, "no headers selected" ); - equals( $("#list1").accordion('option', 'active'), false); -}); - -test("{ active: Number }", function() { - expect(4); - $("#list1").accordion({ - active: 0 + state( ac, 0, 0, 0 ); + equals( ac.find( ".ui-accordion-header.ui-state-active" ).size(), 0, "no headers selected" ); + equals( ac.accordion( "option", "active" ), false ); + + // TODO: fix active: false when not collapsible +// ac.accordion( "option", "collapsible", false ); +// state( ac, 1, 0, 0 ); +// equals( ac.accordion( "option", "active" ), 0 ); +// +// ac.accordion( "destroy" ); +// ac.accordion({ +// active: false +// }); +// state( ac, 1, 0, 0 ); +// strictEqual( ac.accordion( "option", "active" ), 0 ); +}); + +test( "{ active: Number }", function() { + var ac = $( "#list1" ).accordion({ + active: 2 }); - equals( $("#list1").accordion('option', 'active'), 0); - - $("#list1").accordion('option', 'active', 1); - equals( $("#list1").accordion('option', 'active'), 1); - - $('.ui-accordion-header:eq(2)', '#list1').click(); - equals( $("#list1").accordion('option', 'active'), 2); - - $("#list1").accordion('option', 'active', 0); - equals( $("#list1").accordion('option', 'active'), 0); -}); + equals( ac.accordion( "option", "active" ), 2 ); + state( ac, 0, 0, 1 ); + + ac.accordion( "option", "active", 0 ); + equals( ac.accordion( "option", "active" ), 0 ); + state( ac, 1, 0, 0 ); + + ac.find( ".ui-accordion-header" ).eq( 1 ).click(); + equals( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); + + ac.accordion( "option", "active", 10 ); + equals( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); +}); + +if ( $.uiBackCompat === false ) { + test( "{ active: -Number }", function() { + // TODO: fix initializing with negative value + var ac = $( "#list1" ).accordion({ +// active: -1 + }); +// equals( ac.accordion( "option", "active" ), 2 ); +// state( ac, 0, 0, 1 ); + + ac.accordion( "option", "active", -2 ); + equals( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); + + ac.accordion( "option", "active", -10 ); + equals( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); + + ac.accordion( "option", "active", -3 ); + equals( ac.accordion( "option", "active" ), 0 ); + state( ac, 1, 0, 0 ); + }); +} -test("{ autoHeight: true }, default", function() { - equalHeights($('#navigation').accordion({ autoHeight: true }), 95, 130); -}); +// TODO: add animation tests -test("{ heightStyle: 'auto' }, default", function() { - equalHeights($('#navigation').accordion({ heightStyle: 'auto' }), 95, 130); -}); - -test("{ autoHeight: false }", function() { - var accordion = $('#navigation').accordion({ autoHeight: false }); - var sizes = []; - accordion.find(".ui-accordion-content").each(function() { - sizes.push($(this).height()); +test( "{ collapsible: false }", function() { + var ac = $( "#list1" ).accordion({ + active: 1 }); - ok( sizes[0] >= 70 && sizes[0] <= 90, "was " + sizes[0] ); - ok( sizes[1] >= 98 && sizes[1] <= 126, "was " + sizes[1] ); - ok( sizes[2] >= 42 && sizes[2] <= 54, "was " + sizes[2] ); -}); + ac.accordion( "option", "active", false ); + equal( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); -test("{ heightStyle: 'content' }", function() { - var accordion = $('#navigation').accordion({ heightStyle: 'content' }); - var sizes = []; - accordion.find(".ui-accordion-content").each(function() { - sizes.push($(this).height()); - }); - ok( sizes[0] >= 70 && sizes[0] <= 90, "was " + sizes[0] ); - ok( sizes[1] >= 98 && sizes[1] <= 126, "was " + sizes[1] ); - ok( sizes[2] >= 42 && sizes[2] <= 54, "was " + sizes[2] ); -}); -test("{ collapsible: false }, default", function() { - var ac = $("#list1").accordion(); - ac.accordion("option", "active", false); - state(ac, 1, 0, 0); + ac.find( ".ui-accordion-header" ).eq( 1 ).click(); + equal( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); }); -test("{ collapsible: true }", function() { - var ac = $("#list1").accordion({ +test( "{ collapsible: true }", function() { + var ac = $( "#list1" ).accordion({ active: 1, collapsible: true }); - var header = $('#list1 .ui-accordion-header:eq(1)').click(); - equals( $("#list1").accordion('option', 'active'), false); - state(ac, 0, 0, 0); -}); - -// fillSpace: false == autoHeight: true, covered above -test("{ fillSpace: true }", function() { - $("#navigationWrapper").height(500); - equalHeights($('#navigation').accordion({ fillSpace: true }), 446, 458); -}); - -test("{ heightStyle: 'fill' }", function() { - $("#navigationWrapper").height(500); - equalHeights($('#navigation').accordion({ heightStyle: 'fill' }), 446, 458); -}); - -test("{ fillSpace: true } with sibling", function() { - $("#navigationWrapper").height(500); - var sibling = $("<p>Lorem Ipsum</p>"); - $("#navigationWrapper").prepend( sibling.height(100) ); - //sibling.outerHeight(true) == 126 - equalHeights($('#navigation').accordion({ fillSpace: true}), 320, 332); -}); - -test("{ fillSpace: true } with multiple siblings", function() { - $("#navigationWrapper").height(500); - var sibling = $("<p>Lorem Ipsum</p>"); - $("#navigationWrapper") - .prepend( sibling.clone().height(100) ) - .prepend( sibling.clone().height(100).css( "position", "absolute" ) ) - .prepend( sibling.clone().height(50) ); - //sibling.outerHeight(true) == 126 - equalHeights($('#navigation').accordion({ fillSpace: true}), 244, 256); -}); - -test("{ header: '> li > :first-child,> :not(li):even' }, default", function() { - state($("#list1").accordion(), 1, 0, 0); - state($("#navigation").accordion(), 1, 0, 0); -}); -test("{ icons: false }", function() { - var list = $("#list1"); - function icons(on) { - same($("span.ui-icon", list).length, on ? 3 : 0); - same( list.hasClass("ui-accordion-icons"), on ); + // TODO: fix setting active to false +// ac.accordion( "option", "active", false ); +// equal( ac.accordion( "option", "active" ), false ); +// state( ac, 0, 0, 0 ); + + ac.accordion( "option", "active", 1 ); + equal( ac.accordion( "option", "active" ), 1 ); + state( ac, 0, 1, 0 ); + + ac.find( ".ui-accordion-header" ).eq( 1 ).click(); + equals( ac.accordion( "option", "active" ), false ); + state( ac, 0, 0, 0 ); +}); + +// TODO: add event tests + +// TODO: add more header tests +test( "{ header: default }", function() { + // default: > li > :first-child,> :not(li):even + // > :not(li):even + state( $( "#list1" ).accordion(), 1, 0, 0); + // > li > :first-child + state( $( "#navigation" ).accordion(), 1, 0, 0); +}); + +test( "{ heightStyle: 'auto' }", function() { + var ac = $( "#navigation" ).accordion({ heightStyle: "auto" }); + equalHeights( ac, 95, 130 ); +}); + +test( "{ heightStyle: 'content' }", function() { + var ac = $( "#navigation" ).accordion({ heightStyle: "content" }); + var sizes = ac.find( ".ui-accordion-content" ).map(function() { + return $( this ).height(); + }).get(); + ok( sizes[ 0 ] >= 70 && sizes[ 0 ] <= 90, "was " + sizes[ 0 ] ); + ok( sizes[ 1 ] >= 98 && sizes[ 1 ] <= 126, "was " + sizes[ 1 ] ); + ok( sizes[ 2 ] >= 42 && sizes[ 2 ] <= 54, "was " + sizes[ 2 ] ); +}); + +test( "{ heightStyle: 'fill' }", function() { + $( "#navigationWrapper" ).height( 500 ); + var ac = $( "#navigation" ).accordion({ heightStyle: "fill" }); + equalHeights( ac, 446, 458 ); +}); + +test( "{ heightStyle: 'fill' } with sibling", function() { + $( "#navigationWrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#navigationWrapper" ); + var ac = $( "#navigation" ).accordion({ heightStyle: "fill" }); + equalHeights( ac , 346, 358); +}); + +test( "{ heightStyle: 'fill' } with multiple siblings", function() { + $( "#navigationWrapper" ).height( 500 ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30 + }) + .prependTo( "#navigationWrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 50, + marginTop: 20, + marginBottom: 30, + position: "absolute" + }) + .prependTo( "#navigationWrapper" ); + $( "<p>Lorem Ipsum</p>" ) + .css({ + height: 25, + marginTop: 10, + marginBottom: 15 + }) + .prependTo( "#navigationWrapper" ); + var ac = $( "#navigation" ).accordion({ heightStyle: "fill" }); + equalHeights( ac, 296, 308 ); +}); + +test( "{ icons: false }", function() { + var list = $( "#list1" ); + function icons( on ) { + same( list.find( "span.ui-icon").length, on ? 3 : 0 ); + same( list.hasClass( "ui-accordion-icons" ), on ); } list.accordion(); - icons(true); - list.accordion("destroy").accordion({ + icons( true ); + list.accordion( "destroy" ).accordion({ icons: false }); - icons(false); - list.accordion("option", "icons", $.ui.accordion.prototype.options.icons); - icons(true); - list.accordion("option", "icons", false); - icons(false); -}); - -test("{ icons: { activeHeader : 'test' } }", function() { - var list = $("#list1"); - list.accordion( { icons: { "activeHeader": "test" } } ); - equals( $( "#list1 span.test" ).length, 1); - list.accordion("option", "icons", { "activeHeader": "news" } ); - equals( $( "#list1 span.test" ).length, 0); - equals( $( "#list1 span.news" ).length, 1); -}); - -test("{ navigation: true, navigationFilter: header }", function() { - $("#navigation").accordion({ - navigation: true, - navigationFilter: function() { - return /\?p=1\.1\.3$/.test(this.href); - } - }); - equals( $("#navigation .ui-accordion-content:eq(2)").size(), 1, "third content active" ); + icons( false ); + list.accordion( "option", "icons", { header: "foo", activeHeader: "bar" } ); + icons( true ); + list.accordion( "option", "icons", false ); + icons( false ); }); -test("{ navigation: true, navigationFilter: content }", function() { - $("#navigation").accordion({ - navigation: true, - navigationFilter: function() { - return /\?p=1\.1\.3\.2$/.test(this.href); - } +test( "{ icons: hash }", function() { + var list = $( "#list1" ).accordion({ + icons: { activeHeader: "a1", header: "h1" } }); - equals( $("#navigation .ui-accordion-content:eq(2)").size(), 1, "third content active" ); -}); - -test("change headerSelected option after creation", function() { - var list = $("#list1"); - list.accordion( { icons: { "activeHeader": "test" } } ); - equals( $( "#list1 span.test" ).length, 1); - list.accordion( "option", "icons", { "headerSelected": "deprecated" } ); - equals( $( "#list1 span.deprecated" ).length, 1); + ok( list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a1" ) ); + list.accordion( "option", "icons", { activeHeader: "a2", header: "h2" } ); + ok( !list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a1" ) ); + ok( list.find( ".ui-accordion-header.ui-state-active span.ui-icon" ).hasClass( "a2" ) ); }); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/accordion/accordion_tickets.js b/tests/unit/accordion/accordion_tickets.js index 98d8fbe4c..b301051da 100644 --- a/tests/unit/accordion/accordion_tickets.js +++ b/tests/unit/accordion/accordion_tickets.js @@ -1,8 +1,5 @@ -/* - * accordion_tickets.js - */ -(function($) { +(function( $ ) { -module("accordion: tickets"); +module( "accordion: tickets", accordionSetupTeardown() ); -})(jQuery); +}( jQuery ) ); diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index d152f84cd..9724a946f 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -1,39 +1,69 @@ -function testWidgetDefaults(widget, defaults) { - var pluginDefaults = $.extend({}, - $.ui[widget].prototype.options - ); - +(function() { + +function testWidgetDefaults( widget, defaults ) { + var pluginDefaults = $.ui[ widget ].prototype.options; + // ensure that all defaults have the correct value - test('defined defaults', function() { - $.each(defaults, function(key, val) { - if ($.isFunction(val)) { - ok(val !== undefined, key); + test( "defined defaults", function() { + $.each( defaults, function( key, val ) { + if ( $.isFunction( val ) ) { + ok( $.isFunction( pluginDefaults[ key ] ), key ); return; } - same(pluginDefaults[key], val, key); + same( pluginDefaults[ key ], val, key ); }); }); - + // ensure that all defaults were tested - test('tested defaults', function() { - $.each(pluginDefaults, function(key, val) { - ok(key in defaults, key); + test( "tested defaults", function() { + $.each( pluginDefaults, function( key, val ) { + ok( key in defaults, key ); }); }); } -function testWidgetOverrides(widget) { - test('$.widget overrides', function() { - $.each(['_widgetInit', 'option', '_trigger'], function(i, method) { - ok($.Widget.prototype[method] == $.ui[widget].prototype[method], - 'should not override ' + method); +var privateMethods = [ + "_createWidget", + "_super", + "_superApply", + "destroy", + "option", + "enable", + "disable", + "_trigger" +]; + +function testWidgetOverrides( widget ) { + if ( $.uiBackCompat === false ) { + test( "$.widget overrides", function() { + $.each( privateMethods, function( i, method ) { + strictEqual( $.ui[ widget ].prototype[ method ], + $.Widget.prototype[ method ], "should not override " + method ); + }); }); - }); + } } -function commonWidgetTests(widget, settings) { - module(widget + ": common widget"); +function testBasicUsage( widget ) { + test( "basic usage", function() { + var defaultElement = $.ui[ widget ].prototype.defaultElement; + $( defaultElement ).appendTo( "body" )[ widget ]().remove(); + ok( true, "initialized on element" ); - testWidgetDefaults(widget, settings.defaults); - testWidgetOverrides(widget); + $( defaultElement )[ widget ]().remove(); + ok( true, "initialized on disconnected DOMElement - never connected" ); + + $( defaultElement ).appendTo( "body" ).remove()[ widget ]().remove(); + ok( true, "initialized on disconnected DOMElement - removed" ); + }); } + +window.commonWidgetTests = function( widget, settings ) { + module( widget + ": common widget" ); + + testWidgetDefaults( widget, settings.defaults ); + testWidgetOverrides( widget ); + testBasicUsage( widget ); +}; + +}()); diff --git a/tests/unit/widget/widget.html b/tests/unit/widget/widget.html index c6fa54e41..d8fa2ecaf 100644 --- a/tests/unit/widget/widget.html +++ b/tests/unit/widget/widget.html @@ -1,22 +1,22 @@ <!DOCTYPE html> <html lang="en"> <head> - <meta charset="UTF-8" /> + <meta charset="utf-8"> <title>jQuery UI Widget Test Suite</title> - <script type="text/javascript" src="../../../jquery-1.4.4.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 src="../../../jquery-1.4.4.js"></script> + <script src="../../../ui/jquery.ui.core.js"></script> + <script src="../../../ui/jquery.ui.widget.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> + <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 type="text/javascript" src="widget_core.js"></script> - <script type="text/javascript" src="widget_tickets.js"></script> - - <script type="text/javascript" src="../swarminject.js"></script> + <script src="widget_core.js"></script> + <script src="widget_tickets.js"></script> + + <script src="../swarminject.js"></script> </head> <body> diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index d993194e2..6f4930621 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -1,6 +1,3 @@ -/* - * widget unit tests - */ (function( $ ) { module( "widget factory", { @@ -26,6 +23,54 @@ test( "widget creation", function() { "option method copied over from base widget" ); }); +test( "element normalization", function() { + expect( 11 ); + var elem; + $.widget( "ui.testWidget", {} ); + + $.ui.testWidget.prototype._create = function() { + ok( this.element.is( "div" ), "generated div" ); + same( this.element.data( "testWidget" ), this, "intance stored in .data()" ); + }; + $.ui.testWidget(); + + $.ui.testWidget.prototype.defaultElement = "<span data-test='pass'>"; + $.ui.testWidget.prototype._create = function() { + ok( this.element.is( "span[data-test=pass]" ), "generated span with properties" ); + same( this.element.data( "testWidget" ), this, "instace stored in .data()" ); + }; + $.ui.testWidget(); + + elem = $( "<input>" ); + $.ui.testWidget.prototype._create = function() { + same( this.element[ 0 ], elem[ 0 ], "from element" ); + same( elem.data( "testWidget" ), this, "instace stored in .data()" ); + }; + $.ui.testWidget( {}, elem[ 0 ] ); + + elem = $( "<div>" ); + $.ui.testWidget.prototype._create = function() { + same( this.element[ 0 ], elem[ 0 ], "from jQuery object" ); + same( elem.data( "testWidget" ), this, "instace stored in .data()" ); + }; + $.ui.testWidget( {}, elem ); + + elem = $( "<div id='element-normalization-selector'></div>" ) + .appendTo( "#main" ); + $.ui.testWidget.prototype._create = function() { + same( this.element[ 0 ], elem[ 0 ], "from selector" ); + same( elem.data( "testWidget" ), this, "instace stored in .data()" ); + }; + $.ui.testWidget( {}, "#element-normalization-selector" ); + + $.ui.testWidget.prototype.defaultElement = null; + $.ui.testWidget.prototype._create = function() { + // using strictEqual throws an error (Maximum call stack size exceeded) + ok( this.element[ 0 ] === this, "instance as element" ); + }; + $.ui.testWidget(); +}); + test( "jQuery usage", function() { expect( 11 ); @@ -55,7 +100,7 @@ test( "jQuery usage", function() { }); shouldCreate = true; - var elem = $( "<div></div>" ) + var elem = $( "<div>" ) .bind( "testwidgetcreate", function() { ok( shouldCreate, "create event triggered on instantiation" ); }) @@ -101,7 +146,7 @@ test( "direct usage", function() { } }); - var elem = $( "<div></div>" )[ 0 ]; + var elem = $( "<div>" )[ 0 ]; shouldCreate = true; var instance = new $.ui.testWidget( {}, elem ); @@ -153,7 +198,7 @@ test( "merge multiple option arguments", function() { }); } }); - $( "<div></div>" ).testWidget({ + $( "<div>" ).testWidget({ option1: "valuex", option2: "valuex", option3: "value3", @@ -200,7 +245,7 @@ test( "._getCreateOptions()", function() { }); test( "re-init", function() { - var div = $( "<div></div>" ), + var div = $( "<div>" ), actions = []; $.widget( "ui.testWidget", { @@ -286,7 +331,7 @@ test( ".option() - getter", function() { _create: function() {} }); - var div = $( "<div></div>" ).testWidget({ + var div = $( "<div>" ).testWidget({ foo: "bar", baz: 5, qux: [ "quux", "quuux" ] @@ -317,7 +362,7 @@ test( ".option() - delegate to ._setOptions()", function() { calls.push( options ); } }); - var div = $( "<div></div>" ).testWidget(); + var div = $( "<div>" ).testWidget(); calls = []; div.testWidget( "option", "foo", "bar" ); @@ -343,7 +388,7 @@ test( ".option() - delegate to ._setOption()", function() { }); } }); - var div = $( "<div></div>" ).testWidget(); + var div = $( "<div>" ).testWidget(); calls = []; div.testWidget( "option", "foo", "bar" ); @@ -370,7 +415,7 @@ test( ".enable()", function() { same( val, false, "disabled set to false" ); } }); - $( "<div></div>" ).testWidget().testWidget( "enable" ); + $( "<div>" ).testWidget().testWidget( "enable" ); }); test( ".disable()", function() { @@ -382,26 +427,26 @@ test( ".disable()", function() { same( val, true, "disabled set to true" ); } }); - $( "<div></div>" ).testWidget().testWidget( "disable" ); + $( "<div>" ).testWidget().testWidget( "disable" ); }); test( ".widget() - base", function() { $.widget( "ui.testWidget", { _create: function() {} }); - var div = $( "<div></div>" ).testWidget(); + var div = $( "<div>" ).testWidget(); same( div[0], div.testWidget( "widget" )[0]); }); test( ".widget() - overriden", function() { - var wrapper = $( "<div></div>" ); + var wrapper = $( "<div>" ); $.widget( "ui.testWidget", { _create: function() {}, widget: function() { return wrapper; } }); - same( wrapper[0], $( "<div></div>" ).testWidget().testWidget( "widget" )[0] ); + same( wrapper[0], $( "<div>" ).testWidget().testWidget( "widget" )[0] ); }); test( "._bind() to element (default)", function() { @@ -691,6 +736,28 @@ test( "._trigger() - provide event and ui", function() { .testWidget( "testEvent" ); }); +test( "._triger() - instance as element", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + defaultElement: null, + testEvent: function() { + var ui = { foo: "bar" }; + this._trigger( "foo", null, ui ); + } + }); + var instance = $.ui.testWidget({ + foo: function( event, ui ) { + equal( event.type, "testwidgetfoo", "event object passed to callback" ); + same( ui, { foo: "bar" }, "ui object passed to callback" ); + } + }); + $( instance ).bind( "testwidgetfoo", function( event, ui ) { + equal( event.type, "testwidgetfoo", "event object passed to event handler" ); + same( ui, { foo: "bar" }, "ui object passed to event handler" ); + }); + instance.testEvent(); +}); + test( "auto-destroy - .remove()", function() { expect( 1 ); $.widget( "ui.testWidget", { @@ -721,8 +788,6 @@ test( "auto-destroy - .remove() on child", function() { } }); $( "#widget" ).testWidget().children().remove(); - // http://github.com/jquery/qunit/pull/34 - $.ui.testWidget.prototype.destroy = $.noop; }); test( "auto-destroy - .empty()", function() { @@ -733,8 +798,6 @@ test( "auto-destroy - .empty()", function() { } }); $( "#widget" ).testWidget().empty(); - // http://github.com/jquery/qunit/pull/34 - $.ui.testWidget.prototype.destroy = $.noop; }); test( "auto-destroy - .empty() on parent", function() { @@ -758,4 +821,4 @@ test( "auto-destroy - .detach()", function() { $( "#widget" ).testWidget().detach(); }); -})( jQuery ); +}( jQuery ) ); diff --git a/tests/unit/widget/widget_tickets.js b/tests/unit/widget/widget_tickets.js index 21f44b54c..0267c8ff4 100644 --- a/tests/unit/widget/widget_tickets.js +++ b/tests/unit/widget/widget_tickets.js @@ -1,6 +1,3 @@ -/* - * widget unit tests - */ (function( $ ) { module( "widget: tickets" ); @@ -43,4 +40,4 @@ test( "#5830 - Widget: Using inheritance overwrites the base classes options", f delete $.ui.testWidgetExtension; }); -})( jQuery ); +}( jQuery ) ); diff --git a/themes/base/jquery.ui.accordion.css b/themes/base/jquery.ui.accordion.css index 80a80c82c..a260cf9ef 100644 --- a/themes/base/jquery.ui.accordion.css +++ b/themes/base/jquery.ui.accordion.css @@ -10,7 +10,6 @@ /* IE/Win - Fix animation bug - #4615 */ .ui-accordion { width: 100%; } .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } .ui-accordion .ui-accordion-heading { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } .ui-accordion-icons .ui-accordion-heading { padding-left: 2.2em; } diff --git a/ui/i18n/jquery.ui.datepicker-ar-DZ.js b/ui/i18n/jquery.ui.datepicker-ar-DZ.js new file mode 100644 index 000000000..e0e1685d8 --- /dev/null +++ b/ui/i18n/jquery.ui.datepicker-ar-DZ.js @@ -0,0 +1,23 @@ +/* Algerian Arabic Translation for jQuery UI date picker plugin. (can be used for Tunisia)*/ +/* Mohamed Cherif BOUCHELAGHEM -- cherifbouchelaghem@yahoo.fr */ + +jQuery(function($){ + $.datepicker.regional['ar-DZ'] = { + closeText: 'إغلاق', + prevText: '<السابق', + nextText: 'التالي>', + currentText: 'اليوم', + monthNames: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', + 'جويلية', 'أوت', 'سبتمبر','أكتوبر', 'نوفمبر', 'ديسمبر'], + monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], + dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], + dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], + dayNamesMin: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], + weekHeader: 'أسبوع', + dateFormat: 'dd/mm/yy', + firstDay: 6, + isRTL: true, + showMonthAfterYear: false, + yearSuffix: ''}; + $.datepicker.setDefaults($.datepicker.regional['ar-DZ']); +}); diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 954ee91bd..6c257c8c0 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -20,12 +20,10 @@ $.widget( "ui.accordion", { collapsible: false, event: "click", header: "> li > :first-child,> :not(li):even", - // TODO: set to "auto" in 2.0 (#5868, #5872) - heightStyle: null, // "auto" + heightStyle: "auto", icons: { - header: "ui-icon-triangle-1-e", - // TODO: set to "ui-icon-triangle-1-s" in 2.0 (#6835) - activeHeader: null // "ui-icon-triangle-1-s" + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" } }, @@ -35,12 +33,7 @@ $.widget( "ui.accordion", { self.running = 0; - self.element - .addClass( "ui-accordion ui-widget ui-helper-reset" ) - // in lack of child-selectors in CSS - // we need to mark top-LIs in a UL-accordion for some IE-fix - .children( "li" ) - .addClass( "ui-accordion-li-fix" ); + self.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); self.headers = self.element.find( options.header ) .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); @@ -265,6 +258,17 @@ $.widget( "ui.accordion", { return; } + // allow the activation to be canceled + var eventData = { + oldHeader: this.active, + oldContent: this.active.next(), + newHeader: $(), + newContent: $() + }; + if ( this._trigger( "beforeActivate", null, eventData ) === false ) { + return; + } + this.active .removeClass( "ui-state-active ui-corner-top" ) .addClass( "ui-state-default ui-corner-all" ) @@ -275,24 +279,34 @@ $.widget( "ui.accordion", { var toHide = this.active.next(), data = { options: this.options, - newHeader: $( [] ), + newHeader: $(), oldHeader: this.active, - newContent: $( [] ), + newContent: $(), oldContent: toHide }, - toShow = ( this.active = $( [] ) ); + toShow = ( this.active = $() ); this._toggle( toShow, toHide, data ); }, // TODO: add tests/docs for negative values in 2.0 (#6854) _findActive: function( selector ) { - return typeof selector === "number" ? this.headers.eq( selector ) : $( [] ); + return typeof selector === "number" ? this.headers.eq( selector ) : $(); }, _eventHandler: function( event ) { var options = this.options, + active = this.active, clicked = $( event.currentTarget ), - clickedIsActive = clicked[0] === this.active[0]; + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldContent: toHide, + newHeader: collapsing ? $() : clicked, + newContent: collapsing ? $() : toShow + }; event.preventDefault(); @@ -305,26 +319,26 @@ $.widget( "ui.accordion", { return; } - options.active = options.collapsible && clickedIsActive ? - false : - this.headers.index( clicked ); + // allow the activation to be canceled + if ( this._trigger( "beforeActivate", null, eventData ) === false ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); // find elements to show and hide - var active = this.active, - toShow = clicked.next(), - toHide = this.active.next(), - data = { + var data = { options: options, - newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, - oldHeader: this.active, - newContent: clickedIsActive && options.collapsible ? $([]) : toShow, + newHeader: collapsing ? $() : clicked, + oldHeader: active, + newContent: collapsing ? $() : toShow, oldContent: toHide }, - down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + down = this.headers.index( active[0] ) > this.headers.index( clicked[0] ); // when the call to ._toggle() comes after the class changes // it causes a very odd bug in IE 8 (see #6720) - this.active = clickedIsActive ? $([]) : clicked; + this.active = clickedIsActive ? $() : clicked; this._toggle( toShow, toHide, data, clickedIsActive, down ); // switch classes @@ -362,9 +376,6 @@ $.widget( "ui.accordion", { return self._completed.apply( self, arguments ); }; - // trigger changestart event - self._trigger( "changestart", null, self.data ); - // count elements to animate self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); @@ -373,7 +384,7 @@ $.widget( "ui.accordion", { if ( options.collapsible && clickedIsActive ) { animOptions = { - toShow: $( [] ), + toShow: $(), toHide: toHide, complete: complete, down: down, @@ -468,7 +479,7 @@ $.widget( "ui.accordion", { this.toHide.parent()[0].className = this.toHide.parent()[0].className; } - this._trigger( "change", null, this.data ); + this._trigger( "activate", null, this.data ); } }); @@ -578,115 +589,138 @@ $.extend( $.ui.accordion, { // DEPRECATED - -// navigation options -(function( $, prototype ) { - $.extend( prototype.options, { - navigation: false, - navigationFilter: function() { - return this.href.toLowerCase() === location.href.toLowerCase(); - } - }); - - var _create = prototype._create; - prototype._create = function() { - if ( this.options.navigation ) { - var self = this, - headers = this.element.find( this.options.header ), - content = headers.next(); - current = headers.add( content ) - .find( "a" ) - .filter( this.options.navigationFilter ) - [ 0 ]; - if ( current ) { - headers.add( content ).each( function( index ) { - if ( $.contains( this, current ) ) { - self.options.active = Math.floor( index / 2 ); - return false; - } - }); +if ( $.uiBackCompat !== false ) { + // navigation options + (function( $, prototype ) { + $.extend( prototype.options, { + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() === location.href.toLowerCase(); + } + }); + + var _create = prototype._create; + prototype._create = function() { + if ( this.options.navigation ) { + var self = this, + headers = this.element.find( this.options.header ), + content = headers.next(); + current = headers.add( content ) + .find( "a" ) + .filter( this.options.navigationFilter ) + [ 0 ]; + if ( current ) { + headers.add( content ).each( function( index ) { + if ( $.contains( this, current ) ) { + self.options.active = Math.floor( index / 2 ); + return false; + } + }); + } } - } - _create.call( this ); - }; -}( jQuery, jQuery.ui.accordion.prototype ) ); - -// height options -(function( $, prototype ) { - $.extend( prototype.options, { - autoHeight: true, // use heightStyle: "auto" - clearStyle: false, // use heightStyle: "content" - fillSpace: false // use heightStyle: "fill" - }); - - var _create = prototype._create, - _setOption = prototype._setOption; - - $.extend( prototype, { - _create: function() { - this.options.heightStyle = this.options.heightStyle || - this._mergeHeightStyle(); - _create.call( this ); - }, + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // height options + (function( $, prototype ) { + $.extend( prototype.options, { + heightStyle: null, // remove default so we fall back to old values + autoHeight: true, // use heightStyle: "auto" + clearStyle: false, // use heightStyle: "content" + fillSpace: false // use heightStyle: "fill" + }); + + var _create = prototype._create, + _setOption = prototype._setOption; + + $.extend( prototype, { + _create: function() { + this.options.heightStyle = this.options.heightStyle || + this._mergeHeightStyle(); + + _create.call( this ); + }, - _setOption: function( key, value ) { - if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { - this.options.heightStyle = this._mergeHeightStyle(); - } - _setOption.apply( this, arguments ); - }, + _setOption: function( key, value ) { + if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { + this.options.heightStyle = this._mergeHeightStyle(); + } + _setOption.apply( this, arguments ); + }, - _mergeHeightStyle: function() { - var options = this.options; + _mergeHeightStyle: function() { + var options = this.options; - if ( options.fillSpace ) { - return "fill"; - } + if ( options.fillSpace ) { + return "fill"; + } - if ( options.clearStyle ) { - return "content"; - } + if ( options.clearStyle ) { + return "content"; + } - if ( options.autoHeight ) { - return "auto"; + if ( options.autoHeight ) { + return "auto"; + } } - } - }); -}( jQuery, jQuery.ui.accordion.prototype ) ); - -// icon options -(function( $, prototype ) { - prototype.options.icons.headerSelected = "ui-icon-triangle-1-s"; - - var _createIcons = prototype._createIcons; - prototype._createIcons = function() { - this.options.icons.activeHeader = this.options.icons.activeHeader || - this.options.icons.headerSelected; - _createIcons.call( this ); - }; -}( jQuery, jQuery.ui.accordion.prototype ) ); - -// expanded active option, activate method -(function( $, prototype ) { - prototype.activate = prototype._activate; - - var _findActive = prototype._findActive; - prototype._findActive = function( index ) { - if ( index === -1 ) { - index = false; - } - if ( index && typeof index !== "number" ) { - index = this.headers.index( this.headers.filter( index ) ); + }); + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // icon options + (function( $, prototype ) { + $.extend( prototype.options.icons, { + activeHeader: null, // remove default so we fall back to old values + headerSelected: "ui-icon-triangle-1-s" + }); + + var _createIcons = prototype._createIcons; + prototype._createIcons = function() { + this.options.icons.activeHeader = this.options.icons.activeHeader || + this.options.icons.headerSelected; + _createIcons.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // expanded active option, activate method + (function( $, prototype ) { + prototype.activate = prototype._activate; + + var _findActive = prototype._findActive; + prototype._findActive = function( index ) { if ( index === -1 ) { index = false; } - } - return _findActive.call( this, index ); - }; -}( jQuery, jQuery.ui.accordion.prototype ) ); + if ( index && typeof index !== "number" ) { + index = this.headers.index( this.headers.filter( index ) ); + if ( index === -1 ) { + index = false; + } + } + return _findActive.call( this, index ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // resize method + jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh; + + // change events + (function( $, prototype ) { + var _trigger = prototype._trigger; + prototype._trigger = function( type, event, data ) { + var ret = _trigger.apply( this, arguments ); + if ( !ret ) { + return false; + } -// resize method -jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh; + if ( type === "beforeActivate" ) { + ret = _trigger.call( this, "changestart", event, data ); + } else if ( type === "activate" ) { + ret = _trigger.call( this, "change", event, data ); + } + return ret; + } + }( jQuery, jQuery.ui.accordion.prototype ) ); +} })( jQuery ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 1342f7648..594d59530 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -15,7 +15,11 @@ */ (function( $, undefined ) { +// used to prevent race conditions with remote data sources +var requestIndex = 0; + $.widget( "ui.autocomplete", { + defaultElement: "<input>", options: { appendTo: "body", delay: 300, @@ -256,17 +260,16 @@ $.widget( "ui.autocomplete", { url: url, data: request, dataType: "json", - success: function( data, status, xhr ) { - if ( xhr === self.xhr ) { + autocompleteRequest: ++requestIndex, + success: function( data, status ) { + if ( this.autocompleteRequest === requestIndex ) { response( data ); } - self.xhr = null; }, - error: function( xhr ) { - if ( xhr === self.xhr ) { + error: function() { + if ( this.autocompleteRequest === requestIndex ) { response( [] ); } - self.xhr = null; } }); }; diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index b1d060a42..8f63ec57a 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -43,6 +43,7 @@ var lastActive, }; $.widget( "ui.button", { + defaultElement: "<button>", options: { disabled: null, text: true, diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 842557da8..c64057ee0 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -16,6 +16,7 @@ var idIncrement = 0; $.widget("ui.menu", { + defaultElement: "<ul>", _create: function() { var self = this; this.menuId = this.element.attr( "id" ) || "ui-menu-" + idIncrement++; diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index aa57e3233..05cbf2132 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -359,7 +359,7 @@ $.widget("ui.sortable", $.ui.mouse, { if(this.dragging) { - this._mouseUp(); + this._mouseUp({ target: null }); if(this.options.helper == "original") this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); @@ -377,21 +377,23 @@ $.widget("ui.sortable", $.ui.mouse, { } - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); - - $.extend(this, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); - if(this.domPosition.prev) { - $(this.domPosition.prev).after(this.currentItem); - } else { - $(this.domPosition.parent).prepend(this.currentItem); + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } } return this; diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index f444e3126..c8a76f4cf 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -14,6 +14,7 @@ (function($) { $.widget('ui.spinner', { + defaultElement: "<input>", options: { incremental: true, max: null, @@ -305,20 +306,14 @@ $.widget('ui.spinner', { _parse: function(val) { var input = val; if (typeof val == 'string') { - // special case for currency formatting until Globalization handles currencies - if (this.options.numberformat == "C" && window.Globalization) { - // parseFloat should accept number format, including currency - var culture = Globalization.culture || Globalization.cultures['default']; - val = val.replace(culture.numberFormat.currency.symbol, ""); - } - val = window.Globalization && this.options.numberformat ? Globalization.parseFloat(val) : +val; + val = $.global && this.options.numberformat ? $.global.parseFloat(val) : +val; } return isNaN(val) ? null : val; }, _format: function(num) { var num = this.options.value; - this.element.val( window.Globalization && this.options.numberformat ? Globalization.format(num, this.options.numberformat) : num ); + this.element.val( $.global && this.options.numberformat ? $.global.format(num, this.options.numberformat) : num ); }, destroy: function() { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 4f092f9d8..c8e5348ac 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -37,7 +37,13 @@ $.widget = function( name, base, prototype ) { $[ namespace ] = $[ namespace ] || {}; $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new $[ namespace ][ name ]( options, element ); + } + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) if ( arguments.length ) { this._createWidget( options, element ); } @@ -97,7 +103,7 @@ $.widget.bridge = function( name, object ) { if ( instance ) { instance.option( options || {} )._init(); } else { - $.data( this, name, new object( options, this ) ); + object( options, this ); } }); } @@ -107,7 +113,13 @@ $.widget.bridge = function( name, object ) { }; $.Widget = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new $[ namespace ][ name ]( options, element ); + } + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) if ( arguments.length ) { this._createWidget( options, element ); } @@ -116,13 +128,12 @@ $.Widget = function( options, element ) { $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", + defaultElement: "<div>", options: { disabled: false }, _createWidget: function( options, element ) { - // $.widget.bridge stores the plugin instance, but we do it anyway - // so that it's stored even before the _create function runs - $.data( element, this.widgetName, this ); + element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); this.options = $.extend( true, {}, this.options, @@ -132,7 +143,11 @@ $.Widget.prototype = { this.bindings = $(); this.hoverable = $(); this.focusable = $(); - this._bind({ remove: "destroy" }); + + if ( element !== this ) { + $.data( element, this.widgetName, this ); + this._bind({ remove: "destroy" }); + } this._create(); this._trigger( "create" ); |