bootstrap-source/bootstrap-3.0.3/js/tests/vendor/qunit.js
changeset 115 a9d04f5f5650
parent 114 6093dda9fe38
child 116 00287f05dc6a
     1.1 --- a/bootstrap-source/bootstrap-3.0.3/js/tests/vendor/qunit.js	Sat Jan 18 12:34:36 2014 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1510 +0,0 @@
     1.4 -/**
     1.5 - * QUnit - A JavaScript Unit Testing Framework
     1.6 - *
     1.7 - * http://docs.jquery.com/QUnit
     1.8 - *
     1.9 - * Copyright (c) 2012 John Resig, Jörn Zaefferer
    1.10 - * Dual licensed under the MIT (MIT-LICENSE.txt)
    1.11 - * or GPL (GPL-LICENSE.txt) licenses.
    1.12 - */
    1.13 -
    1.14 -(function(window) {
    1.15 -
    1.16 -var defined = {
    1.17 -	setTimeout: typeof window.setTimeout !== "undefined",
    1.18 -	sessionStorage: (function() {
    1.19 -		try {
    1.20 -			return !!sessionStorage.getItem;
    1.21 -		} catch(e) {
    1.22 -			return false;
    1.23 -		}
    1.24 -	})()
    1.25 -};
    1.26 -
    1.27 -var testId = 0;
    1.28 -
    1.29 -var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
    1.30 -	this.name = name;
    1.31 -	this.testName = testName;
    1.32 -	this.expected = expected;
    1.33 -	this.testEnvironmentArg = testEnvironmentArg;
    1.34 -	this.async = async;
    1.35 -	this.callback = callback;
    1.36 -	this.assertions = [];
    1.37 -};
    1.38 -Test.prototype = {
    1.39 -	init: function() {
    1.40 -		var tests = id("qunit-tests");
    1.41 -		if (tests) {
    1.42 -			var b = document.createElement("strong");
    1.43 -				b.innerHTML = "Running " + this.name;
    1.44 -			var li = document.createElement("li");
    1.45 -				li.appendChild( b );
    1.46 -				li.className = "running";
    1.47 -				li.id = this.id = "test-output" + testId++;
    1.48 -			tests.appendChild( li );
    1.49 -		}
    1.50 -	},
    1.51 -	setup: function() {
    1.52 -		if (this.module != config.previousModule) {
    1.53 -			if ( config.previousModule ) {
    1.54 -				QUnit.moduleDone( {
    1.55 -					name: config.previousModule,
    1.56 -					failed: config.moduleStats.bad,
    1.57 -					passed: config.moduleStats.all - config.moduleStats.bad,
    1.58 -					total: config.moduleStats.all
    1.59 -				} );
    1.60 -			}
    1.61 -			config.previousModule = this.module;
    1.62 -			config.moduleStats = { all: 0, bad: 0 };
    1.63 -			QUnit.moduleStart( {
    1.64 -				name: this.module
    1.65 -			} );
    1.66 -		}
    1.67 -
    1.68 -		config.current = this;
    1.69 -		this.testEnvironment = extend({
    1.70 -			setup: function() {},
    1.71 -			teardown: function() {}
    1.72 -		}, this.moduleTestEnvironment);
    1.73 -		if (this.testEnvironmentArg) {
    1.74 -			extend(this.testEnvironment, this.testEnvironmentArg);
    1.75 -		}
    1.76 -
    1.77 -		QUnit.testStart( {
    1.78 -			name: this.testName
    1.79 -		} );
    1.80 -
    1.81 -		// allow utility functions to access the current test environment
    1.82 -		// TODO why??
    1.83 -		QUnit.current_testEnvironment = this.testEnvironment;
    1.84 -
    1.85 -		try {
    1.86 -			if ( !config.pollution ) {
    1.87 -				saveGlobal();
    1.88 -			}
    1.89 -
    1.90 -			this.testEnvironment.setup.call(this.testEnvironment);
    1.91 -		} catch(e) {
    1.92 -			QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
    1.93 -		}
    1.94 -	},
    1.95 -	run: function() {
    1.96 -		if ( this.async ) {
    1.97 -			QUnit.stop();
    1.98 -		}
    1.99 -
   1.100 -		if ( config.notrycatch ) {
   1.101 -			this.callback.call(this.testEnvironment);
   1.102 -			return;
   1.103 -		}
   1.104 -		try {
   1.105 -			this.callback.call(this.testEnvironment);
   1.106 -		} catch(e) {
   1.107 -			fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
   1.108 -			QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
   1.109 -			// else next test will carry the responsibility
   1.110 -			saveGlobal();
   1.111 -
   1.112 -			// Restart the tests if they're blocking
   1.113 -			if ( config.blocking ) {
   1.114 -				start();
   1.115 -			}
   1.116 -		}
   1.117 -	},
   1.118 -	teardown: function() {
   1.119 -		try {
   1.120 -			this.testEnvironment.teardown.call(this.testEnvironment);
   1.121 -			checkPollution();
   1.122 -		} catch(e) {
   1.123 -			QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
   1.124 -		}
   1.125 -	},
   1.126 -	finish: function() {
   1.127 -		if ( this.expected && this.expected != this.assertions.length ) {
   1.128 -			QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
   1.129 -		}
   1.130 -
   1.131 -		var good = 0, bad = 0,
   1.132 -			tests = id("qunit-tests");
   1.133 -
   1.134 -		config.stats.all += this.assertions.length;
   1.135 -		config.moduleStats.all += this.assertions.length;
   1.136 -
   1.137 -		if ( tests ) {
   1.138 -			var ol = document.createElement("ol");
   1.139 -
   1.140 -			for ( var i = 0; i < this.assertions.length; i++ ) {
   1.141 -				var assertion = this.assertions[i];
   1.142 -
   1.143 -				var li = document.createElement("li");
   1.144 -				li.className = assertion.result ? "pass" : "fail";
   1.145 -				li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
   1.146 -				ol.appendChild( li );
   1.147 -
   1.148 -				if ( assertion.result ) {
   1.149 -					good++;
   1.150 -				} else {
   1.151 -					bad++;
   1.152 -					config.stats.bad++;
   1.153 -					config.moduleStats.bad++;
   1.154 -				}
   1.155 -			}
   1.156 -
   1.157 -			// store result when possible
   1.158 -			if ( QUnit.config.reorder && defined.sessionStorage ) {
   1.159 -				if (bad) {
   1.160 -					sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad);
   1.161 -				} else {
   1.162 -					sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName);
   1.163 -				}
   1.164 -			}
   1.165 -
   1.166 -			if (bad == 0) {
   1.167 -				ol.style.display = "none";
   1.168 -			}
   1.169 -
   1.170 -			var b = document.createElement("strong");
   1.171 -			b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
   1.172 -
   1.173 -			var a = document.createElement("a");
   1.174 -			a.innerHTML = "Rerun";
   1.175 -			a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
   1.176 -
   1.177 -			addEvent(b, "click", function() {
   1.178 -				var next = b.nextSibling.nextSibling,
   1.179 -					display = next.style.display;
   1.180 -				next.style.display = display === "none" ? "block" : "none";
   1.181 -			});
   1.182 -
   1.183 -			addEvent(b, "dblclick", function(e) {
   1.184 -				var target = e && e.target ? e.target : window.event.srcElement;
   1.185 -				if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
   1.186 -					target = target.parentNode;
   1.187 -				}
   1.188 -				if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
   1.189 -					window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
   1.190 -				}
   1.191 -			});
   1.192 -
   1.193 -			var li = id(this.id);
   1.194 -			li.className = bad ? "fail" : "pass";
   1.195 -			li.removeChild( li.firstChild );
   1.196 -			li.appendChild( b );
   1.197 -			li.appendChild( a );
   1.198 -			li.appendChild( ol );
   1.199 -
   1.200 -		} else {
   1.201 -			for ( var i = 0; i < this.assertions.length; i++ ) {
   1.202 -				if ( !this.assertions[i].result ) {
   1.203 -					bad++;
   1.204 -					config.stats.bad++;
   1.205 -					config.moduleStats.bad++;
   1.206 -				}
   1.207 -			}
   1.208 -		}
   1.209 -
   1.210 -		try {
   1.211 -			QUnit.reset();
   1.212 -		} catch(e) {
   1.213 -			fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
   1.214 -		}
   1.215 -
   1.216 -		QUnit.testDone( {
   1.217 -			name: this.testName,
   1.218 -			failed: bad,
   1.219 -			passed: this.assertions.length - bad,
   1.220 -			total: this.assertions.length
   1.221 -		} );
   1.222 -	},
   1.223 -
   1.224 -	queue: function() {
   1.225 -		var test = this;
   1.226 -		synchronize(function() {
   1.227 -			test.init();
   1.228 -		});
   1.229 -		function run() {
   1.230 -			// each of these can by async
   1.231 -			synchronize(function() {
   1.232 -				test.setup();
   1.233 -			});
   1.234 -			synchronize(function() {
   1.235 -				test.run();
   1.236 -			});
   1.237 -			synchronize(function() {
   1.238 -				test.teardown();
   1.239 -			});
   1.240 -			synchronize(function() {
   1.241 -				test.finish();
   1.242 -			});
   1.243 -		}
   1.244 -		// defer when previous test run passed, if storage is available
   1.245 -		var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName);
   1.246 -		if (bad) {
   1.247 -			run();
   1.248 -		} else {
   1.249 -			synchronize(run);
   1.250 -		};
   1.251 -	}
   1.252 -
   1.253 -};
   1.254 -
   1.255 -var QUnit = {
   1.256 -
   1.257 -	// call on start of module test to prepend name to all tests
   1.258 -	module: function(name, testEnvironment) {
   1.259 -		config.currentModule = name;
   1.260 -		config.currentModuleTestEnviroment = testEnvironment;
   1.261 -	},
   1.262 -
   1.263 -	asyncTest: function(testName, expected, callback) {
   1.264 -		if ( arguments.length === 2 ) {
   1.265 -			callback = expected;
   1.266 -			expected = 0;
   1.267 -		}
   1.268 -
   1.269 -		QUnit.test(testName, expected, callback, true);
   1.270 -	},
   1.271 -
   1.272 -	test: function(testName, expected, callback, async) {
   1.273 -		var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg;
   1.274 -
   1.275 -		if ( arguments.length === 2 ) {
   1.276 -			callback = expected;
   1.277 -			expected = null;
   1.278 -		}
   1.279 -		// is 2nd argument a testEnvironment?
   1.280 -		if ( expected && typeof expected === 'object') {
   1.281 -			testEnvironmentArg = expected;
   1.282 -			expected = null;
   1.283 -		}
   1.284 -
   1.285 -		if ( config.currentModule ) {
   1.286 -			name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
   1.287 -		}
   1.288 -
   1.289 -		if ( !validTest(config.currentModule + ": " + testName) ) {
   1.290 -			return;
   1.291 -		}
   1.292 -
   1.293 -		var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
   1.294 -		test.module = config.currentModule;
   1.295 -		test.moduleTestEnvironment = config.currentModuleTestEnviroment;
   1.296 -		test.queue();
   1.297 -	},
   1.298 -
   1.299 -	/**
   1.300 -	 * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
   1.301 -	 */
   1.302 -	expect: function(asserts) {
   1.303 -		config.current.expected = asserts;
   1.304 -	},
   1.305 -
   1.306 -	/**
   1.307 -	 * Asserts true.
   1.308 -	 * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
   1.309 -	 */
   1.310 -	ok: function(a, msg) {
   1.311 -		a = !!a;
   1.312 -		var details = {
   1.313 -			result: a,
   1.314 -			message: msg
   1.315 -		};
   1.316 -		msg = escapeHtml(msg);
   1.317 -		QUnit.log(details);
   1.318 -		config.current.assertions.push({
   1.319 -			result: a,
   1.320 -			message: msg
   1.321 -		});
   1.322 -	},
   1.323 -
   1.324 -	/**
   1.325 -	 * Checks that the first two arguments are equal, with an optional message.
   1.326 -	 * Prints out both actual and expected values.
   1.327 -	 *
   1.328 -	 * Prefered to ok( actual == expected, message )
   1.329 -	 *
   1.330 -	 * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
   1.331 -	 *
   1.332 -	 * @param Object actual
   1.333 -	 * @param Object expected
   1.334 -	 * @param String message (optional)
   1.335 -	 */
   1.336 -	equal: function(actual, expected, message) {
   1.337 -		QUnit.push(expected == actual, actual, expected, message);
   1.338 -	},
   1.339 -
   1.340 -	notEqual: function(actual, expected, message) {
   1.341 -		QUnit.push(expected != actual, actual, expected, message);
   1.342 -	},
   1.343 -
   1.344 -	deepEqual: function(actual, expected, message) {
   1.345 -		QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
   1.346 -	},
   1.347 -
   1.348 -	notDeepEqual: function(actual, expected, message) {
   1.349 -		QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
   1.350 -	},
   1.351 -
   1.352 -	strictEqual: function(actual, expected, message) {
   1.353 -		QUnit.push(expected === actual, actual, expected, message);
   1.354 -	},
   1.355 -
   1.356 -	notStrictEqual: function(actual, expected, message) {
   1.357 -		QUnit.push(expected !== actual, actual, expected, message);
   1.358 -	},
   1.359 -
   1.360 -	raises: function(block, expected, message) {
   1.361 -		var actual, ok = false;
   1.362 -
   1.363 -		if (typeof expected === 'string') {
   1.364 -			message = expected;
   1.365 -			expected = null;
   1.366 -		}
   1.367 -
   1.368 -		try {
   1.369 -			block();
   1.370 -		} catch (e) {
   1.371 -			actual = e;
   1.372 -		}
   1.373 -
   1.374 -		if (actual) {
   1.375 -			// we don't want to validate thrown error
   1.376 -			if (!expected) {
   1.377 -				ok = true;
   1.378 -			// expected is a regexp
   1.379 -			} else if (QUnit.objectType(expected) === "regexp") {
   1.380 -				ok = expected.test(actual);
   1.381 -			// expected is a constructor
   1.382 -			} else if (actual instanceof expected) {
   1.383 -				ok = true;
   1.384 -			// expected is a validation function which returns true is validation passed
   1.385 -			} else if (expected.call({}, actual) === true) {
   1.386 -				ok = true;
   1.387 -			}
   1.388 -		}
   1.389 -
   1.390 -		QUnit.ok(ok, message);
   1.391 -	},
   1.392 -
   1.393 -	start: function() {
   1.394 -		config.semaphore--;
   1.395 -		if (config.semaphore > 0) {
   1.396 -			// don't start until equal number of stop-calls
   1.397 -			return;
   1.398 -		}
   1.399 -		if (config.semaphore < 0) {
   1.400 -			// ignore if start is called more often then stop
   1.401 -			config.semaphore = 0;
   1.402 -		}
   1.403 -		// A slight delay, to avoid any current callbacks
   1.404 -		if ( defined.setTimeout ) {
   1.405 -			window.setTimeout(function() {
   1.406 -				if (config.semaphore > 0) {
   1.407 -					return;
   1.408 -				}
   1.409 -				if ( config.timeout ) {
   1.410 -					clearTimeout(config.timeout);
   1.411 -				}
   1.412 -
   1.413 -				config.blocking = false;
   1.414 -				process();
   1.415 -			}, 13);
   1.416 -		} else {
   1.417 -			config.blocking = false;
   1.418 -			process();
   1.419 -		}
   1.420 -	},
   1.421 -
   1.422 -	stop: function(timeout) {
   1.423 -		config.semaphore++;
   1.424 -		config.blocking = true;
   1.425 -
   1.426 -		if ( timeout && defined.setTimeout ) {
   1.427 -			clearTimeout(config.timeout);
   1.428 -			config.timeout = window.setTimeout(function() {
   1.429 -				QUnit.ok( false, "Test timed out" );
   1.430 -				QUnit.start();
   1.431 -			}, timeout);
   1.432 -		}
   1.433 -	}
   1.434 -};
   1.435 -
   1.436 -// Backwards compatibility, deprecated
   1.437 -QUnit.equals = QUnit.equal;
   1.438 -QUnit.same = QUnit.deepEqual;
   1.439 -
   1.440 -// Maintain internal state
   1.441 -var config = {
   1.442 -	// The queue of tests to run
   1.443 -	queue: [],
   1.444 -
   1.445 -	// block until document ready
   1.446 -	blocking: true,
   1.447 -
   1.448 -	// when enabled, show only failing tests
   1.449 -	// gets persisted through sessionStorage and can be changed in UI via checkbox
   1.450 -	hidepassed: false,
   1.451 -
   1.452 -	// by default, run previously failed tests first
   1.453 -	// very useful in combination with "Hide passed tests" checked
   1.454 -	reorder: true,
   1.455 -
   1.456 -	// by default, modify document.title when suite is done
   1.457 -	altertitle: true,
   1.458 -
   1.459 -	urlConfig: ['noglobals', 'notrycatch']
   1.460 -};
   1.461 -
   1.462 -// Load paramaters
   1.463 -(function() {
   1.464 -	var location = window.location || { search: "", protocol: "file:" },
   1.465 -		params = location.search.slice( 1 ).split( "&" ),
   1.466 -		length = params.length,
   1.467 -		urlParams = {},
   1.468 -		current;
   1.469 -
   1.470 -	if ( params[ 0 ] ) {
   1.471 -		for ( var i = 0; i < length; i++ ) {
   1.472 -			current = params[ i ].split( "=" );
   1.473 -			current[ 0 ] = decodeURIComponent( current[ 0 ] );
   1.474 -			// allow just a key to turn on a flag, e.g., test.html?noglobals
   1.475 -			current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
   1.476 -			urlParams[ current[ 0 ] ] = current[ 1 ];
   1.477 -		}
   1.478 -	}
   1.479 -
   1.480 -	QUnit.urlParams = urlParams;
   1.481 -	config.filter = urlParams.filter;
   1.482 -
   1.483 -	// Figure out if we're running the tests from a server or not
   1.484 -	QUnit.isLocal = !!(location.protocol === 'file:');
   1.485 -})();
   1.486 -
   1.487 -// Expose the API as global variables, unless an 'exports'
   1.488 -// object exists, in that case we assume we're in CommonJS
   1.489 -if ( typeof exports === "undefined" || typeof require === "undefined" ) {
   1.490 -	extend(window, QUnit);
   1.491 -	window.QUnit = QUnit;
   1.492 -} else {
   1.493 -	extend(exports, QUnit);
   1.494 -	exports.QUnit = QUnit;
   1.495 -}
   1.496 -
   1.497 -// define these after exposing globals to keep them in these QUnit namespace only
   1.498 -extend(QUnit, {
   1.499 -	config: config,
   1.500 -
   1.501 -	// Initialize the configuration options
   1.502 -	init: function() {
   1.503 -		extend(config, {
   1.504 -			stats: { all: 0, bad: 0 },
   1.505 -			moduleStats: { all: 0, bad: 0 },
   1.506 -			started: +new Date,
   1.507 -			updateRate: 1000,
   1.508 -			blocking: false,
   1.509 -			autostart: true,
   1.510 -			autorun: false,
   1.511 -			filter: "",
   1.512 -			queue: [],
   1.513 -			semaphore: 0
   1.514 -		});
   1.515 -
   1.516 -		var tests = id( "qunit-tests" ),
   1.517 -			banner = id( "qunit-banner" ),
   1.518 -			result = id( "qunit-testresult" );
   1.519 -
   1.520 -		if ( tests ) {
   1.521 -			tests.innerHTML = "";
   1.522 -		}
   1.523 -
   1.524 -		if ( banner ) {
   1.525 -			banner.className = "";
   1.526 -		}
   1.527 -
   1.528 -		if ( result ) {
   1.529 -			result.parentNode.removeChild( result );
   1.530 -		}
   1.531 -
   1.532 -		if ( tests ) {
   1.533 -			result = document.createElement( "p" );
   1.534 -			result.id = "qunit-testresult";
   1.535 -			result.className = "result";
   1.536 -			tests.parentNode.insertBefore( result, tests );
   1.537 -			result.innerHTML = 'Running...<br/>&nbsp;';
   1.538 -		}
   1.539 -	},
   1.540 -
   1.541 -	/**
   1.542 -	 * Resets the test setup. Useful for tests that modify the DOM.
   1.543 -	 *
   1.544 -	 * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
   1.545 -	 */
   1.546 -	reset: function() {
   1.547 -		if ( window.jQuery ) {
   1.548 -			jQuery( "#qunit-fixture" ).html( config.fixture );
   1.549 -		} else {
   1.550 -			var main = id( 'qunit-fixture' );
   1.551 -			if ( main ) {
   1.552 -				main.innerHTML = config.fixture;
   1.553 -			}
   1.554 -		}
   1.555 -	},
   1.556 -
   1.557 -	/**
   1.558 -	 * Trigger an event on an element.
   1.559 -	 *
   1.560 -	 * @example triggerEvent( document.body, "click" );
   1.561 -	 *
   1.562 -	 * @param DOMElement elem
   1.563 -	 * @param String type
   1.564 -	 */
   1.565 -	triggerEvent: function( elem, type, event ) {
   1.566 -		if ( document.createEvent ) {
   1.567 -			event = document.createEvent("MouseEvents");
   1.568 -			event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
   1.569 -				0, 0, 0, 0, 0, false, false, false, false, 0, null);
   1.570 -			elem.dispatchEvent( event );
   1.571 -
   1.572 -		} else if ( elem.fireEvent ) {
   1.573 -			elem.fireEvent("on"+type);
   1.574 -		}
   1.575 -	},
   1.576 -
   1.577 -	// Safe object type checking
   1.578 -	is: function( type, obj ) {
   1.579 -		return QUnit.objectType( obj ) == type;
   1.580 -	},
   1.581 -
   1.582 -	objectType: function( obj ) {
   1.583 -		if (typeof obj === "undefined") {
   1.584 -				return "undefined";
   1.585 -
   1.586 -		// consider: typeof null === object
   1.587 -		}
   1.588 -		if (obj === null) {
   1.589 -				return "null";
   1.590 -		}
   1.591 -
   1.592 -		var type = Object.prototype.toString.call( obj )
   1.593 -			.match(/^\[object\s(.*)\]$/)[1] || '';
   1.594 -
   1.595 -		switch (type) {
   1.596 -				case 'Number':
   1.597 -						if (isNaN(obj)) {
   1.598 -								return "nan";
   1.599 -						} else {
   1.600 -								return "number";
   1.601 -						}
   1.602 -				case 'String':
   1.603 -				case 'Boolean':
   1.604 -				case 'Array':
   1.605 -				case 'Date':
   1.606 -				case 'RegExp':
   1.607 -				case 'Function':
   1.608 -						return type.toLowerCase();
   1.609 -		}
   1.610 -		if (typeof obj === "object") {
   1.611 -				return "object";
   1.612 -		}
   1.613 -		return undefined;
   1.614 -	},
   1.615 -
   1.616 -	push: function(result, actual, expected, message) {
   1.617 -		var details = {
   1.618 -			result: result,
   1.619 -			message: message,
   1.620 -			actual: actual,
   1.621 -			expected: expected
   1.622 -		};
   1.623 -
   1.624 -		message = escapeHtml(message) || (result ? "okay" : "failed");
   1.625 -		message = '<span class="test-message">' + message + "</span>";
   1.626 -		expected = escapeHtml(QUnit.jsDump.parse(expected));
   1.627 -		actual = escapeHtml(QUnit.jsDump.parse(actual));
   1.628 -		var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
   1.629 -		if (actual != expected) {
   1.630 -			output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
   1.631 -			output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
   1.632 -		}
   1.633 -		if (!result) {
   1.634 -			var source = sourceFromStacktrace();
   1.635 -			if (source) {
   1.636 -				details.source = source;
   1.637 -				output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeHtml(source) + '</pre></td></tr>';
   1.638 -			}
   1.639 -		}
   1.640 -		output += "</table>";
   1.641 -
   1.642 -		QUnit.log(details);
   1.643 -
   1.644 -		config.current.assertions.push({
   1.645 -			result: !!result,
   1.646 -			message: output
   1.647 -		});
   1.648 -	},
   1.649 -
   1.650 -	url: function( params ) {
   1.651 -		params = extend( extend( {}, QUnit.urlParams ), params );
   1.652 -		var querystring = "?",
   1.653 -			key;
   1.654 -		for ( key in params ) {
   1.655 -			querystring += encodeURIComponent( key ) + "=" +
   1.656 -				encodeURIComponent( params[ key ] ) + "&";
   1.657 -		}
   1.658 -		return window.location.pathname + querystring.slice( 0, -1 );
   1.659 -	},
   1.660 -
   1.661 -	extend: extend,
   1.662 -	id: id,
   1.663 -	addEvent: addEvent,
   1.664 -
   1.665 -	// Logging callbacks; all receive a single argument with the listed properties
   1.666 -	// run test/logs.html for any related changes
   1.667 -	begin: function() {},
   1.668 -	// done: { failed, passed, total, runtime }
   1.669 -	done: function() {},
   1.670 -	// log: { result, actual, expected, message }
   1.671 -	log: function() {},
   1.672 -	// testStart: { name }
   1.673 -	testStart: function() {},
   1.674 -	// testDone: { name, failed, passed, total }
   1.675 -	testDone: function() {},
   1.676 -	// moduleStart: { name }
   1.677 -	moduleStart: function() {},
   1.678 -	// moduleDone: { name, failed, passed, total }
   1.679 -	moduleDone: function() {}
   1.680 -});
   1.681 -
   1.682 -if ( typeof document === "undefined" || document.readyState === "complete" ) {
   1.683 -	config.autorun = true;
   1.684 -}
   1.685 -
   1.686 -QUnit.load = function() {
   1.687 -	QUnit.begin({});
   1.688 -
   1.689 -	// Initialize the config, saving the execution queue
   1.690 -	var oldconfig = extend({}, config);
   1.691 -	QUnit.init();
   1.692 -	extend(config, oldconfig);
   1.693 -
   1.694 -	config.blocking = false;
   1.695 -
   1.696 -	var urlConfigHtml = '', len = config.urlConfig.length;
   1.697 -	for ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) {
   1.698 -		config[val] = QUnit.urlParams[val];
   1.699 -		urlConfigHtml += '<label><input name="' + val + '" type="checkbox"' + ( config[val] ? ' checked="checked"' : '' ) + '>' + val + '</label>';
   1.700 -	}
   1.701 -
   1.702 -	var userAgent = id("qunit-userAgent");
   1.703 -	if ( userAgent ) {
   1.704 -		userAgent.innerHTML = navigator.userAgent;
   1.705 -	}
   1.706 -	var banner = id("qunit-header");
   1.707 -	if ( banner ) {
   1.708 -		banner.innerHTML = '<a href="' + QUnit.url({ filter: undefined }) + '"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;
   1.709 -		addEvent( banner, "change", function( event ) {
   1.710 -			var params = {};
   1.711 -			params[ event.target.name ] = event.target.checked ? true : undefined;
   1.712 -			window.location = QUnit.url( params );
   1.713 -		});
   1.714 -	}
   1.715 -
   1.716 -	var toolbar = id("qunit-testrunner-toolbar");
   1.717 -	if ( toolbar ) {
   1.718 -		var filter = document.createElement("input");
   1.719 -		filter.type = "checkbox";
   1.720 -		filter.id = "qunit-filter-pass";
   1.721 -		addEvent( filter, "click", function() {
   1.722 -			var ol = document.getElementById("qunit-tests");
   1.723 -			if ( filter.checked ) {
   1.724 -				ol.className = ol.className + " hidepass";
   1.725 -			} else {
   1.726 -				var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
   1.727 -				ol.className = tmp.replace(/ hidepass /, " ");
   1.728 -			}
   1.729 -			if ( defined.sessionStorage ) {
   1.730 -				if (filter.checked) {
   1.731 -					sessionStorage.setItem("qunit-filter-passed-tests", "true");
   1.732 -				} else {
   1.733 -					sessionStorage.removeItem("qunit-filter-passed-tests");
   1.734 -				}
   1.735 -			}
   1.736 -		});
   1.737 -		if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
   1.738 -			filter.checked = true;
   1.739 -			var ol = document.getElementById("qunit-tests");
   1.740 -			ol.className = ol.className + " hidepass";
   1.741 -		}
   1.742 -		toolbar.appendChild( filter );
   1.743 -
   1.744 -		var label = document.createElement("label");
   1.745 -		label.setAttribute("for", "qunit-filter-pass");
   1.746 -		label.innerHTML = "Hide passed tests";
   1.747 -		toolbar.appendChild( label );
   1.748 -	}
   1.749 -
   1.750 -	var main = id('qunit-fixture');
   1.751 -	if ( main ) {
   1.752 -		config.fixture = main.innerHTML;
   1.753 -	}
   1.754 -
   1.755 -	if (config.autostart) {
   1.756 -		QUnit.start();
   1.757 -	}
   1.758 -};
   1.759 -
   1.760 -addEvent(window, "load", QUnit.load);
   1.761 -
   1.762 -function done() {
   1.763 -	config.autorun = true;
   1.764 -
   1.765 -	// Log the last module results
   1.766 -	if ( config.currentModule ) {
   1.767 -		QUnit.moduleDone( {
   1.768 -			name: config.currentModule,
   1.769 -			failed: config.moduleStats.bad,
   1.770 -			passed: config.moduleStats.all - config.moduleStats.bad,
   1.771 -			total: config.moduleStats.all
   1.772 -		} );
   1.773 -	}
   1.774 -
   1.775 -	var banner = id("qunit-banner"),
   1.776 -		tests = id("qunit-tests"),
   1.777 -		runtime = +new Date - config.started,
   1.778 -		passed = config.stats.all - config.stats.bad,
   1.779 -		html = [
   1.780 -			'Tests completed in ',
   1.781 -			runtime,
   1.782 -			' milliseconds.<br/>',
   1.783 -			'<span class="passed">',
   1.784 -			passed,
   1.785 -			'</span> tests of <span class="total">',
   1.786 -			config.stats.all,
   1.787 -			'</span> passed, <span class="failed">',
   1.788 -			config.stats.bad,
   1.789 -			'</span> failed.'
   1.790 -		].join('');
   1.791 -
   1.792 -	if ( banner ) {
   1.793 -		banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
   1.794 -	}
   1.795 -
   1.796 -	if ( tests ) {
   1.797 -		id( "qunit-testresult" ).innerHTML = html;
   1.798 -	}
   1.799 -
   1.800 -	if ( config.altertitle && typeof document !== "undefined" && document.title ) {
   1.801 -		// show ✖ for good, ✔ for bad suite result in title
   1.802 -		// use escape sequences in case file gets loaded with non-utf-8-charset
   1.803 -		document.title = [
   1.804 -			(config.stats.bad ? "\u2716" : "\u2714"),
   1.805 -			document.title.replace(/^[\u2714\u2716] /i, "")
   1.806 -		].join(" ");
   1.807 -	}
   1.808 -
   1.809 -	QUnit.done( {
   1.810 -		failed: config.stats.bad,
   1.811 -		passed: passed,
   1.812 -		total: config.stats.all,
   1.813 -		runtime: runtime
   1.814 -	} );
   1.815 -}
   1.816 -
   1.817 -function validTest( name ) {
   1.818 -	var filter = config.filter,
   1.819 -		run = false;
   1.820 -
   1.821 -	if ( !filter ) {
   1.822 -		return true;
   1.823 -	}
   1.824 -
   1.825 -	var not = filter.charAt( 0 ) === "!";
   1.826 -	if ( not ) {
   1.827 -		filter = filter.slice( 1 );
   1.828 -	}
   1.829 -
   1.830 -	if ( name.indexOf( filter ) !== -1 ) {
   1.831 -		return !not;
   1.832 -	}
   1.833 -
   1.834 -	if ( not ) {
   1.835 -		run = true;
   1.836 -	}
   1.837 -
   1.838 -	return run;
   1.839 -}
   1.840 -
   1.841 -// so far supports only Firefox, Chrome and Opera (buggy)
   1.842 -// could be extended in the future to use something like https://github.com/csnover/TraceKit
   1.843 -function sourceFromStacktrace() {
   1.844 -	try {
   1.845 -		throw new Error();
   1.846 -	} catch ( e ) {
   1.847 -		if (e.stacktrace) {
   1.848 -			// Opera
   1.849 -			return e.stacktrace.split("\n")[6];
   1.850 -		} else if (e.stack) {
   1.851 -			// Firefox, Chrome
   1.852 -			return e.stack.split("\n")[4];
   1.853 -		} else if (e.sourceURL) {
   1.854 -			// Safari, PhantomJS
   1.855 -			// TODO sourceURL points at the 'throw new Error' line above, useless
   1.856 -			//return e.sourceURL + ":" + e.line;
   1.857 -		}
   1.858 -	}
   1.859 -}
   1.860 -
   1.861 -function escapeHtml(s) {
   1.862 -	if (!s) {
   1.863 -		return "";
   1.864 -	}
   1.865 -	s = s + "";
   1.866 -	return s.replace(/[\&"<>\\]/g, function(s) {
   1.867 -		switch(s) {
   1.868 -			case "&": return "&amp;";
   1.869 -			case "\\": return "\\\\";
   1.870 -			case '"': return '\"';
   1.871 -			case "<": return "&lt;";
   1.872 -			case ">": return "&gt;";
   1.873 -			default: return s;
   1.874 -		}
   1.875 -	});
   1.876 -}
   1.877 -
   1.878 -function synchronize( callback ) {
   1.879 -	config.queue.push( callback );
   1.880 -
   1.881 -	if ( config.autorun && !config.blocking ) {
   1.882 -		process();
   1.883 -	}
   1.884 -}
   1.885 -
   1.886 -function process() {
   1.887 -	var start = (new Date()).getTime();
   1.888 -
   1.889 -	while ( config.queue.length && !config.blocking ) {
   1.890 -		if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
   1.891 -			config.queue.shift()();
   1.892 -		} else {
   1.893 -			window.setTimeout( process, 13 );
   1.894 -			break;
   1.895 -		}
   1.896 -	}
   1.897 -	if (!config.blocking && !config.queue.length) {
   1.898 -		done();
   1.899 -	}
   1.900 -}
   1.901 -
   1.902 -function saveGlobal() {
   1.903 -	config.pollution = [];
   1.904 -
   1.905 -	if ( config.noglobals ) {
   1.906 -		for ( var key in window ) {
   1.907 -			config.pollution.push( key );
   1.908 -		}
   1.909 -	}
   1.910 -}
   1.911 -
   1.912 -function checkPollution( name ) {
   1.913 -	var old = config.pollution;
   1.914 -	saveGlobal();
   1.915 -
   1.916 -	var newGlobals = diff( config.pollution, old );
   1.917 -	if ( newGlobals.length > 0 ) {
   1.918 -		ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
   1.919 -	}
   1.920 -
   1.921 -	var deletedGlobals = diff( old, config.pollution );
   1.922 -	if ( deletedGlobals.length > 0 ) {
   1.923 -		ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
   1.924 -	}
   1.925 -}
   1.926 -
   1.927 -// returns a new Array with the elements that are in a but not in b
   1.928 -function diff( a, b ) {
   1.929 -	var result = a.slice();
   1.930 -	for ( var i = 0; i < result.length; i++ ) {
   1.931 -		for ( var j = 0; j < b.length; j++ ) {
   1.932 -			if ( result[i] === b[j] ) {
   1.933 -				result.splice(i, 1);
   1.934 -				i--;
   1.935 -				break;
   1.936 -			}
   1.937 -		}
   1.938 -	}
   1.939 -	return result;
   1.940 -}
   1.941 -
   1.942 -function fail(message, exception, callback) {
   1.943 -	if ( typeof console !== "undefined" && console.error && console.warn ) {
   1.944 -		console.error(message);
   1.945 -		console.error(exception);
   1.946 -		console.warn(callback.toString());
   1.947 -
   1.948 -	} else if ( window.opera && opera.postError ) {
   1.949 -		opera.postError(message, exception, callback.toString);
   1.950 -	}
   1.951 -}
   1.952 -
   1.953 -function extend(a, b) {
   1.954 -	for ( var prop in b ) {
   1.955 -		if ( b[prop] === undefined ) {
   1.956 -			delete a[prop];
   1.957 -		} else {
   1.958 -			a[prop] = b[prop];
   1.959 -		}
   1.960 -	}
   1.961 -
   1.962 -	return a;
   1.963 -}
   1.964 -
   1.965 -function addEvent(elem, type, fn) {
   1.966 -	if ( elem.addEventListener ) {
   1.967 -		elem.addEventListener( type, fn, false );
   1.968 -	} else if ( elem.attachEvent ) {
   1.969 -		elem.attachEvent( "on" + type, fn );
   1.970 -	} else {
   1.971 -		fn();
   1.972 -	}
   1.973 -}
   1.974 -
   1.975 -function id(name) {
   1.976 -	return !!(typeof document !== "undefined" && document && document.getElementById) &&
   1.977 -		document.getElementById( name );
   1.978 -}
   1.979 -
   1.980 -// Test for equality any JavaScript type.
   1.981 -// Discussions and reference: http://philrathe.com/articles/equiv
   1.982 -// Test suites: http://philrathe.com/tests/equiv
   1.983 -// Author: Philippe Rathé <prathe@gmail.com>
   1.984 -QUnit.equiv = function () {
   1.985 -
   1.986 -	var innerEquiv; // the real equiv function
   1.987 -	var callers = []; // stack to decide between skip/abort functions
   1.988 -	var parents = []; // stack to avoiding loops from circular referencing
   1.989 -
   1.990 -	// Call the o related callback with the given arguments.
   1.991 -	function bindCallbacks(o, callbacks, args) {
   1.992 -		var prop = QUnit.objectType(o);
   1.993 -		if (prop) {
   1.994 -			if (QUnit.objectType(callbacks[prop]) === "function") {
   1.995 -				return callbacks[prop].apply(callbacks, args);
   1.996 -			} else {
   1.997 -				return callbacks[prop]; // or undefined
   1.998 -			}
   1.999 -		}
  1.1000 -	}
  1.1001 -
  1.1002 -	var callbacks = function () {
  1.1003 -
  1.1004 -		// for string, boolean, number and null
  1.1005 -		function useStrictEquality(b, a) {
  1.1006 -			if (b instanceof a.constructor || a instanceof b.constructor) {
  1.1007 -				// to catch short annotaion VS 'new' annotation of a
  1.1008 -				// declaration
  1.1009 -				// e.g. var i = 1;
  1.1010 -				// var j = new Number(1);
  1.1011 -				return a == b;
  1.1012 -			} else {
  1.1013 -				return a === b;
  1.1014 -			}
  1.1015 -		}
  1.1016 -
  1.1017 -		return {
  1.1018 -			"string" : useStrictEquality,
  1.1019 -			"boolean" : useStrictEquality,
  1.1020 -			"number" : useStrictEquality,
  1.1021 -			"null" : useStrictEquality,
  1.1022 -			"undefined" : useStrictEquality,
  1.1023 -
  1.1024 -			"nan" : function(b) {
  1.1025 -				return isNaN(b);
  1.1026 -			},
  1.1027 -
  1.1028 -			"date" : function(b, a) {
  1.1029 -				return QUnit.objectType(b) === "date"
  1.1030 -						&& a.valueOf() === b.valueOf();
  1.1031 -			},
  1.1032 -
  1.1033 -			"regexp" : function(b, a) {
  1.1034 -				return QUnit.objectType(b) === "regexp"
  1.1035 -						&& a.source === b.source && // the regex itself
  1.1036 -						a.global === b.global && // and its modifers
  1.1037 -													// (gmi) ...
  1.1038 -						a.ignoreCase === b.ignoreCase
  1.1039 -						&& a.multiline === b.multiline;
  1.1040 -			},
  1.1041 -
  1.1042 -			// - skip when the property is a method of an instance (OOP)
  1.1043 -			// - abort otherwise,
  1.1044 -			// initial === would have catch identical references anyway
  1.1045 -			"function" : function() {
  1.1046 -				var caller = callers[callers.length - 1];
  1.1047 -				return caller !== Object && typeof caller !== "undefined";
  1.1048 -			},
  1.1049 -
  1.1050 -			"array" : function(b, a) {
  1.1051 -				var i, j, loop;
  1.1052 -				var len;
  1.1053 -
  1.1054 -				// b could be an object literal here
  1.1055 -				if (!(QUnit.objectType(b) === "array")) {
  1.1056 -					return false;
  1.1057 -				}
  1.1058 -
  1.1059 -				len = a.length;
  1.1060 -				if (len !== b.length) { // safe and faster
  1.1061 -					return false;
  1.1062 -				}
  1.1063 -
  1.1064 -				// track reference to avoid circular references
  1.1065 -				parents.push(a);
  1.1066 -				for (i = 0; i < len; i++) {
  1.1067 -					loop = false;
  1.1068 -					for (j = 0; j < parents.length; j++) {
  1.1069 -						if (parents[j] === a[i]) {
  1.1070 -							loop = true;// dont rewalk array
  1.1071 -						}
  1.1072 -					}
  1.1073 -					if (!loop && !innerEquiv(a[i], b[i])) {
  1.1074 -						parents.pop();
  1.1075 -						return false;
  1.1076 -					}
  1.1077 -				}
  1.1078 -				parents.pop();
  1.1079 -				return true;
  1.1080 -			},
  1.1081 -
  1.1082 -			"object" : function(b, a) {
  1.1083 -				var i, j, loop;
  1.1084 -				var eq = true; // unless we can proove it
  1.1085 -				var aProperties = [], bProperties = []; // collection of
  1.1086 -														// strings
  1.1087 -
  1.1088 -				// comparing constructors is more strict than using
  1.1089 -				// instanceof
  1.1090 -				if (a.constructor !== b.constructor) {
  1.1091 -					return false;
  1.1092 -				}
  1.1093 -
  1.1094 -				// stack constructor before traversing properties
  1.1095 -				callers.push(a.constructor);
  1.1096 -				// track reference to avoid circular references
  1.1097 -				parents.push(a);
  1.1098 -
  1.1099 -				for (i in a) { // be strict: don't ensures hasOwnProperty
  1.1100 -								// and go deep
  1.1101 -					loop = false;
  1.1102 -					for (j = 0; j < parents.length; j++) {
  1.1103 -						if (parents[j] === a[i])
  1.1104 -							loop = true; // don't go down the same path
  1.1105 -											// twice
  1.1106 -					}
  1.1107 -					aProperties.push(i); // collect a's properties
  1.1108 -
  1.1109 -					if (!loop && !innerEquiv(a[i], b[i])) {
  1.1110 -						eq = false;
  1.1111 -						break;
  1.1112 -					}
  1.1113 -				}
  1.1114 -
  1.1115 -				callers.pop(); // unstack, we are done
  1.1116 -				parents.pop();
  1.1117 -
  1.1118 -				for (i in b) {
  1.1119 -					bProperties.push(i); // collect b's properties
  1.1120 -				}
  1.1121 -
  1.1122 -				// Ensures identical properties name
  1.1123 -				return eq
  1.1124 -						&& innerEquiv(aProperties.sort(), bProperties
  1.1125 -								.sort());
  1.1126 -			}
  1.1127 -		};
  1.1128 -	}();
  1.1129 -
  1.1130 -	innerEquiv = function() { // can take multiple arguments
  1.1131 -		var args = Array.prototype.slice.apply(arguments);
  1.1132 -		if (args.length < 2) {
  1.1133 -			return true; // end transition
  1.1134 -		}
  1.1135 -
  1.1136 -		return (function(a, b) {
  1.1137 -			if (a === b) {
  1.1138 -				return true; // catch the most you can
  1.1139 -			} else if (a === null || b === null || typeof a === "undefined"
  1.1140 -					|| typeof b === "undefined"
  1.1141 -					|| QUnit.objectType(a) !== QUnit.objectType(b)) {
  1.1142 -				return false; // don't lose time with error prone cases
  1.1143 -			} else {
  1.1144 -				return bindCallbacks(a, callbacks, [ b, a ]);
  1.1145 -			}
  1.1146 -
  1.1147 -			// apply transition with (1..n) arguments
  1.1148 -		})(args[0], args[1])
  1.1149 -				&& arguments.callee.apply(this, args.splice(1,
  1.1150 -						args.length - 1));
  1.1151 -	};
  1.1152 -
  1.1153 -	return innerEquiv;
  1.1154 -
  1.1155 -}();
  1.1156 -
  1.1157 -/**
  1.1158 - * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
  1.1159 - * http://flesler.blogspot.com Licensed under BSD
  1.1160 - * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
  1.1161 - *
  1.1162 - * @projectDescription Advanced and extensible data dumping for Javascript.
  1.1163 - * @version 1.0.0
  1.1164 - * @author Ariel Flesler
  1.1165 - * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
  1.1166 - */
  1.1167 -QUnit.jsDump = (function() {
  1.1168 -	function quote( str ) {
  1.1169 -		return '"' + str.toString().replace(/"/g, '\\"') + '"';
  1.1170 -	};
  1.1171 -	function literal( o ) {
  1.1172 -		return o + '';
  1.1173 -	};
  1.1174 -	function join( pre, arr, post ) {
  1.1175 -		var s = jsDump.separator(),
  1.1176 -			base = jsDump.indent(),
  1.1177 -			inner = jsDump.indent(1);
  1.1178 -		if ( arr.join )
  1.1179 -			arr = arr.join( ',' + s + inner );
  1.1180 -		if ( !arr )
  1.1181 -			return pre + post;
  1.1182 -		return [ pre, inner + arr, base + post ].join(s);
  1.1183 -	};
  1.1184 -	function array( arr, stack ) {
  1.1185 -		var i = arr.length, ret = Array(i);
  1.1186 -		this.up();
  1.1187 -		while ( i-- )
  1.1188 -			ret[i] = this.parse( arr[i] , undefined , stack);
  1.1189 -		this.down();
  1.1190 -		return join( '[', ret, ']' );
  1.1191 -	};
  1.1192 -
  1.1193 -	var reName = /^function (\w+)/;
  1.1194 -
  1.1195 -	var jsDump = {
  1.1196 -		parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
  1.1197 -			stack = stack || [ ];
  1.1198 -			var parser = this.parsers[ type || this.typeOf(obj) ];
  1.1199 -			type = typeof parser;
  1.1200 -			var inStack = inArray(obj, stack);
  1.1201 -			if (inStack != -1) {
  1.1202 -				return 'recursion('+(inStack - stack.length)+')';
  1.1203 -			}
  1.1204 -			//else
  1.1205 -			if (type == 'function')  {
  1.1206 -					stack.push(obj);
  1.1207 -					var res = parser.call( this, obj, stack );
  1.1208 -					stack.pop();
  1.1209 -					return res;
  1.1210 -			}
  1.1211 -			// else
  1.1212 -			return (type == 'string') ? parser : this.parsers.error;
  1.1213 -		},
  1.1214 -		typeOf:function( obj ) {
  1.1215 -			var type;
  1.1216 -			if ( obj === null ) {
  1.1217 -				type = "null";
  1.1218 -			} else if (typeof obj === "undefined") {
  1.1219 -				type = "undefined";
  1.1220 -			} else if (QUnit.is("RegExp", obj)) {
  1.1221 -				type = "regexp";
  1.1222 -			} else if (QUnit.is("Date", obj)) {
  1.1223 -				type = "date";
  1.1224 -			} else if (QUnit.is("Function", obj)) {
  1.1225 -				type = "function";
  1.1226 -			} else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
  1.1227 -				type = "window";
  1.1228 -			} else if (obj.nodeType === 9) {
  1.1229 -				type = "document";
  1.1230 -			} else if (obj.nodeType) {
  1.1231 -				type = "node";
  1.1232 -			} else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
  1.1233 -				type = "array";
  1.1234 -			} else {
  1.1235 -				type = typeof obj;
  1.1236 -			}
  1.1237 -			return type;
  1.1238 -		},
  1.1239 -		separator:function() {
  1.1240 -			return this.multiline ?	this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
  1.1241 -		},
  1.1242 -		indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
  1.1243 -			if ( !this.multiline )
  1.1244 -				return '';
  1.1245 -			var chr = this.indentChar;
  1.1246 -			if ( this.HTML )
  1.1247 -				chr = chr.replace(/\t/g,'   ').replace(/ /g,'&nbsp;');
  1.1248 -			return Array( this._depth_ + (extra||0) ).join(chr);
  1.1249 -		},
  1.1250 -		up:function( a ) {
  1.1251 -			this._depth_ += a || 1;
  1.1252 -		},
  1.1253 -		down:function( a ) {
  1.1254 -			this._depth_ -= a || 1;
  1.1255 -		},
  1.1256 -		setParser:function( name, parser ) {
  1.1257 -			this.parsers[name] = parser;
  1.1258 -		},
  1.1259 -		// The next 3 are exposed so you can use them
  1.1260 -		quote:quote,
  1.1261 -		literal:literal,
  1.1262 -		join:join,
  1.1263 -		//
  1.1264 -		_depth_: 1,
  1.1265 -		// This is the list of parsers, to modify them, use jsDump.setParser
  1.1266 -		parsers:{
  1.1267 -			window: '[Window]',
  1.1268 -			document: '[Document]',
  1.1269 -			error:'[ERROR]', //when no parser is found, shouldn't happen
  1.1270 -			unknown: '[Unknown]',
  1.1271 -			'null':'null',
  1.1272 -			'undefined':'undefined',
  1.1273 -			'function':function( fn ) {
  1.1274 -				var ret = 'function',
  1.1275 -					name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
  1.1276 -				if ( name )
  1.1277 -					ret += ' ' + name;
  1.1278 -				ret += '(';
  1.1279 -
  1.1280 -				ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
  1.1281 -				return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
  1.1282 -			},
  1.1283 -			array: array,
  1.1284 -			nodelist: array,
  1.1285 -			arguments: array,
  1.1286 -			object:function( map, stack ) {
  1.1287 -				var ret = [ ];
  1.1288 -				QUnit.jsDump.up();
  1.1289 -				for ( var key in map ) {
  1.1290 -				    var val = map[key];
  1.1291 -					ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack));
  1.1292 -                }
  1.1293 -				QUnit.jsDump.down();
  1.1294 -				return join( '{', ret, '}' );
  1.1295 -			},
  1.1296 -			node:function( node ) {
  1.1297 -				var open = QUnit.jsDump.HTML ? '&lt;' : '<',
  1.1298 -					close = QUnit.jsDump.HTML ? '&gt;' : '>';
  1.1299 -
  1.1300 -				var tag = node.nodeName.toLowerCase(),
  1.1301 -					ret = open + tag;
  1.1302 -
  1.1303 -				for ( var a in QUnit.jsDump.DOMAttrs ) {
  1.1304 -					var val = node[QUnit.jsDump.DOMAttrs[a]];
  1.1305 -					if ( val )
  1.1306 -						ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
  1.1307 -				}
  1.1308 -				return ret + close + open + '/' + tag + close;
  1.1309 -			},
  1.1310 -			functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
  1.1311 -				var l = fn.length;
  1.1312 -				if ( !l ) return '';
  1.1313 -
  1.1314 -				var args = Array(l);
  1.1315 -				while ( l-- )
  1.1316 -					args[l] = String.fromCharCode(97+l);//97 is 'a'
  1.1317 -				return ' ' + args.join(', ') + ' ';
  1.1318 -			},
  1.1319 -			key:quote, //object calls it internally, the key part of an item in a map
  1.1320 -			functionCode:'[code]', //function calls it internally, it's the content of the function
  1.1321 -			attribute:quote, //node calls it internally, it's an html attribute value
  1.1322 -			string:quote,
  1.1323 -			date:quote,
  1.1324 -			regexp:literal, //regex
  1.1325 -			number:literal,
  1.1326 -			'boolean':literal
  1.1327 -		},
  1.1328 -		DOMAttrs:{//attributes to dump from nodes, name=>realName
  1.1329 -			id:'id',
  1.1330 -			name:'name',
  1.1331 -			'class':'className'
  1.1332 -		},
  1.1333 -		HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
  1.1334 -		indentChar:'  ',//indentation unit
  1.1335 -		multiline:true //if true, items in a collection, are separated by a \n, else just a space.
  1.1336 -	};
  1.1337 -
  1.1338 -	return jsDump;
  1.1339 -})();
  1.1340 -
  1.1341 -// from Sizzle.js
  1.1342 -function getText( elems ) {
  1.1343 -	var ret = "", elem;
  1.1344 -
  1.1345 -	for ( var i = 0; elems[i]; i++ ) {
  1.1346 -		elem = elems[i];
  1.1347 -
  1.1348 -		// Get the text from text nodes and CDATA nodes
  1.1349 -		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
  1.1350 -			ret += elem.nodeValue;
  1.1351 -
  1.1352 -		// Traverse everything else, except comment nodes
  1.1353 -		} else if ( elem.nodeType !== 8 ) {
  1.1354 -			ret += getText( elem.childNodes );
  1.1355 -		}
  1.1356 -	}
  1.1357 -
  1.1358 -	return ret;
  1.1359 -};
  1.1360 -
  1.1361 -//from jquery.js
  1.1362 -function inArray( elem, array ) {
  1.1363 -	if ( array.indexOf ) {
  1.1364 -		return array.indexOf( elem );
  1.1365 -	}
  1.1366 -
  1.1367 -	for ( var i = 0, length = array.length; i < length; i++ ) {
  1.1368 -		if ( array[ i ] === elem ) {
  1.1369 -			return i;
  1.1370 -		}
  1.1371 -	}
  1.1372 -
  1.1373 -	return -1;
  1.1374 -}
  1.1375 -
  1.1376 -/*
  1.1377 - * Javascript Diff Algorithm
  1.1378 - *  By John Resig (http://ejohn.org/)
  1.1379 - *  Modified by Chu Alan "sprite"
  1.1380 - *
  1.1381 - * Released under the MIT license.
  1.1382 - *
  1.1383 - * More Info:
  1.1384 - *  http://ejohn.org/projects/javascript-diff-algorithm/
  1.1385 - *
  1.1386 - * Usage: QUnit.diff(expected, actual)
  1.1387 - *
  1.1388 - * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
  1.1389 - */
  1.1390 -QUnit.diff = (function() {
  1.1391 -	function diff(o, n) {
  1.1392 -		var ns = {};
  1.1393 -		var os = {};
  1.1394 -
  1.1395 -		for (var i = 0; i < n.length; i++) {
  1.1396 -			if (ns[n[i]] == null)
  1.1397 -				ns[n[i]] = {
  1.1398 -					rows: [],
  1.1399 -					o: null
  1.1400 -				};
  1.1401 -			ns[n[i]].rows.push(i);
  1.1402 -		}
  1.1403 -
  1.1404 -		for (var i = 0; i < o.length; i++) {
  1.1405 -			if (os[o[i]] == null)
  1.1406 -				os[o[i]] = {
  1.1407 -					rows: [],
  1.1408 -					n: null
  1.1409 -				};
  1.1410 -			os[o[i]].rows.push(i);
  1.1411 -		}
  1.1412 -
  1.1413 -		for (var i in ns) {
  1.1414 -			if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
  1.1415 -				n[ns[i].rows[0]] = {
  1.1416 -					text: n[ns[i].rows[0]],
  1.1417 -					row: os[i].rows[0]
  1.1418 -				};
  1.1419 -				o[os[i].rows[0]] = {
  1.1420 -					text: o[os[i].rows[0]],
  1.1421 -					row: ns[i].rows[0]
  1.1422 -				};
  1.1423 -			}
  1.1424 -		}
  1.1425 -
  1.1426 -		for (var i = 0; i < n.length - 1; i++) {
  1.1427 -			if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
  1.1428 -			n[i + 1] == o[n[i].row + 1]) {
  1.1429 -				n[i + 1] = {
  1.1430 -					text: n[i + 1],
  1.1431 -					row: n[i].row + 1
  1.1432 -				};
  1.1433 -				o[n[i].row + 1] = {
  1.1434 -					text: o[n[i].row + 1],
  1.1435 -					row: i + 1
  1.1436 -				};
  1.1437 -			}
  1.1438 -		}
  1.1439 -
  1.1440 -		for (var i = n.length - 1; i > 0; i--) {
  1.1441 -			if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
  1.1442 -			n[i - 1] == o[n[i].row - 1]) {
  1.1443 -				n[i - 1] = {
  1.1444 -					text: n[i - 1],
  1.1445 -					row: n[i].row - 1
  1.1446 -				};
  1.1447 -				o[n[i].row - 1] = {
  1.1448 -					text: o[n[i].row - 1],
  1.1449 -					row: i - 1
  1.1450 -				};
  1.1451 -			}
  1.1452 -		}
  1.1453 -
  1.1454 -		return {
  1.1455 -			o: o,
  1.1456 -			n: n
  1.1457 -		};
  1.1458 -	}
  1.1459 -
  1.1460 -	return function(o, n) {
  1.1461 -		o = o.replace(/\s+$/, '');
  1.1462 -		n = n.replace(/\s+$/, '');
  1.1463 -		var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
  1.1464 -
  1.1465 -		var str = "";
  1.1466 -
  1.1467 -		var oSpace = o.match(/\s+/g);
  1.1468 -		if (oSpace == null) {
  1.1469 -			oSpace = [" "];
  1.1470 -		}
  1.1471 -		else {
  1.1472 -			oSpace.push(" ");
  1.1473 -		}
  1.1474 -		var nSpace = n.match(/\s+/g);
  1.1475 -		if (nSpace == null) {
  1.1476 -			nSpace = [" "];
  1.1477 -		}
  1.1478 -		else {
  1.1479 -			nSpace.push(" ");
  1.1480 -		}
  1.1481 -
  1.1482 -		if (out.n.length == 0) {
  1.1483 -			for (var i = 0; i < out.o.length; i++) {
  1.1484 -				str += '<del>' + out.o[i] + oSpace[i] + "</del>";
  1.1485 -			}
  1.1486 -		}
  1.1487 -		else {
  1.1488 -			if (out.n[0].text == null) {
  1.1489 -				for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
  1.1490 -					str += '<del>' + out.o[n] + oSpace[n] + "</del>";
  1.1491 -				}
  1.1492 -			}
  1.1493 -
  1.1494 -			for (var i = 0; i < out.n.length; i++) {
  1.1495 -				if (out.n[i].text == null) {
  1.1496 -					str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
  1.1497 -				}
  1.1498 -				else {
  1.1499 -					var pre = "";
  1.1500 -
  1.1501 -					for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
  1.1502 -						pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
  1.1503 -					}
  1.1504 -					str += " " + out.n[i].text + nSpace[i] + pre;
  1.1505 -				}
  1.1506 -			}
  1.1507 -		}
  1.1508 -
  1.1509 -		return str;
  1.1510 -	};
  1.1511 -})();
  1.1512 -
  1.1513 -})(this);
Impressum Datenschutzerklärung