").html(['
Tests completed in ',
59 | time, ' milliseconds. ',
60 | _config.stats.bad, ' tests of ', _config.stats.all, ' failed.
']
61 | .join(''))
62 | .appendTo("body");
63 | $("#banner").addClass(_config.stats.bad ? "fail" : "pass");
64 | });
65 | }
66 |
67 | function test(name, callback, nowait) {
68 | if(_config.currentModule)
69 | name = _config.currentModule + " module: " + name;
70 |
71 | var filter = location.search.slice(1);
72 | if ( filter && encodeURIComponent(name) != filter )
73 | return;
74 |
75 | synchronize(function() {
76 | _config.Test = [];
77 | try {
78 | callback();
79 | } catch(e) {
80 | if( typeof console != "undefined" && console.error && console.warn ) {
81 | console.error("Test " + name + " died, exception and test follows");
82 | console.error(e);
83 | console.warn(callback.toString());
84 | }
85 | _config.Test.push( [ false, "Died on test #" + (_config.Test.length+1) + ": " + e ] );
86 | //throw e;
87 | }
88 | });
89 | synchronize(function() {
90 | reset();
91 |
92 | // don't output pause tests
93 | if(nowait) return;
94 |
95 | if(_config.expected && _config.expected != _config.Test.length) {
96 | _config.Test.push( [ false, "Expected " + _config.expected + " assertions, but " + _config.Test.length + " were run" ] );
97 | }
98 | _config.expected = null;
99 |
100 | var good = 0, bad = 0;
101 | var ol = document.createElement("ol");
102 | ol.style.display = "none";
103 | var li = "", state = "pass";
104 | for ( var i = 0; i < _config.Test.length; i++ ) {
105 | var li = document.createElement("li");
106 | li.className = _config.Test[i][0] ? "pass" : "fail";
107 | li.innerHTML = _config.Test[i][1];
108 | ol.appendChild( li );
109 |
110 | _config.stats.all++;
111 | if ( !_config.Test[i][0] ) {
112 | state = "fail";
113 | bad++;
114 | _config.stats.bad++;
115 | } else good++;
116 | }
117 |
118 | var li = document.createElement("li");
119 | li.className = state;
120 |
121 | var b = document.createElement("strong");
122 | b.innerHTML = name + "
(" + bad + " , " + good + " , " + _config.Test.length + ") ";
123 | b.onclick = function(){
124 | var n = this.nextSibling;
125 | if ( jQuery.css( n, "display" ) == "none" )
126 | n.style.display = "block";
127 | else
128 | n.style.display = "none";
129 | };
130 | $(b).dblclick(function(event) {
131 | var target = jQuery(event.target).filter("strong").clone();
132 | if ( target.length ) {
133 | target.children().remove();
134 | location.href = location.href.match(/^(.+?)(\?.*)?$/)[1] + "?" + encodeURIComponent($.trim(target.text()));
135 | }
136 | });
137 | li.appendChild( b );
138 | li.appendChild( ol );
139 |
140 | document.getElementById("tests").appendChild( li );
141 | });
142 | }
143 |
144 | // call on start of module test to prepend name to all tests
145 | function module(moduleName) {
146 | _config.currentModule = moduleName;
147 | }
148 |
149 | /**
150 | * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
151 | */
152 | function expect(asserts) {
153 | _config.expected = asserts;
154 | }
155 |
156 | /**
157 | * Resets the test setup. Useful for tests that modify the DOM.
158 | */
159 | function reset() {
160 | document.getElementById('main').innerHTML = _config.fixture;
161 | }
162 |
163 | /**
164 | * Asserts true.
165 | * @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
166 | */
167 | function ok(a, msg) {
168 | _config.Test.push( [ !!a, msg ] );
169 | }
170 |
171 | /**
172 | * Asserts that two arrays are the same
173 | */
174 | function isSet(a, b, msg) {
175 | var ret = true;
176 | if ( a && b && a.length != undefined && a.length == b.length ) {
177 | for ( var i = 0; i < a.length; i++ )
178 | if ( a[i] != b[i] )
179 | ret = false;
180 | } else
181 | ret = false;
182 | if ( !ret )
183 | _config.Test.push( [ ret, msg + " expected: " + serialArray(b) + " result: " + serialArray(a) ] );
184 | else
185 | _config.Test.push( [ ret, msg ] );
186 | }
187 |
188 | /**
189 | * Asserts that two objects are equivalent
190 | */
191 | function isObj(a, b, msg) {
192 | var ret = true;
193 |
194 | if ( a && b ) {
195 | for ( var i in a )
196 | if ( a[i] != b[i] )
197 | ret = false;
198 |
199 | for ( i in b )
200 | if ( a[i] != b[i] )
201 | ret = false;
202 | } else
203 | ret = false;
204 |
205 | _config.Test.push( [ ret, msg ] );
206 | }
207 |
208 | function serialArray( a ) {
209 | var r = [];
210 |
211 | if ( a && a.length )
212 | for ( var i = 0; i < a.length; i++ ) {
213 | var str = a[i].nodeName;
214 | if ( str ) {
215 | str = str.toLowerCase();
216 | if ( a[i].id )
217 | str += "#" + a[i].id;
218 | } else
219 | str = a[i];
220 | r.push( str );
221 | }
222 |
223 | return "[ " + r.join(", ") + " ]"
224 | }
225 |
226 | /**
227 | * Returns an array of elements with the given IDs, eg.
228 | * @example q("main", "foo", "bar")
229 | * @result [
,
, ]
230 | */
231 | function q() {
232 | var r = [];
233 | for ( var i = 0; i < arguments.length; i++ )
234 | r.push( document.getElementById( arguments[i] ) );
235 | return r;
236 | }
237 |
238 | /**
239 | * Asserts that a select matches the given IDs
240 | * @example t("Check for something", "//[a]", ["foo", "baar"]);
241 | * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
242 | */
243 | function t(a,b,c) {
244 | var f = jQuery(b);
245 | var s = "";
246 | for ( var i = 0; i < f.length; i++ )
247 | s += (s && ",") + '"' + f[i].id + '"';
248 | isSet(f, q.apply(q,c), a + " (" + b + ")");
249 | }
250 |
251 | /**
252 | * Add random number to url to stop IE from caching
253 | *
254 | * @example url("data/test.html")
255 | * @result "data/test.html?10538358428943"
256 | *
257 | * @example url("data/test.php?foo=bar")
258 | * @result "data/test.php?foo=bar&10538358345554"
259 | */
260 | function url(value) {
261 | return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
262 | }
263 |
264 | /**
265 | * Checks that the first two arguments are equal, with an optional message.
266 | * Prints out both expected and actual values on failure.
267 | *
268 | * Prefered to ok( expected == actual, message )
269 | *
270 | * @example equals( "Expected 2 characters.", v.formatMessage("Expected {0} characters.", 2) );
271 | *
272 | * @param Object expected
273 | * @param Object actual
274 | * @param String message (optional)
275 | */
276 | function equals(expected, actual, message) {
277 | var result = expected == actual;
278 | message = message || (result ? "okay" : "failed");
279 | _config.Test.push( [ result, result ? message + ": " + expected : message + " expected: " + expected + " actual: " + actual ] );
280 | }
281 |
282 | /**
283 | * Trigger an event on an element.
284 | *
285 | * @example triggerEvent( document.body, "click" );
286 | *
287 | * @param DOMElement elem
288 | * @param String type
289 | */
290 | function triggerEvent( elem, type, event ) {
291 | if ( jQuery.browser.mozilla || jQuery.browser.opera ) {
292 | event = document.createEvent("MouseEvents");
293 | event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
294 | 0, 0, 0, 0, 0, false, false, false, false, 0, null);
295 | elem.dispatchEvent( event );
296 | } else if ( jQuery.browser.msie ) {
297 | elem.fireEvent("on"+type);
298 | }
299 | }
300 |
--------------------------------------------------------------------------------
/test/jquery.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | /*
3 | * jQuery 1.2.2b2 - New Wave Javascript
4 | *
5 | * Copyright (c) 2007 John Resig (jquery.com)
6 | * Dual licensed under the MIT (MIT-LICENSE.txt)
7 | * and GPL (GPL-LICENSE.txt) licenses.
8 | *
9 | * $Date: 2007-12-20 14:36:56 +0100 (Don, 20 Dez 2007) $
10 | * $Rev: 4251 $
11 | */
12 |
13 | // Map over jQuery in case of overwrite
14 | if ( window.jQuery )
15 | var _jQuery = window.jQuery;
16 |
17 | var jQuery = window.jQuery = function( selector, context ) {
18 | // The jQuery object is actually just the init constructor 'enhanced'
19 | return new jQuery.prototype.init( selector, context );
20 | };
21 |
22 | // Map over the $ in case of overwrite
23 | if ( window.$ )
24 | var _$ = window.$;
25 |
26 | // Map the jQuery namespace to the '$' one
27 | window.$ = jQuery;
28 |
29 | // A simple way to check for HTML strings or ID strings
30 | // (both of which we optimize for)
31 | var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
32 |
33 | // Is it a simple selector
34 | var isSimple = /^.[^:#\[\.]*$/;
35 |
36 | jQuery.fn = jQuery.prototype = {
37 | init: function( selector, context ) {
38 | // Make sure that a selection was provided
39 | selector = selector || document;
40 |
41 | // Handle $(DOMElement)
42 | if ( selector.nodeType ) {
43 | this[0] = selector;
44 | this.length = 1;
45 | return this;
46 |
47 | // Handle HTML strings
48 | } else if ( typeof selector == "string" ) {
49 | // Are we dealing with HTML string or an ID?
50 | var match = quickExpr.exec( selector );
51 |
52 | // Verify a match, and that no context was specified for #id
53 | if ( match && (match[1] || !context) ) {
54 |
55 | // HANDLE: $(html) -> $(array)
56 | if ( match[1] )
57 | selector = jQuery.clean( [ match[1] ], context );
58 |
59 | // HANDLE: $("#id")
60 | else {
61 | var elem = document.getElementById( match[3] );
62 |
63 | // Make sure an element was located
64 | if ( elem )
65 | // Handle the case where IE and Opera return items
66 | // by name instead of ID
67 | if ( elem.id != match[3] )
68 | return jQuery().find( selector );
69 |
70 | // Otherwise, we inject the element directly into the jQuery object
71 | else {
72 | this[0] = elem;
73 | this.length = 1;
74 | return this;
75 | }
76 |
77 | else
78 | selector = [];
79 | }
80 |
81 | // HANDLE: $(expr, [context])
82 | // (which is just equivalent to: $(content).find(expr)
83 | } else
84 | return new jQuery( context ).find( selector );
85 |
86 | // HANDLE: $(function)
87 | // Shortcut for document ready
88 | } else if ( jQuery.isFunction( selector ) )
89 | return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
90 |
91 | return this.setArray(
92 | // HANDLE: $(array)
93 | selector.constructor == Array && selector ||
94 |
95 | // HANDLE: $(arraylike)
96 | // Watch for when an array-like object, contains DOM nodes, is passed in as the selector
97 | (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
98 |
99 | // HANDLE: $(*)
100 | [ selector ] );
101 | },
102 |
103 | // The current version of jQuery being used
104 | jquery: "@VERSION",
105 |
106 | // The number of elements contained in the matched element set
107 | size: function() {
108 | return this.length;
109 | },
110 |
111 | // The number of elements contained in the matched element set
112 | length: 0,
113 |
114 | // Get the Nth element in the matched element set OR
115 | // Get the whole matched element set as a clean array
116 | get: function( num ) {
117 | return num == undefined ?
118 |
119 | // Return a 'clean' array
120 | jQuery.makeArray( this ) :
121 |
122 | // Return just the object
123 | this[ num ];
124 | },
125 |
126 | // Take an array of elements and push it onto the stack
127 | // (returning the new matched element set)
128 | pushStack: function( elems ) {
129 | // Build a new jQuery matched element set
130 | var ret = jQuery( elems );
131 |
132 | // Add the old object onto the stack (as a reference)
133 | ret.prevObject = this;
134 |
135 | // Return the newly-formed element set
136 | return ret;
137 | },
138 |
139 | // Force the current matched set of elements to become
140 | // the specified array of elements (destroying the stack in the process)
141 | // You should use pushStack() in order to do this, but maintain the stack
142 | setArray: function( elems ) {
143 | // Resetting the length to 0, then using the native Array push
144 | // is a super-fast way to populate an object with array-like properties
145 | this.length = 0;
146 | Array.prototype.push.apply( this, elems );
147 |
148 | return this;
149 | },
150 |
151 | // Execute a callback for every element in the matched set.
152 | // (You can seed the arguments with an array of args, but this is
153 | // only used internally.)
154 | each: function( callback, args ) {
155 | return jQuery.each( this, callback, args );
156 | },
157 |
158 | // Determine the position of an element within
159 | // the matched set of elements
160 | index: function( elem ) {
161 | var ret = -1;
162 |
163 | // Locate the position of the desired element
164 | this.each(function(i){
165 | if ( this == elem )
166 | ret = i;
167 | });
168 |
169 | return ret;
170 | },
171 |
172 | attr: function( name, value, type ) {
173 | var options = name;
174 |
175 | // Look for the case where we're accessing a style value
176 | if ( name.constructor == String )
177 | if ( value == undefined )
178 | return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
179 |
180 | else {
181 | options = {};
182 | options[ name ] = value;
183 | }
184 |
185 | // Check to see if we're setting style values
186 | return this.each(function(i){
187 | // Set all the styles
188 | for ( name in options )
189 | jQuery.attr(
190 | type ?
191 | this.style :
192 | this,
193 | name, jQuery.prop( this, options[ name ], type, i, name )
194 | );
195 | });
196 | },
197 |
198 | css: function( key, value ) {
199 | // ignore negative width and height values
200 | if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
201 | value = undefined;
202 | return this.attr( key, value, "curCSS" );
203 | },
204 |
205 | text: function( text ) {
206 | if ( typeof text != "object" && text != null )
207 | return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
208 |
209 | var ret = "";
210 |
211 | jQuery.each( text || this, function(){
212 | jQuery.each( this.childNodes, function(){
213 | if ( this.nodeType != 8 )
214 | ret += this.nodeType != 1 ?
215 | this.nodeValue :
216 | jQuery.fn.text( [ this ] );
217 | });
218 | });
219 |
220 | return ret;
221 | },
222 |
223 | wrapAll: function( html ) {
224 | if ( this[0] )
225 | // The elements to wrap the target around
226 | jQuery( html, this[0].ownerDocument )
227 | .clone()
228 | .insertBefore( this[0] )
229 | .map(function(){
230 | var elem = this;
231 |
232 | while ( elem.firstChild )
233 | elem = elem.firstChild;
234 |
235 | return elem;
236 | })
237 | .append(this);
238 |
239 | return this;
240 | },
241 |
242 | wrapInner: function( html ) {
243 | return this.each(function(){
244 | jQuery( this ).contents().wrapAll( html );
245 | });
246 | },
247 |
248 | wrap: function( html ) {
249 | return this.each(function(){
250 | jQuery( this ).wrapAll( html );
251 | });
252 | },
253 |
254 | append: function() {
255 | return this.domManip(arguments, true, false, function(elem){
256 | if (this.nodeType == 1)
257 | this.appendChild( elem );
258 | });
259 | },
260 |
261 | prepend: function() {
262 | return this.domManip(arguments, true, true, function(elem){
263 | if (this.nodeType == 1)
264 | this.insertBefore( elem, this.firstChild );
265 | });
266 | },
267 |
268 | before: function() {
269 | return this.domManip(arguments, false, false, function(elem){
270 | this.parentNode.insertBefore( elem, this );
271 | });
272 | },
273 |
274 | after: function() {
275 | return this.domManip(arguments, false, true, function(elem){
276 | this.parentNode.insertBefore( elem, this.nextSibling );
277 | });
278 | },
279 |
280 | end: function() {
281 | return this.prevObject || jQuery( [] );
282 | },
283 |
284 | find: function( selector ) {
285 | var elems = jQuery.map(this, function(elem){
286 | return jQuery.find( selector, elem );
287 | });
288 |
289 | return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
290 | jQuery.unique( elems ) :
291 | elems );
292 | },
293 |
294 | clone: function( events ) {
295 | // Do the clone
296 | var ret = this.map(function(){
297 | if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
298 | // IE copies events bound via attachEvent when
299 | // using cloneNode. Calling detachEvent on the
300 | // clone will also remove the events from the orignal
301 | // In order to get around this, we use innerHTML.
302 | // Unfortunately, this means some modifications to
303 | // attributes in IE that are actually only stored
304 | // as properties will not be copied (such as the
305 | // the name attribute on an input).
306 | var clone = this.cloneNode(true),
307 | container = document.createElement("div"),
308 | container2 = document.createElement("div");
309 | container.appendChild(clone);
310 | container2.innerHTML = container.innerHTML;
311 | return container2.firstChild;
312 | } else
313 | return this.cloneNode(true);
314 | });
315 |
316 | // Need to set the expando to null on the cloned set if it exists
317 | // removeData doesn't work here, IE removes it from the original as well
318 | // this is primarily for IE but the data expando shouldn't be copied over in any browser
319 | var clone = ret.find("*").andSelf().each(function(){
320 | if ( this[ expando ] != undefined )
321 | this[ expando ] = null;
322 | });
323 |
324 | // Copy the events from the original to the clone
325 | if ( events === true )
326 | this.find("*").andSelf().each(function(i){
327 | var events = jQuery.data( this, "events" );
328 |
329 | for ( var type in events )
330 | for ( var handler in events[ type ] )
331 | jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
332 | });
333 |
334 | // Return the cloned set
335 | return ret;
336 | },
337 |
338 | filter: function( selector ) {
339 | return this.pushStack(
340 | jQuery.isFunction( selector ) &&
341 | jQuery.grep(this, function(elem, i){
342 | return selector.call( elem, i );
343 | }) ||
344 |
345 | jQuery.multiFilter( selector, this ) );
346 | },
347 |
348 | not: function( selector ) {
349 | if ( selector.constructor == String )
350 | // test special case where just one selector is passed in
351 | if ( isSimple.test( selector ) )
352 | return this.pushStack( jQuery.multiFilter( selector, this, true ) );
353 | else
354 | selector = jQuery.multiFilter( selector, this );
355 |
356 | var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
357 | return this.filter(function() {
358 | return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
359 | });
360 | },
361 |
362 | add: function( selector ) {
363 | return !selector ? this : this.pushStack( jQuery.merge(
364 | this.get(),
365 | selector.constructor == String ?
366 | jQuery( selector ).get() :
367 | selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
368 | selector : [selector] ) );
369 | },
370 |
371 | is: function( selector ) {
372 | return selector ?
373 | jQuery.multiFilter( selector, this ).length > 0 :
374 | false;
375 | },
376 |
377 | hasClass: function( selector ) {
378 | return this.is( "." + selector );
379 | },
380 |
381 | val: function( value ) {
382 | if ( value == undefined ) {
383 |
384 | if ( this.length ) {
385 | var elem = this[0];
386 |
387 | // We need to handle select boxes special
388 | if ( jQuery.nodeName( elem, "select" ) ) {
389 | var index = elem.selectedIndex,
390 | values = [],
391 | options = elem.options,
392 | one = elem.type == "select-one";
393 |
394 | // Nothing was selected
395 | if ( index < 0 )
396 | return null;
397 |
398 | // Loop through all the selected options
399 | for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
400 | var option = options[ i ];
401 |
402 | if ( option.selected ) {
403 | // Get the specifc value for the option
404 | value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
405 |
406 | // We don't need an array for one selects
407 | if ( one )
408 | return value;
409 |
410 | // Multi-Selects return an array
411 | values.push( value );
412 | }
413 | }
414 |
415 | return values;
416 |
417 | // Everything else, we just grab the value
418 | } else
419 | return (this[0].value || "").replace(/\r/g, "");
420 |
421 | }
422 |
423 | return undefined;
424 | }
425 |
426 | return this.each(function(){
427 | if ( this.nodeType != 1 )
428 | return;
429 |
430 | if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
431 | this.checked = (jQuery.inArray(this.value, value) >= 0 ||
432 | jQuery.inArray(this.name, value) >= 0);
433 |
434 | else if ( jQuery.nodeName( this, "select" ) ) {
435 | var values = value.constructor == Array ?
436 | value :
437 | [ value ];
438 |
439 | jQuery( "option", this ).each(function(){
440 | this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
441 | jQuery.inArray( this.text, values ) >= 0);
442 | });
443 |
444 | if ( !values.length )
445 | this.selectedIndex = -1;
446 |
447 | } else
448 | this.value = value;
449 | });
450 | },
451 |
452 | html: function( value ) {
453 | return value == undefined ?
454 | (this.length ?
455 | this[0].innerHTML :
456 | null) :
457 | this.empty().append( value );
458 | },
459 |
460 | replaceWith: function( value ) {
461 | return this.after( value ).remove();
462 | },
463 |
464 | eq: function( i ) {
465 | return this.slice( i, i + 1 );
466 | },
467 |
468 | slice: function() {
469 | return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
470 | },
471 |
472 | map: function( callback ) {
473 | return this.pushStack( jQuery.map(this, function(elem, i){
474 | return callback.call( elem, i, elem );
475 | }));
476 | },
477 |
478 | andSelf: function() {
479 | return this.add( this.prevObject );
480 | },
481 |
482 | domManip: function( args, table, reverse, callback ) {
483 | var clone = this.length > 1, elems;
484 |
485 | return this.each(function(){
486 | if ( !elems ) {
487 | elems = jQuery.clean( args, this.ownerDocument );
488 |
489 | if ( reverse )
490 | elems.reverse();
491 | }
492 |
493 | var obj = this;
494 |
495 | if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
496 | obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
497 |
498 | var scripts = jQuery( [] );
499 |
500 | jQuery.each(elems, function(){
501 | var elem = clone ?
502 | jQuery( this ).clone( true )[0] :
503 | this;
504 |
505 | // execute all scripts after the elements have been injected
506 | if ( jQuery.nodeName( elem, "script" ) ) {
507 | scripts = scripts.add( elem );
508 | } else {
509 | // Remove any inner scripts for later evaluation
510 | if ( elem.nodeType == 1 )
511 | scripts = scripts.add( jQuery( "script", elem ).remove() );
512 |
513 | // Inject the elements into the document
514 | callback.call( obj, elem );
515 | }
516 | });
517 |
518 | scripts.each( evalScript );
519 | });
520 | }
521 | };
522 |
523 | // Give the init function the jQuery prototype for later instantiation
524 | jQuery.prototype.init.prototype = jQuery.prototype;
525 |
526 | function evalScript( i, elem ) {
527 | if ( elem.src )
528 | jQuery.ajax({
529 | url: elem.src,
530 | async: false,
531 | dataType: "script"
532 | });
533 |
534 | else
535 | jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
536 |
537 | if ( elem.parentNode )
538 | elem.parentNode.removeChild( elem );
539 | }
540 |
541 | jQuery.extend = jQuery.fn.extend = function() {
542 | // copy reference to target object
543 | var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
544 |
545 | // Handle a deep copy situation
546 | if ( target.constructor == Boolean ) {
547 | deep = target;
548 | target = arguments[1] || {};
549 | // skip the boolean and the target
550 | i = 2;
551 | }
552 |
553 | // Handle case when target is a string or something (possible in deep copy)
554 | if ( typeof target != "object" && typeof target != "function" )
555 | target = {};
556 |
557 | // extend jQuery itself if only one argument is passed
558 | if ( length == 1 ) {
559 | target = this;
560 | i = 0;
561 | }
562 |
563 | for ( ; i < length; i++ )
564 | // Only deal with non-null/undefined values
565 | if ( (options = arguments[ i ]) != null )
566 | // Extend the base object
567 | for ( var name in options ) {
568 | // Prevent never-ending loop
569 | if ( target === options[ name ] )
570 | continue;
571 |
572 | // Recurse if we're merging object values
573 | if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
574 | target[ name ] = jQuery.extend( target[ name ], options[ name ] );
575 |
576 | // Don't bring in undefined values
577 | else if ( options[ name ] != undefined )
578 | target[ name ] = options[ name ];
579 |
580 | }
581 |
582 | // Return the modified object
583 | return target;
584 | };
585 |
586 | var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
587 |
588 | // exclude the following css properties to add px
589 | var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
590 |
591 | jQuery.extend({
592 | noConflict: function( deep ) {
593 | window.$ = _$;
594 |
595 | if ( deep )
596 | window.jQuery = _jQuery;
597 |
598 | return jQuery;
599 | },
600 |
601 | // This may seem like some crazy code, but trust me when I say that this
602 | // is the only cross-browser way to do this. --John
603 | isFunction: function( fn ) {
604 | return !!fn && typeof fn != "string" && !fn.nodeName &&
605 | fn.constructor != Array && /function/i.test( fn + "" );
606 | },
607 |
608 | // check if an element is in a (or is an) XML document
609 | isXMLDoc: function( elem ) {
610 | return elem.documentElement && !elem.body ||
611 | elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
612 | },
613 |
614 | // Evalulates a script in a global context
615 | globalEval: function( data ) {
616 | data = jQuery.trim( data );
617 |
618 | if ( data ) {
619 | // Inspired by code by Andrea Giammarchi
620 | // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
621 | var head = document.getElementsByTagName("head")[0] || document.documentElement,
622 | script = document.createElement("script");
623 |
624 | script.type = "text/javascript";
625 | if ( jQuery.browser.msie )
626 | script.text = data;
627 | else
628 | script.appendChild( document.createTextNode( data ) );
629 |
630 | head.appendChild( script );
631 | head.removeChild( script );
632 | }
633 | },
634 |
635 | nodeName: function( elem, name ) {
636 | return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
637 | },
638 |
639 | cache: {},
640 |
641 | data: function( elem, name, data ) {
642 | elem = elem == window ?
643 | windowData :
644 | elem;
645 |
646 | var id = elem[ expando ];
647 |
648 | // Compute a unique ID for the element
649 | if ( !id )
650 | id = elem[ expando ] = ++uuid;
651 |
652 | // Only generate the data cache if we're
653 | // trying to access or manipulate it
654 | if ( name && !jQuery.cache[ id ] )
655 | jQuery.cache[ id ] = {};
656 |
657 | // Prevent overriding the named cache with undefined values
658 | if ( data != undefined )
659 | jQuery.cache[ id ][ name ] = data;
660 |
661 | // Return the named cache data, or the ID for the element
662 | return name ?
663 | jQuery.cache[ id ][ name ] :
664 | id;
665 | },
666 |
667 | removeData: function( elem, name ) {
668 | elem = elem == window ?
669 | windowData :
670 | elem;
671 |
672 | var id = elem[ expando ];
673 |
674 | // If we want to remove a specific section of the element's data
675 | if ( name ) {
676 | if ( jQuery.cache[ id ] ) {
677 | // Remove the section of cache data
678 | delete jQuery.cache[ id ][ name ];
679 |
680 | // If we've removed all the data, remove the element's cache
681 | name = "";
682 |
683 | for ( name in jQuery.cache[ id ] )
684 | break;
685 |
686 | if ( !name )
687 | jQuery.removeData( elem );
688 | }
689 |
690 | // Otherwise, we want to remove all of the element's data
691 | } else {
692 | // Clean up the element expando
693 | try {
694 | delete elem[ expando ];
695 | } catch(e){
696 | // IE has trouble directly removing the expando
697 | // but it's ok with using removeAttribute
698 | if ( elem.removeAttribute )
699 | elem.removeAttribute( expando );
700 | }
701 |
702 | // Completely remove the data cache
703 | delete jQuery.cache[ id ];
704 | }
705 | },
706 |
707 | // args is for internal usage only
708 | each: function( object, callback, args ) {
709 | if ( args ) {
710 | if ( object.length == undefined )
711 | for ( var name in object )
712 | callback.apply( object[ name ], args );
713 | else
714 | for ( var i = 0, length = object.length; i < length; i++ )
715 | if ( callback.apply( object[ i ], args ) === false )
716 | break;
717 |
718 | // A special, fast, case for the most common use of each
719 | } else {
720 | if ( object.length == undefined )
721 | for ( var name in object )
722 | callback.call( object[ name ], name, object[ name ] );
723 | else
724 | for ( var i = 0, length = object.length, value = object[0];
725 | i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
726 | }
727 |
728 | return object;
729 | },
730 |
731 | prop: function( elem, value, type, i, name ) {
732 | // Handle executable functions
733 | if ( jQuery.isFunction( value ) )
734 | value = value.call( elem, i );
735 |
736 | // Handle passing in a number to a CSS property
737 | return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
738 | value + "px" :
739 | value;
740 | },
741 |
742 | className: {
743 | // internal only, use addClass("class")
744 | add: function( elem, classNames ) {
745 | jQuery.each((classNames || "").split(/\s+/), function(i, className){
746 | if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
747 | elem.className += (elem.className ? " " : "") + className;
748 | });
749 | },
750 |
751 | // internal only, use removeClass("class")
752 | remove: function( elem, classNames ) {
753 | if (elem.nodeType == 1)
754 | elem.className = classNames != undefined ?
755 | jQuery.grep(elem.className.split(/\s+/), function(className){
756 | return !jQuery.className.has( classNames, className );
757 | }).join(" ") :
758 | "";
759 | },
760 |
761 | // internal only, use is(".class")
762 | has: function( elem, className ) {
763 | return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
764 | }
765 | },
766 |
767 | // A method for quickly swapping in/out CSS properties to get correct calculations
768 | swap: function( elem, options, callback ) {
769 | var old = {};
770 | // Remember the old values, and insert the new ones
771 | for ( var name in options ) {
772 | old[ name ] = elem.style[ name ];
773 | elem.style[ name ] = options[ name ];
774 | }
775 |
776 | callback.call( elem );
777 |
778 | // Revert the old values
779 | for ( var name in options )
780 | elem.style[ name ] = old[ name ];
781 | },
782 |
783 | css: function( elem, name, force ) {
784 | if ( name == "width" || name == "height" ) {
785 | var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
786 |
787 | function getWH() {
788 | val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
789 | var padding = 0, border = 0;
790 | jQuery.each( which, function() {
791 | padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
792 | border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
793 | });
794 | val -= Math.round(padding + border);
795 | }
796 |
797 | if ( jQuery(elem).is(":visible") )
798 | getWH();
799 | else
800 | jQuery.swap( elem, props, getWH );
801 |
802 | return Math.max(0, val);
803 | }
804 |
805 | return jQuery.curCSS( elem, name, force );
806 | },
807 |
808 | curCSS: function( elem, name, force ) {
809 | var ret;
810 |
811 | // A helper method for determining if an element's values are broken
812 | function color( elem ) {
813 | if ( !jQuery.browser.safari )
814 | return false;
815 |
816 | var ret = document.defaultView.getComputedStyle( elem, null );
817 | return !ret || ret.getPropertyValue("color") == "";
818 | }
819 |
820 | // We need to handle opacity special in IE
821 | if ( name == "opacity" && jQuery.browser.msie ) {
822 | ret = jQuery.attr( elem.style, "opacity" );
823 |
824 | return ret == "" ?
825 | "1" :
826 | ret;
827 | }
828 | // Opera sometimes will give the wrong display answer, this fixes it, see #2037
829 | if ( jQuery.browser.opera && name == "display" ) {
830 | var save = elem.style.display;
831 | elem.style.display = "block";
832 | elem.style.display = save;
833 | }
834 |
835 | // Make sure we're using the right name for getting the float value
836 | if ( name.match( /float/i ) )
837 | name = styleFloat;
838 |
839 | if ( !force && elem.style[ name ] )
840 | ret = elem.style[ name ];
841 |
842 | else if ( document.defaultView && document.defaultView.getComputedStyle ) {
843 |
844 | // Only "float" is needed here
845 | if ( name.match( /float/i ) )
846 | name = "float";
847 |
848 | name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
849 |
850 | var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
851 |
852 | if ( getComputedStyle && !color( elem ) )
853 | ret = getComputedStyle.getPropertyValue( name );
854 |
855 | // If the element isn't reporting its values properly in Safari
856 | // then some display: none elements are involved
857 | else {
858 | var swap = [], stack = [];
859 |
860 | // Locate all of the parent display: none elements
861 | for ( var a = elem; a && color(a); a = a.parentNode )
862 | stack.unshift(a);
863 |
864 | // Go through and make them visible, but in reverse
865 | // (It would be better if we knew the exact display type that they had)
866 | for ( var i = 0; i < stack.length; i++ )
867 | if ( color( stack[ i ] ) ) {
868 | swap[ i ] = stack[ i ].style.display;
869 | stack[ i ].style.display = "block";
870 | }
871 |
872 | // Since we flip the display style, we have to handle that
873 | // one special, otherwise get the value
874 | ret = name == "display" && swap[ stack.length - 1 ] != null ?
875 | "none" :
876 | ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
877 |
878 | // Finally, revert the display styles back
879 | for ( var i = 0; i < swap.length; i++ )
880 | if ( swap[ i ] != null )
881 | stack[ i ].style.display = swap[ i ];
882 | }
883 |
884 | // We should always get a number back from opacity
885 | if ( name == "opacity" && ret == "" )
886 | ret = "1";
887 |
888 | } else if ( elem.currentStyle ) {
889 | var camelCase = name.replace(/\-(\w)/g, function(all, letter){
890 | return letter.toUpperCase();
891 | });
892 |
893 | ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
894 |
895 | // From the awesome hack by Dean Edwards
896 | // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
897 |
898 | // If we're not dealing with a regular pixel number
899 | // but a number that has a weird ending, we need to convert it to pixels
900 | if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
901 | // Remember the original values
902 | var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
903 |
904 | // Put in the new values to get a computed value out
905 | elem.runtimeStyle.left = elem.currentStyle.left;
906 | elem.style.left = ret || 0;
907 | ret = elem.style.pixelLeft + "px";
908 |
909 | // Revert the changed values
910 | elem.style.left = style;
911 | elem.runtimeStyle.left = runtimeStyle;
912 | }
913 | }
914 |
915 | return ret;
916 | },
917 |
918 | clean: function( elems, context ) {
919 | var ret = [];
920 | context = context || document;
921 | // !context.createElement fails in IE with an error but returns typeof 'object'
922 | if (typeof context.createElement == 'undefined')
923 | context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
924 |
925 | jQuery.each(elems, function(i, elem){
926 | if ( !elem )
927 | return;
928 |
929 | if ( elem.constructor == Number )
930 | elem = elem.toString();
931 |
932 | // Convert html string into DOM nodes
933 | if ( typeof elem == "string" ) {
934 | // Fix "XHTML"-style tags in all browsers
935 | elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
936 | return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i) ?
937 | all :
938 | front + ">" + tag + ">";
939 | });
940 |
941 | // Trim whitespace, otherwise indexOf won't work as expected
942 | var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
943 |
944 | var wrap =
945 | // option or optgroup
946 | !tags.indexOf("", "" ] ||
948 |
949 | !tags.indexOf("", "" ] ||
951 |
952 | tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
953 | [ 1, "" ] ||
954 |
955 | !tags.indexOf("", " " ] ||
957 |
958 | // matched above
959 | (!tags.indexOf(" ", " " ] ||
961 |
962 | !tags.indexOf("", " " ] ||
964 |
965 | // IE can't serialize and