Mercurial > public > sg101
comparison media/js/jquery-autocomplete/lib/jquery.js @ 45:a5b4c5ce0658
Breaking down and controlling all media files, including javascript libraries.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Fri, 19 Jun 2009 03:16:03 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
44:08cd19c1ee50 | 45:a5b4c5ce0658 |
---|---|
1 (function(){ | |
2 /* | |
3 * jQuery 1.2.6 - New Wave Javascript | |
4 * | |
5 * Copyright (c) 2008 John Resig (jquery.com) | |
6 * Dual licensed under the MIT (MIT-LICENSE.txt) | |
7 * and GPL (GPL-LICENSE.txt) licenses. | |
8 * | |
9 * $Date: 2008-05-27 21:17:26 +0200 (Di, 27 Mai 2008) $ | |
10 * $Rev: 5700 $ | |
11 */ | |
12 | |
13 // Map over jQuery in case of overwrite | |
14 var _jQuery = window.jQuery, | |
15 // Map over the $ in case of overwrite | |
16 _$ = window.$; | |
17 | |
18 var jQuery = window.jQuery = window.$ = function( selector, context ) { | |
19 // The jQuery object is actually just the init constructor 'enhanced' | |
20 return new jQuery.fn.init( selector, context ); | |
21 }; | |
22 | |
23 // A simple way to check for HTML strings or ID strings | |
24 // (both of which we optimize for) | |
25 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/, | |
26 | |
27 // Is it a simple selector | |
28 isSimple = /^.[^:#\[\.]*$/, | |
29 | |
30 // Will speed up references to undefined, and allows munging its name. | |
31 undefined; | |
32 | |
33 jQuery.fn = jQuery.prototype = { | |
34 init: function( selector, context ) { | |
35 // Make sure that a selection was provided | |
36 selector = selector || document; | |
37 | |
38 // Handle $(DOMElement) | |
39 if ( selector.nodeType ) { | |
40 this[0] = selector; | |
41 this.length = 1; | |
42 return this; | |
43 } | |
44 // Handle HTML strings | |
45 if ( typeof selector == "string" ) { | |
46 // Are we dealing with HTML string or an ID? | |
47 var match = quickExpr.exec( selector ); | |
48 | |
49 // Verify a match, and that no context was specified for #id | |
50 if ( match && (match[1] || !context) ) { | |
51 | |
52 // HANDLE: $(html) -> $(array) | |
53 if ( match[1] ) | |
54 selector = jQuery.clean( [ match[1] ], context ); | |
55 | |
56 // HANDLE: $("#id") | |
57 else { | |
58 var elem = document.getElementById( match[3] ); | |
59 | |
60 // Make sure an element was located | |
61 if ( elem ){ | |
62 // Handle the case where IE and Opera return items | |
63 // by name instead of ID | |
64 if ( elem.id != match[3] ) | |
65 return jQuery().find( selector ); | |
66 | |
67 // Otherwise, we inject the element directly into the jQuery object | |
68 return jQuery( elem ); | |
69 } | |
70 selector = []; | |
71 } | |
72 | |
73 // HANDLE: $(expr, [context]) | |
74 // (which is just equivalent to: $(content).find(expr) | |
75 } else | |
76 return jQuery( context ).find( selector ); | |
77 | |
78 // HANDLE: $(function) | |
79 // Shortcut for document ready | |
80 } else if ( jQuery.isFunction( selector ) ) | |
81 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); | |
82 | |
83 return this.setArray(jQuery.makeArray(selector)); | |
84 }, | |
85 | |
86 // The current version of jQuery being used | |
87 jquery: "1.2.6", | |
88 | |
89 // The number of elements contained in the matched element set | |
90 size: function() { | |
91 return this.length; | |
92 }, | |
93 | |
94 // The number of elements contained in the matched element set | |
95 length: 0, | |
96 | |
97 // Get the Nth element in the matched element set OR | |
98 // Get the whole matched element set as a clean array | |
99 get: function( num ) { | |
100 return num == undefined ? | |
101 | |
102 // Return a 'clean' array | |
103 jQuery.makeArray( this ) : | |
104 | |
105 // Return just the object | |
106 this[ num ]; | |
107 }, | |
108 | |
109 // Take an array of elements and push it onto the stack | |
110 // (returning the new matched element set) | |
111 pushStack: function( elems ) { | |
112 // Build a new jQuery matched element set | |
113 var ret = jQuery( elems ); | |
114 | |
115 // Add the old object onto the stack (as a reference) | |
116 ret.prevObject = this; | |
117 | |
118 // Return the newly-formed element set | |
119 return ret; | |
120 }, | |
121 | |
122 // Force the current matched set of elements to become | |
123 // the specified array of elements (destroying the stack in the process) | |
124 // You should use pushStack() in order to do this, but maintain the stack | |
125 setArray: function( elems ) { | |
126 // Resetting the length to 0, then using the native Array push | |
127 // is a super-fast way to populate an object with array-like properties | |
128 this.length = 0; | |
129 Array.prototype.push.apply( this, elems ); | |
130 | |
131 return this; | |
132 }, | |
133 | |
134 // Execute a callback for every element in the matched set. | |
135 // (You can seed the arguments with an array of args, but this is | |
136 // only used internally.) | |
137 each: function( callback, args ) { | |
138 return jQuery.each( this, callback, args ); | |
139 }, | |
140 | |
141 // Determine the position of an element within | |
142 // the matched set of elements | |
143 index: function( elem ) { | |
144 var ret = -1; | |
145 | |
146 // Locate the position of the desired element | |
147 return jQuery.inArray( | |
148 // If it receives a jQuery object, the first element is used | |
149 elem && elem.jquery ? elem[0] : elem | |
150 , this ); | |
151 }, | |
152 | |
153 attr: function( name, value, type ) { | |
154 var options = name; | |
155 | |
156 // Look for the case where we're accessing a style value | |
157 if ( name.constructor == String ) | |
158 if ( value === undefined ) | |
159 return this[0] && jQuery[ type || "attr" ]( this[0], name ); | |
160 | |
161 else { | |
162 options = {}; | |
163 options[ name ] = value; | |
164 } | |
165 | |
166 // Check to see if we're setting style values | |
167 return this.each(function(i){ | |
168 // Set all the styles | |
169 for ( name in options ) | |
170 jQuery.attr( | |
171 type ? | |
172 this.style : | |
173 this, | |
174 name, jQuery.prop( this, options[ name ], type, i, name ) | |
175 ); | |
176 }); | |
177 }, | |
178 | |
179 css: function( key, value ) { | |
180 // ignore negative width and height values | |
181 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) | |
182 value = undefined; | |
183 return this.attr( key, value, "curCSS" ); | |
184 }, | |
185 | |
186 text: function( text ) { | |
187 if ( typeof text != "object" && text != null ) | |
188 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); | |
189 | |
190 var ret = ""; | |
191 | |
192 jQuery.each( text || this, function(){ | |
193 jQuery.each( this.childNodes, function(){ | |
194 if ( this.nodeType != 8 ) | |
195 ret += this.nodeType != 1 ? | |
196 this.nodeValue : | |
197 jQuery.fn.text( [ this ] ); | |
198 }); | |
199 }); | |
200 | |
201 return ret; | |
202 }, | |
203 | |
204 wrapAll: function( html ) { | |
205 if ( this[0] ) | |
206 // The elements to wrap the target around | |
207 jQuery( html, this[0].ownerDocument ) | |
208 .clone() | |
209 .insertBefore( this[0] ) | |
210 .map(function(){ | |
211 var elem = this; | |
212 | |
213 while ( elem.firstChild ) | |
214 elem = elem.firstChild; | |
215 | |
216 return elem; | |
217 }) | |
218 .append(this); | |
219 | |
220 return this; | |
221 }, | |
222 | |
223 wrapInner: function( html ) { | |
224 return this.each(function(){ | |
225 jQuery( this ).contents().wrapAll( html ); | |
226 }); | |
227 }, | |
228 | |
229 wrap: function( html ) { | |
230 return this.each(function(){ | |
231 jQuery( this ).wrapAll( html ); | |
232 }); | |
233 }, | |
234 | |
235 append: function() { | |
236 return this.domManip(arguments, true, false, function(elem){ | |
237 if (this.nodeType == 1) | |
238 this.appendChild( elem ); | |
239 }); | |
240 }, | |
241 | |
242 prepend: function() { | |
243 return this.domManip(arguments, true, true, function(elem){ | |
244 if (this.nodeType == 1) | |
245 this.insertBefore( elem, this.firstChild ); | |
246 }); | |
247 }, | |
248 | |
249 before: function() { | |
250 return this.domManip(arguments, false, false, function(elem){ | |
251 this.parentNode.insertBefore( elem, this ); | |
252 }); | |
253 }, | |
254 | |
255 after: function() { | |
256 return this.domManip(arguments, false, true, function(elem){ | |
257 this.parentNode.insertBefore( elem, this.nextSibling ); | |
258 }); | |
259 }, | |
260 | |
261 end: function() { | |
262 return this.prevObject || jQuery( [] ); | |
263 }, | |
264 | |
265 find: function( selector ) { | |
266 var elems = jQuery.map(this, function(elem){ | |
267 return jQuery.find( selector, elem ); | |
268 }); | |
269 | |
270 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? | |
271 jQuery.unique( elems ) : | |
272 elems ); | |
273 }, | |
274 | |
275 clone: function( events ) { | |
276 // Do the clone | |
277 var ret = this.map(function(){ | |
278 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { | |
279 // IE copies events bound via attachEvent when | |
280 // using cloneNode. Calling detachEvent on the | |
281 // clone will also remove the events from the orignal | |
282 // In order to get around this, we use innerHTML. | |
283 // Unfortunately, this means some modifications to | |
284 // attributes in IE that are actually only stored | |
285 // as properties will not be copied (such as the | |
286 // the name attribute on an input). | |
287 var clone = this.cloneNode(true), | |
288 container = document.createElement("div"); | |
289 container.appendChild(clone); | |
290 return jQuery.clean([container.innerHTML])[0]; | |
291 } else | |
292 return this.cloneNode(true); | |
293 }); | |
294 | |
295 // Need to set the expando to null on the cloned set if it exists | |
296 // removeData doesn't work here, IE removes it from the original as well | |
297 // this is primarily for IE but the data expando shouldn't be copied over in any browser | |
298 var clone = ret.find("*").andSelf().each(function(){ | |
299 if ( this[ expando ] != undefined ) | |
300 this[ expando ] = null; | |
301 }); | |
302 | |
303 // Copy the events from the original to the clone | |
304 if ( events === true ) | |
305 this.find("*").andSelf().each(function(i){ | |
306 if (this.nodeType == 3) | |
307 return; | |
308 var events = jQuery.data( this, "events" ); | |
309 | |
310 for ( var type in events ) | |
311 for ( var handler in events[ type ] ) | |
312 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); | |
313 }); | |
314 | |
315 // Return the cloned set | |
316 return ret; | |
317 }, | |
318 | |
319 filter: function( selector ) { | |
320 return this.pushStack( | |
321 jQuery.isFunction( selector ) && | |
322 jQuery.grep(this, function(elem, i){ | |
323 return selector.call( elem, i ); | |
324 }) || | |
325 | |
326 jQuery.multiFilter( selector, this ) ); | |
327 }, | |
328 | |
329 not: function( selector ) { | |
330 if ( selector.constructor == String ) | |
331 // test special case where just one selector is passed in | |
332 if ( isSimple.test( selector ) ) | |
333 return this.pushStack( jQuery.multiFilter( selector, this, true ) ); | |
334 else | |
335 selector = jQuery.multiFilter( selector, this ); | |
336 | |
337 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; | |
338 return this.filter(function() { | |
339 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; | |
340 }); | |
341 }, | |
342 | |
343 add: function( selector ) { | |
344 return this.pushStack( jQuery.unique( jQuery.merge( | |
345 this.get(), | |
346 typeof selector == 'string' ? | |
347 jQuery( selector ) : | |
348 jQuery.makeArray( selector ) | |
349 ))); | |
350 }, | |
351 | |
352 is: function( selector ) { | |
353 return !!selector && jQuery.multiFilter( selector, this ).length > 0; | |
354 }, | |
355 | |
356 hasClass: function( selector ) { | |
357 return this.is( "." + selector ); | |
358 }, | |
359 | |
360 val: function( value ) { | |
361 if ( value == undefined ) { | |
362 | |
363 if ( this.length ) { | |
364 var elem = this[0]; | |
365 | |
366 // We need to handle select boxes special | |
367 if ( jQuery.nodeName( elem, "select" ) ) { | |
368 var index = elem.selectedIndex, | |
369 values = [], | |
370 options = elem.options, | |
371 one = elem.type == "select-one"; | |
372 | |
373 // Nothing was selected | |
374 if ( index < 0 ) | |
375 return null; | |
376 | |
377 // Loop through all the selected options | |
378 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { | |
379 var option = options[ i ]; | |
380 | |
381 if ( option.selected ) { | |
382 // Get the specifc value for the option | |
383 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; | |
384 | |
385 // We don't need an array for one selects | |
386 if ( one ) | |
387 return value; | |
388 | |
389 // Multi-Selects return an array | |
390 values.push( value ); | |
391 } | |
392 } | |
393 | |
394 return values; | |
395 | |
396 // Everything else, we just grab the value | |
397 } else | |
398 return (this[0].value || "").replace(/\r/g, ""); | |
399 | |
400 } | |
401 | |
402 return undefined; | |
403 } | |
404 | |
405 if( value.constructor == Number ) | |
406 value += ''; | |
407 | |
408 return this.each(function(){ | |
409 if ( this.nodeType != 1 ) | |
410 return; | |
411 | |
412 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) | |
413 this.checked = (jQuery.inArray(this.value, value) >= 0 || | |
414 jQuery.inArray(this.name, value) >= 0); | |
415 | |
416 else if ( jQuery.nodeName( this, "select" ) ) { | |
417 var values = jQuery.makeArray(value); | |
418 | |
419 jQuery( "option", this ).each(function(){ | |
420 this.selected = (jQuery.inArray( this.value, values ) >= 0 || | |
421 jQuery.inArray( this.text, values ) >= 0); | |
422 }); | |
423 | |
424 if ( !values.length ) | |
425 this.selectedIndex = -1; | |
426 | |
427 } else | |
428 this.value = value; | |
429 }); | |
430 }, | |
431 | |
432 html: function( value ) { | |
433 return value == undefined ? | |
434 (this[0] ? | |
435 this[0].innerHTML : | |
436 null) : | |
437 this.empty().append( value ); | |
438 }, | |
439 | |
440 replaceWith: function( value ) { | |
441 return this.after( value ).remove(); | |
442 }, | |
443 | |
444 eq: function( i ) { | |
445 return this.slice( i, i + 1 ); | |
446 }, | |
447 | |
448 slice: function() { | |
449 return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); | |
450 }, | |
451 | |
452 map: function( callback ) { | |
453 return this.pushStack( jQuery.map(this, function(elem, i){ | |
454 return callback.call( elem, i, elem ); | |
455 })); | |
456 }, | |
457 | |
458 andSelf: function() { | |
459 return this.add( this.prevObject ); | |
460 }, | |
461 | |
462 data: function( key, value ){ | |
463 var parts = key.split("."); | |
464 parts[1] = parts[1] ? "." + parts[1] : ""; | |
465 | |
466 if ( value === undefined ) { | |
467 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); | |
468 | |
469 if ( data === undefined && this.length ) | |
470 data = jQuery.data( this[0], key ); | |
471 | |
472 return data === undefined && parts[1] ? | |
473 this.data( parts[0] ) : | |
474 data; | |
475 } else | |
476 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ | |
477 jQuery.data( this, key, value ); | |
478 }); | |
479 }, | |
480 | |
481 removeData: function( key ){ | |
482 return this.each(function(){ | |
483 jQuery.removeData( this, key ); | |
484 }); | |
485 }, | |
486 | |
487 domManip: function( args, table, reverse, callback ) { | |
488 var clone = this.length > 1, elems; | |
489 | |
490 return this.each(function(){ | |
491 if ( !elems ) { | |
492 elems = jQuery.clean( args, this.ownerDocument ); | |
493 | |
494 if ( reverse ) | |
495 elems.reverse(); | |
496 } | |
497 | |
498 var obj = this; | |
499 | |
500 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) | |
501 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); | |
502 | |
503 var scripts = jQuery( [] ); | |
504 | |
505 jQuery.each(elems, function(){ | |
506 var elem = clone ? | |
507 jQuery( this ).clone( true )[0] : | |
508 this; | |
509 | |
510 // execute all scripts after the elements have been injected | |
511 if ( jQuery.nodeName( elem, "script" ) ) | |
512 scripts = scripts.add( elem ); | |
513 else { | |
514 // Remove any inner scripts for later evaluation | |
515 if ( elem.nodeType == 1 ) | |
516 scripts = scripts.add( jQuery( "script", elem ).remove() ); | |
517 | |
518 // Inject the elements into the document | |
519 callback.call( obj, elem ); | |
520 } | |
521 }); | |
522 | |
523 scripts.each( evalScript ); | |
524 }); | |
525 } | |
526 }; | |
527 | |
528 // Give the init function the jQuery prototype for later instantiation | |
529 jQuery.fn.init.prototype = jQuery.fn; | |
530 | |
531 function evalScript( i, elem ) { | |
532 if ( elem.src ) | |
533 jQuery.ajax({ | |
534 url: elem.src, | |
535 async: false, | |
536 dataType: "script" | |
537 }); | |
538 | |
539 else | |
540 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); | |
541 | |
542 if ( elem.parentNode ) | |
543 elem.parentNode.removeChild( elem ); | |
544 } | |
545 | |
546 function now(){ | |
547 return +new Date; | |
548 } | |
549 | |
550 jQuery.extend = jQuery.fn.extend = function() { | |
551 // copy reference to target object | |
552 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; | |
553 | |
554 // Handle a deep copy situation | |
555 if ( target.constructor == Boolean ) { | |
556 deep = target; | |
557 target = arguments[1] || {}; | |
558 // skip the boolean and the target | |
559 i = 2; | |
560 } | |
561 | |
562 // Handle case when target is a string or something (possible in deep copy) | |
563 if ( typeof target != "object" && typeof target != "function" ) | |
564 target = {}; | |
565 | |
566 // extend jQuery itself if only one argument is passed | |
567 if ( length == i ) { | |
568 target = this; | |
569 --i; | |
570 } | |
571 | |
572 for ( ; i < length; i++ ) | |
573 // Only deal with non-null/undefined values | |
574 if ( (options = arguments[ i ]) != null ) | |
575 // Extend the base object | |
576 for ( var name in options ) { | |
577 var src = target[ name ], copy = options[ name ]; | |
578 | |
579 // Prevent never-ending loop | |
580 if ( target === copy ) | |
581 continue; | |
582 | |
583 // Recurse if we're merging object values | |
584 if ( deep && copy && typeof copy == "object" && !copy.nodeType ) | |
585 target[ name ] = jQuery.extend( deep, | |
586 // Never move original objects, clone them | |
587 src || ( copy.length != null ? [ ] : { } ) | |
588 , copy ); | |
589 | |
590 // Don't bring in undefined values | |
591 else if ( copy !== undefined ) | |
592 target[ name ] = copy; | |
593 | |
594 } | |
595 | |
596 // Return the modified object | |
597 return target; | |
598 }; | |
599 | |
600 var expando = "jQuery" + now(), uuid = 0, windowData = {}, | |
601 // exclude the following css properties to add px | |
602 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, | |
603 // cache defaultView | |
604 defaultView = document.defaultView || {}; | |
605 | |
606 jQuery.extend({ | |
607 noConflict: function( deep ) { | |
608 window.$ = _$; | |
609 | |
610 if ( deep ) | |
611 window.jQuery = _jQuery; | |
612 | |
613 return jQuery; | |
614 }, | |
615 | |
616 // See test/unit/core.js for details concerning this function. | |
617 isFunction: function( fn ) { | |
618 return !!fn && typeof fn != "string" && !fn.nodeName && | |
619 fn.constructor != Array && /^[\s[]?function/.test( fn + "" ); | |
620 }, | |
621 | |
622 // check if an element is in a (or is an) XML document | |
623 isXMLDoc: function( elem ) { | |
624 return elem.documentElement && !elem.body || | |
625 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; | |
626 }, | |
627 | |
628 // Evalulates a script in a global context | |
629 globalEval: function( data ) { | |
630 data = jQuery.trim( data ); | |
631 | |
632 if ( data ) { | |
633 // Inspired by code by Andrea Giammarchi | |
634 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html | |
635 var head = document.getElementsByTagName("head")[0] || document.documentElement, | |
636 script = document.createElement("script"); | |
637 | |
638 script.type = "text/javascript"; | |
639 if ( jQuery.browser.msie ) | |
640 script.text = data; | |
641 else | |
642 script.appendChild( document.createTextNode( data ) ); | |
643 | |
644 // Use insertBefore instead of appendChild to circumvent an IE6 bug. | |
645 // This arises when a base node is used (#2709). | |
646 head.insertBefore( script, head.firstChild ); | |
647 head.removeChild( script ); | |
648 } | |
649 }, | |
650 | |
651 nodeName: function( elem, name ) { | |
652 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); | |
653 }, | |
654 | |
655 cache: {}, | |
656 | |
657 data: function( elem, name, data ) { | |
658 elem = elem == window ? | |
659 windowData : | |
660 elem; | |
661 | |
662 var id = elem[ expando ]; | |
663 | |
664 // Compute a unique ID for the element | |
665 if ( !id ) | |
666 id = elem[ expando ] = ++uuid; | |
667 | |
668 // Only generate the data cache if we're | |
669 // trying to access or manipulate it | |
670 if ( name && !jQuery.cache[ id ] ) | |
671 jQuery.cache[ id ] = {}; | |
672 | |
673 // Prevent overriding the named cache with undefined values | |
674 if ( data !== undefined ) | |
675 jQuery.cache[ id ][ name ] = data; | |
676 | |
677 // Return the named cache data, or the ID for the element | |
678 return name ? | |
679 jQuery.cache[ id ][ name ] : | |
680 id; | |
681 }, | |
682 | |
683 removeData: function( elem, name ) { | |
684 elem = elem == window ? | |
685 windowData : | |
686 elem; | |
687 | |
688 var id = elem[ expando ]; | |
689 | |
690 // If we want to remove a specific section of the element's data | |
691 if ( name ) { | |
692 if ( jQuery.cache[ id ] ) { | |
693 // Remove the section of cache data | |
694 delete jQuery.cache[ id ][ name ]; | |
695 | |
696 // If we've removed all the data, remove the element's cache | |
697 name = ""; | |
698 | |
699 for ( name in jQuery.cache[ id ] ) | |
700 break; | |
701 | |
702 if ( !name ) | |
703 jQuery.removeData( elem ); | |
704 } | |
705 | |
706 // Otherwise, we want to remove all of the element's data | |
707 } else { | |
708 // Clean up the element expando | |
709 try { | |
710 delete elem[ expando ]; | |
711 } catch(e){ | |
712 // IE has trouble directly removing the expando | |
713 // but it's ok with using removeAttribute | |
714 if ( elem.removeAttribute ) | |
715 elem.removeAttribute( expando ); | |
716 } | |
717 | |
718 // Completely remove the data cache | |
719 delete jQuery.cache[ id ]; | |
720 } | |
721 }, | |
722 | |
723 // args is for internal usage only | |
724 each: function( object, callback, args ) { | |
725 var name, i = 0, length = object.length; | |
726 | |
727 if ( args ) { | |
728 if ( length == undefined ) { | |
729 for ( name in object ) | |
730 if ( callback.apply( object[ name ], args ) === false ) | |
731 break; | |
732 } else | |
733 for ( ; i < length; ) | |
734 if ( callback.apply( object[ i++ ], args ) === false ) | |
735 break; | |
736 | |
737 // A special, fast, case for the most common use of each | |
738 } else { | |
739 if ( length == undefined ) { | |
740 for ( name in object ) | |
741 if ( callback.call( object[ name ], name, object[ name ] ) === false ) | |
742 break; | |
743 } else | |
744 for ( var value = object[0]; | |
745 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} | |
746 } | |
747 | |
748 return object; | |
749 }, | |
750 | |
751 prop: function( elem, value, type, i, name ) { | |
752 // Handle executable functions | |
753 if ( jQuery.isFunction( value ) ) | |
754 value = value.call( elem, i ); | |
755 | |
756 // Handle passing in a number to a CSS property | |
757 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? | |
758 value + "px" : | |
759 value; | |
760 }, | |
761 | |
762 className: { | |
763 // internal only, use addClass("class") | |
764 add: function( elem, classNames ) { | |
765 jQuery.each((classNames || "").split(/\s+/), function(i, className){ | |
766 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) | |
767 elem.className += (elem.className ? " " : "") + className; | |
768 }); | |
769 }, | |
770 | |
771 // internal only, use removeClass("class") | |
772 remove: function( elem, classNames ) { | |
773 if (elem.nodeType == 1) | |
774 elem.className = classNames != undefined ? | |
775 jQuery.grep(elem.className.split(/\s+/), function(className){ | |
776 return !jQuery.className.has( classNames, className ); | |
777 }).join(" ") : | |
778 ""; | |
779 }, | |
780 | |
781 // internal only, use hasClass("class") | |
782 has: function( elem, className ) { | |
783 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; | |
784 } | |
785 }, | |
786 | |
787 // A method for quickly swapping in/out CSS properties to get correct calculations | |
788 swap: function( elem, options, callback ) { | |
789 var old = {}; | |
790 // Remember the old values, and insert the new ones | |
791 for ( var name in options ) { | |
792 old[ name ] = elem.style[ name ]; | |
793 elem.style[ name ] = options[ name ]; | |
794 } | |
795 | |
796 callback.call( elem ); | |
797 | |
798 // Revert the old values | |
799 for ( var name in options ) | |
800 elem.style[ name ] = old[ name ]; | |
801 }, | |
802 | |
803 css: function( elem, name, force ) { | |
804 if ( name == "width" || name == "height" ) { | |
805 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; | |
806 | |
807 function getWH() { | |
808 val = name == "width" ? elem.offsetWidth : elem.offsetHeight; | |
809 var padding = 0, border = 0; | |
810 jQuery.each( which, function() { | |
811 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; | |
812 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; | |
813 }); | |
814 val -= Math.round(padding + border); | |
815 } | |
816 | |
817 if ( jQuery(elem).is(":visible") ) | |
818 getWH(); | |
819 else | |
820 jQuery.swap( elem, props, getWH ); | |
821 | |
822 return Math.max(0, val); | |
823 } | |
824 | |
825 return jQuery.curCSS( elem, name, force ); | |
826 }, | |
827 | |
828 curCSS: function( elem, name, force ) { | |
829 var ret, style = elem.style; | |
830 | |
831 // A helper method for determining if an element's values are broken | |
832 function color( elem ) { | |
833 if ( !jQuery.browser.safari ) | |
834 return false; | |
835 | |
836 // defaultView is cached | |
837 var ret = defaultView.getComputedStyle( elem, null ); | |
838 return !ret || ret.getPropertyValue("color") == ""; | |
839 } | |
840 | |
841 // We need to handle opacity special in IE | |
842 if ( name == "opacity" && jQuery.browser.msie ) { | |
843 ret = jQuery.attr( style, "opacity" ); | |
844 | |
845 return ret == "" ? | |
846 "1" : | |
847 ret; | |
848 } | |
849 // Opera sometimes will give the wrong display answer, this fixes it, see #2037 | |
850 if ( jQuery.browser.opera && name == "display" ) { | |
851 var save = style.outline; | |
852 style.outline = "0 solid black"; | |
853 style.outline = save; | |
854 } | |
855 | |
856 // Make sure we're using the right name for getting the float value | |
857 if ( name.match( /float/i ) ) | |
858 name = styleFloat; | |
859 | |
860 if ( !force && style && style[ name ] ) | |
861 ret = style[ name ]; | |
862 | |
863 else if ( defaultView.getComputedStyle ) { | |
864 | |
865 // Only "float" is needed here | |
866 if ( name.match( /float/i ) ) | |
867 name = "float"; | |
868 | |
869 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); | |
870 | |
871 var computedStyle = defaultView.getComputedStyle( elem, null ); | |
872 | |
873 if ( computedStyle && !color( elem ) ) | |
874 ret = computedStyle.getPropertyValue( name ); | |
875 | |
876 // If the element isn't reporting its values properly in Safari | |
877 // then some display: none elements are involved | |
878 else { | |
879 var swap = [], stack = [], a = elem, i = 0; | |
880 | |
881 // Locate all of the parent display: none elements | |
882 for ( ; a && color(a); a = a.parentNode ) | |
883 stack.unshift(a); | |
884 | |
885 // Go through and make them visible, but in reverse | |
886 // (It would be better if we knew the exact display type that they had) | |
887 for ( ; i < stack.length; i++ ) | |
888 if ( color( stack[ i ] ) ) { | |
889 swap[ i ] = stack[ i ].style.display; | |
890 stack[ i ].style.display = "block"; | |
891 } | |
892 | |
893 // Since we flip the display style, we have to handle that | |
894 // one special, otherwise get the value | |
895 ret = name == "display" && swap[ stack.length - 1 ] != null ? | |
896 "none" : | |
897 ( computedStyle && computedStyle.getPropertyValue( name ) ) || ""; | |
898 | |
899 // Finally, revert the display styles back | |
900 for ( i = 0; i < swap.length; i++ ) | |
901 if ( swap[ i ] != null ) | |
902 stack[ i ].style.display = swap[ i ]; | |
903 } | |
904 | |
905 // We should always get a number back from opacity | |
906 if ( name == "opacity" && ret == "" ) | |
907 ret = "1"; | |
908 | |
909 } else if ( elem.currentStyle ) { | |
910 var camelCase = name.replace(/\-(\w)/g, function(all, letter){ | |
911 return letter.toUpperCase(); | |
912 }); | |
913 | |
914 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; | |
915 | |
916 // From the awesome hack by Dean Edwards | |
917 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 | |
918 | |
919 // If we're not dealing with a regular pixel number | |
920 // but a number that has a weird ending, we need to convert it to pixels | |
921 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { | |
922 // Remember the original values | |
923 var left = style.left, rsLeft = elem.runtimeStyle.left; | |
924 | |
925 // Put in the new values to get a computed value out | |
926 elem.runtimeStyle.left = elem.currentStyle.left; | |
927 style.left = ret || 0; | |
928 ret = style.pixelLeft + "px"; | |
929 | |
930 // Revert the changed values | |
931 style.left = left; | |
932 elem.runtimeStyle.left = rsLeft; | |
933 } | |
934 } | |
935 | |
936 return ret; | |
937 }, | |
938 | |
939 clean: function( elems, context ) { | |
940 var ret = []; | |
941 context = context || document; | |
942 // !context.createElement fails in IE with an error but returns typeof 'object' | |
943 if (typeof context.createElement == 'undefined') | |
944 context = context.ownerDocument || context[0] && context[0].ownerDocument || document; | |
945 | |
946 jQuery.each(elems, function(i, elem){ | |
947 if ( !elem ) | |
948 return; | |
949 | |
950 if ( elem.constructor == Number ) | |
951 elem += ''; | |
952 | |
953 // Convert html string into DOM nodes | |
954 if ( typeof elem == "string" ) { | |
955 // Fix "XHTML"-style tags in all browsers | |
956 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ | |
957 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? | |
958 all : | |
959 front + "></" + tag + ">"; | |
960 }); | |
961 | |
962 // Trim whitespace, otherwise indexOf won't work as expected | |
963 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); | |
964 | |
965 var wrap = | |
966 // option or optgroup | |
967 !tags.indexOf("<opt") && | |
968 [ 1, "<select multiple='multiple'>", "</select>" ] || | |
969 | |
970 !tags.indexOf("<leg") && | |
971 [ 1, "<fieldset>", "</fieldset>" ] || | |
972 | |
973 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && | |
974 [ 1, "<table>", "</table>" ] || | |
975 | |
976 !tags.indexOf("<tr") && | |
977 [ 2, "<table><tbody>", "</tbody></table>" ] || | |
978 | |
979 // <thead> matched above | |
980 (!tags.indexOf("<td") || !tags.indexOf("<th")) && | |
981 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || | |
982 | |
983 !tags.indexOf("<col") && | |
984 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || | |
985 | |
986 // IE can't serialize <link> and <script> tags normally | |
987 jQuery.browser.msie && | |
988 [ 1, "div<div>", "</div>" ] || | |
989 | |
990 [ 0, "", "" ]; | |
991 | |
992 // Go to html and back, then peel off extra wrappers | |
993 div.innerHTML = wrap[1] + elem + wrap[2]; | |
994 | |
995 // Move to the right depth | |
996 while ( wrap[0]-- ) | |
997 div = div.lastChild; | |
998 | |
999 // Remove IE's autoinserted <tbody> from table fragments | |
1000 if ( jQuery.browser.msie ) { | |
1001 | |
1002 // String was a <table>, *may* have spurious <tbody> | |
1003 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ? | |
1004 div.firstChild && div.firstChild.childNodes : | |
1005 | |
1006 // String was a bare <thead> or <tfoot> | |
1007 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ? | |
1008 div.childNodes : | |
1009 []; | |
1010 | |
1011 for ( var j = tbody.length - 1; j >= 0 ; --j ) | |
1012 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) | |
1013 tbody[ j ].parentNode.removeChild( tbody[ j ] ); | |
1014 | |
1015 // IE completely kills leading whitespace when innerHTML is used | |
1016 if ( /^\s/.test( elem ) ) | |
1017 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); | |
1018 | |
1019 } | |
1020 | |
1021 elem = jQuery.makeArray( div.childNodes ); | |
1022 } | |
1023 | |
1024 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) ) | |
1025 return; | |
1026 | |
1027 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options ) | |
1028 ret.push( elem ); | |
1029 | |
1030 else | |
1031 ret = jQuery.merge( ret, elem ); | |
1032 | |
1033 }); | |
1034 | |
1035 return ret; | |
1036 }, | |
1037 | |
1038 attr: function( elem, name, value ) { | |
1039 // don't set attributes on text and comment nodes | |
1040 if (!elem || elem.nodeType == 3 || elem.nodeType == 8) | |
1041 return undefined; | |
1042 | |
1043 var notxml = !jQuery.isXMLDoc( elem ), | |
1044 // Whether we are setting (or getting) | |
1045 set = value !== undefined, | |
1046 msie = jQuery.browser.msie; | |
1047 | |
1048 // Try to normalize/fix the name | |
1049 name = notxml && jQuery.props[ name ] || name; | |
1050 | |
1051 // Only do all the following if this is a node (faster for style) | |
1052 // IE elem.getAttribute passes even for style | |
1053 if ( elem.tagName ) { | |
1054 | |
1055 // These attributes require special treatment | |
1056 var special = /href|src|style/.test( name ); | |
1057 | |
1058 // Safari mis-reports the default selected property of a hidden option | |
1059 // Accessing the parent's selectedIndex property fixes it | |
1060 if ( name == "selected" && jQuery.browser.safari ) | |
1061 elem.parentNode.selectedIndex; | |
1062 | |
1063 // If applicable, access the attribute via the DOM 0 way | |
1064 if ( name in elem && notxml && !special ) { | |
1065 if ( set ){ | |
1066 // We can't allow the type property to be changed (since it causes problems in IE) | |
1067 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) | |
1068 throw "type property can't be changed"; | |
1069 | |
1070 elem[ name ] = value; | |
1071 } | |
1072 | |
1073 // browsers index elements by id/name on forms, give priority to attributes. | |
1074 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) | |
1075 return elem.getAttributeNode( name ).nodeValue; | |
1076 | |
1077 return elem[ name ]; | |
1078 } | |
1079 | |
1080 if ( msie && notxml && name == "style" ) | |
1081 return jQuery.attr( elem.style, "cssText", value ); | |
1082 | |
1083 if ( set ) | |
1084 // convert the value to a string (all browsers do this but IE) see #1070 | |
1085 elem.setAttribute( name, "" + value ); | |
1086 | |
1087 var attr = msie && notxml && special | |
1088 // Some attributes require a special call on IE | |
1089 ? elem.getAttribute( name, 2 ) | |
1090 : elem.getAttribute( name ); | |
1091 | |
1092 // Non-existent attributes return null, we normalize to undefined | |
1093 return attr === null ? undefined : attr; | |
1094 } | |
1095 | |
1096 // elem is actually elem.style ... set the style | |
1097 | |
1098 // IE uses filters for opacity | |
1099 if ( msie && name == "opacity" ) { | |
1100 if ( set ) { | |
1101 // IE has trouble with opacity if it does not have layout | |
1102 // Force it by setting the zoom level | |
1103 elem.zoom = 1; | |
1104 | |
1105 // Set the alpha filter to set the opacity | |
1106 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + | |
1107 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); | |
1108 } | |
1109 | |
1110 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? | |
1111 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '': | |
1112 ""; | |
1113 } | |
1114 | |
1115 name = name.replace(/-([a-z])/ig, function(all, letter){ | |
1116 return letter.toUpperCase(); | |
1117 }); | |
1118 | |
1119 if ( set ) | |
1120 elem[ name ] = value; | |
1121 | |
1122 return elem[ name ]; | |
1123 }, | |
1124 | |
1125 trim: function( text ) { | |
1126 return (text || "").replace( /^\s+|\s+$/g, "" ); | |
1127 }, | |
1128 | |
1129 makeArray: function( array ) { | |
1130 var ret = []; | |
1131 | |
1132 if( array != null ){ | |
1133 var i = array.length; | |
1134 //the window, strings and functions also have 'length' | |
1135 if( i == null || array.split || array.setInterval || array.call ) | |
1136 ret[0] = array; | |
1137 else | |
1138 while( i ) | |
1139 ret[--i] = array[i]; | |
1140 } | |
1141 | |
1142 return ret; | |
1143 }, | |
1144 | |
1145 inArray: function( elem, array ) { | |
1146 for ( var i = 0, length = array.length; i < length; i++ ) | |
1147 // Use === because on IE, window == document | |
1148 if ( array[ i ] === elem ) | |
1149 return i; | |
1150 | |
1151 return -1; | |
1152 }, | |
1153 | |
1154 merge: function( first, second ) { | |
1155 // We have to loop this way because IE & Opera overwrite the length | |
1156 // expando of getElementsByTagName | |
1157 var i = 0, elem, pos = first.length; | |
1158 // Also, we need to make sure that the correct elements are being returned | |
1159 // (IE returns comment nodes in a '*' query) | |
1160 if ( jQuery.browser.msie ) { | |
1161 while ( elem = second[ i++ ] ) | |
1162 if ( elem.nodeType != 8 ) | |
1163 first[ pos++ ] = elem; | |
1164 | |
1165 } else | |
1166 while ( elem = second[ i++ ] ) | |
1167 first[ pos++ ] = elem; | |
1168 | |
1169 return first; | |
1170 }, | |
1171 | |
1172 unique: function( array ) { | |
1173 var ret = [], done = {}; | |
1174 | |
1175 try { | |
1176 | |
1177 for ( var i = 0, length = array.length; i < length; i++ ) { | |
1178 var id = jQuery.data( array[ i ] ); | |
1179 | |
1180 if ( !done[ id ] ) { | |
1181 done[ id ] = true; | |
1182 ret.push( array[ i ] ); | |
1183 } | |
1184 } | |
1185 | |
1186 } catch( e ) { | |
1187 ret = array; | |
1188 } | |
1189 | |
1190 return ret; | |
1191 }, | |
1192 | |
1193 grep: function( elems, callback, inv ) { | |
1194 var ret = []; | |
1195 | |
1196 // Go through the array, only saving the items | |
1197 // that pass the validator function | |
1198 for ( var i = 0, length = elems.length; i < length; i++ ) | |
1199 if ( !inv != !callback( elems[ i ], i ) ) | |
1200 ret.push( elems[ i ] ); | |
1201 | |
1202 return ret; | |
1203 }, | |
1204 | |
1205 map: function( elems, callback ) { | |
1206 var ret = []; | |
1207 | |
1208 // Go through the array, translating each of the items to their | |
1209 // new value (or values). | |
1210 for ( var i = 0, length = elems.length; i < length; i++ ) { | |
1211 var value = callback( elems[ i ], i ); | |
1212 | |
1213 if ( value != null ) | |
1214 ret[ ret.length ] = value; | |
1215 } | |
1216 | |
1217 return ret.concat.apply( [], ret ); | |
1218 } | |
1219 }); | |
1220 | |
1221 var userAgent = navigator.userAgent.toLowerCase(); | |
1222 | |
1223 // Figure out what browser is being used | |
1224 jQuery.browser = { | |
1225 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1], | |
1226 safari: /webkit/.test( userAgent ), | |
1227 opera: /opera/.test( userAgent ), | |
1228 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), | |
1229 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) | |
1230 }; | |
1231 | |
1232 var styleFloat = jQuery.browser.msie ? | |
1233 "styleFloat" : | |
1234 "cssFloat"; | |
1235 | |
1236 jQuery.extend({ | |
1237 // Check to see if the W3C box model is being used | |
1238 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat", | |
1239 | |
1240 props: { | |
1241 "for": "htmlFor", | |
1242 "class": "className", | |
1243 "float": styleFloat, | |
1244 cssFloat: styleFloat, | |
1245 styleFloat: styleFloat, | |
1246 readonly: "readOnly", | |
1247 maxlength: "maxLength", | |
1248 cellspacing: "cellSpacing", | |
1249 rowspan: "rowSpan" | |
1250 } | |
1251 }); | |
1252 | |
1253 jQuery.each({ | |
1254 parent: function(elem){return elem.parentNode;}, | |
1255 parents: function(elem){return jQuery.dir(elem,"parentNode");}, | |
1256 next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, | |
1257 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, | |
1258 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, | |
1259 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, | |
1260 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, | |
1261 children: function(elem){return jQuery.sibling(elem.firstChild);}, | |
1262 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} | |
1263 }, function(name, fn){ | |
1264 jQuery.fn[ name ] = function( selector ) { | |
1265 var ret = jQuery.map( this, fn ); | |
1266 | |
1267 if ( selector && typeof selector == "string" ) | |
1268 ret = jQuery.multiFilter( selector, ret ); | |
1269 | |
1270 return this.pushStack( jQuery.unique( ret ) ); | |
1271 }; | |
1272 }); | |
1273 | |
1274 jQuery.each({ | |
1275 appendTo: "append", | |
1276 prependTo: "prepend", | |
1277 insertBefore: "before", | |
1278 insertAfter: "after", | |
1279 replaceAll: "replaceWith" | |
1280 }, function(name, original){ | |
1281 jQuery.fn[ name ] = function() { | |
1282 var args = arguments; | |
1283 | |
1284 return this.each(function(){ | |
1285 for ( var i = 0, length = args.length; i < length; i++ ) | |
1286 jQuery( args[ i ] )[ original ]( this ); | |
1287 }); | |
1288 }; | |
1289 }); | |
1290 | |
1291 jQuery.each({ | |
1292 removeAttr: function( name ) { | |
1293 jQuery.attr( this, name, "" ); | |
1294 if (this.nodeType == 1) | |
1295 this.removeAttribute( name ); | |
1296 }, | |
1297 | |
1298 addClass: function( classNames ) { | |
1299 jQuery.className.add( this, classNames ); | |
1300 }, | |
1301 | |
1302 removeClass: function( classNames ) { | |
1303 jQuery.className.remove( this, classNames ); | |
1304 }, | |
1305 | |
1306 toggleClass: function( classNames ) { | |
1307 jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames ); | |
1308 }, | |
1309 | |
1310 remove: function( selector ) { | |
1311 if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) { | |
1312 // Prevent memory leaks | |
1313 jQuery( "*", this ).add(this).each(function(){ | |
1314 jQuery.event.remove(this); | |
1315 jQuery.removeData(this); | |
1316 }); | |
1317 if (this.parentNode) | |
1318 this.parentNode.removeChild( this ); | |
1319 } | |
1320 }, | |
1321 | |
1322 empty: function() { | |
1323 // Remove element nodes and prevent memory leaks | |
1324 jQuery( ">*", this ).remove(); | |
1325 | |
1326 // Remove any remaining nodes | |
1327 while ( this.firstChild ) | |
1328 this.removeChild( this.firstChild ); | |
1329 } | |
1330 }, function(name, fn){ | |
1331 jQuery.fn[ name ] = function(){ | |
1332 return this.each( fn, arguments ); | |
1333 }; | |
1334 }); | |
1335 | |
1336 jQuery.each([ "Height", "Width" ], function(i, name){ | |
1337 var type = name.toLowerCase(); | |
1338 | |
1339 jQuery.fn[ type ] = function( size ) { | |
1340 // Get window width or height | |
1341 return this[0] == window ? | |
1342 // Opera reports document.body.client[Width/Height] properly in both quirks and standards | |
1343 jQuery.browser.opera && document.body[ "client" + name ] || | |
1344 | |
1345 // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths) | |
1346 jQuery.browser.safari && window[ "inner" + name ] || | |
1347 | |
1348 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode | |
1349 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] : | |
1350 | |
1351 // Get document width or height | |
1352 this[0] == document ? | |
1353 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater | |
1354 Math.max( | |
1355 Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), | |
1356 Math.max(document.body["offset" + name], document.documentElement["offset" + name]) | |
1357 ) : | |
1358 | |
1359 // Get or set width or height on the element | |
1360 size == undefined ? | |
1361 // Get width or height on the element | |
1362 (this.length ? jQuery.css( this[0], type ) : null) : | |
1363 | |
1364 // Set the width or height on the element (default to pixels if value is unitless) | |
1365 this.css( type, size.constructor == String ? size : size + "px" ); | |
1366 }; | |
1367 }); | |
1368 | |
1369 // Helper function used by the dimensions and offset modules | |
1370 function num(elem, prop) { | |
1371 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; | |
1372 }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? | |
1373 "(?:[\\w*_-]|\\\\.)" : | |
1374 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", | |
1375 quickChild = new RegExp("^>\\s*(" + chars + "+)"), | |
1376 quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), | |
1377 quickClass = new RegExp("^([#.]?)(" + chars + "*)"); | |
1378 | |
1379 jQuery.extend({ | |
1380 expr: { | |
1381 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);}, | |
1382 "#": function(a,i,m){return a.getAttribute("id")==m[2];}, | |
1383 ":": { | |
1384 // Position Checks | |
1385 lt: function(a,i,m){return i<m[3]-0;}, | |
1386 gt: function(a,i,m){return i>m[3]-0;}, | |
1387 nth: function(a,i,m){return m[3]-0==i;}, | |
1388 eq: function(a,i,m){return m[3]-0==i;}, | |
1389 first: function(a,i){return i==0;}, | |
1390 last: function(a,i,m,r){return i==r.length-1;}, | |
1391 even: function(a,i){return i%2==0;}, | |
1392 odd: function(a,i){return i%2;}, | |
1393 | |
1394 // Child Checks | |
1395 "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;}, | |
1396 "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;}, | |
1397 "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");}, | |
1398 | |
1399 // Parent Checks | |
1400 parent: function(a){return a.firstChild;}, | |
1401 empty: function(a){return !a.firstChild;}, | |
1402 | |
1403 // Text Check | |
1404 contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;}, | |
1405 | |
1406 // Visibility | |
1407 visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";}, | |
1408 hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";}, | |
1409 | |
1410 // Form attributes | |
1411 enabled: function(a){return !a.disabled;}, | |
1412 disabled: function(a){return a.disabled;}, | |
1413 checked: function(a){return a.checked;}, | |
1414 selected: function(a){return a.selected||jQuery.attr(a,"selected");}, | |
1415 | |
1416 // Form elements | |
1417 text: function(a){return "text"==a.type;}, | |
1418 radio: function(a){return "radio"==a.type;}, | |
1419 checkbox: function(a){return "checkbox"==a.type;}, | |
1420 file: function(a){return "file"==a.type;}, | |
1421 password: function(a){return "password"==a.type;}, | |
1422 submit: function(a){return "submit"==a.type;}, | |
1423 image: function(a){return "image"==a.type;}, | |
1424 reset: function(a){return "reset"==a.type;}, | |
1425 button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");}, | |
1426 input: function(a){return /input|select|textarea|button/i.test(a.nodeName);}, | |
1427 | |
1428 // :has() | |
1429 has: function(a,i,m){return jQuery.find(m[3],a).length;}, | |
1430 | |
1431 // :header | |
1432 header: function(a){return /h\d/i.test(a.nodeName);}, | |
1433 | |
1434 // :animated | |
1435 animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;} | |
1436 } | |
1437 }, | |
1438 | |
1439 // The regular expressions that power the parsing engine | |
1440 parse: [ | |
1441 // Match: [@value='test'], [@foo] | |
1442 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, | |
1443 | |
1444 // Match: :contains('foo') | |
1445 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, | |
1446 | |
1447 // Match: :even, :last-child, #id, .class | |
1448 new RegExp("^([:.#]*)(" + chars + "+)") | |
1449 ], | |
1450 | |
1451 multiFilter: function( expr, elems, not ) { | |
1452 var old, cur = []; | |
1453 | |
1454 while ( expr && expr != old ) { | |
1455 old = expr; | |
1456 var f = jQuery.filter( expr, elems, not ); | |
1457 expr = f.t.replace(/^\s*,\s*/, "" ); | |
1458 cur = not ? elems = f.r : jQuery.merge( cur, f.r ); | |
1459 } | |
1460 | |
1461 return cur; | |
1462 }, | |
1463 | |
1464 find: function( t, context ) { | |
1465 // Quickly handle non-string expressions | |
1466 if ( typeof t != "string" ) | |
1467 return [ t ]; | |
1468 | |
1469 // check to make sure context is a DOM element or a document | |
1470 if ( context && context.nodeType != 1 && context.nodeType != 9) | |
1471 return [ ]; | |
1472 | |
1473 // Set the correct context (if none is provided) | |
1474 context = context || document; | |
1475 | |
1476 // Initialize the search | |
1477 var ret = [context], done = [], last, nodeName; | |
1478 | |
1479 // Continue while a selector expression exists, and while | |
1480 // we're no longer looping upon ourselves | |
1481 while ( t && last != t ) { | |
1482 var r = []; | |
1483 last = t; | |
1484 | |
1485 t = jQuery.trim(t); | |
1486 | |
1487 var foundToken = false, | |
1488 | |
1489 // An attempt at speeding up child selectors that | |
1490 // point to a specific element tag | |
1491 re = quickChild, | |
1492 | |
1493 m = re.exec(t); | |
1494 | |
1495 if ( m ) { | |
1496 nodeName = m[1].toUpperCase(); | |
1497 | |
1498 // Perform our own iteration and filter | |
1499 for ( var i = 0; ret[i]; i++ ) | |
1500 for ( var c = ret[i].firstChild; c; c = c.nextSibling ) | |
1501 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) ) | |
1502 r.push( c ); | |
1503 | |
1504 ret = r; | |
1505 t = t.replace( re, "" ); | |
1506 if ( t.indexOf(" ") == 0 ) continue; | |
1507 foundToken = true; | |
1508 } else { | |
1509 re = /^([>+~])\s*(\w*)/i; | |
1510 | |
1511 if ( (m = re.exec(t)) != null ) { | |
1512 r = []; | |
1513 | |
1514 var merge = {}; | |
1515 nodeName = m[2].toUpperCase(); | |
1516 m = m[1]; | |
1517 | |
1518 for ( var j = 0, rl = ret.length; j < rl; j++ ) { | |
1519 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild; | |
1520 for ( ; n; n = n.nextSibling ) | |
1521 if ( n.nodeType == 1 ) { | |
1522 var id = jQuery.data(n); | |
1523 | |
1524 if ( m == "~" && merge[id] ) break; | |
1525 | |
1526 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) { | |
1527 if ( m == "~" ) merge[id] = true; | |
1528 r.push( n ); | |
1529 } | |
1530 | |
1531 if ( m == "+" ) break; | |
1532 } | |
1533 } | |
1534 | |
1535 ret = r; | |
1536 | |
1537 // And remove the token | |
1538 t = jQuery.trim( t.replace( re, "" ) ); | |
1539 foundToken = true; | |
1540 } | |
1541 } | |
1542 | |
1543 // See if there's still an expression, and that we haven't already | |
1544 // matched a token | |
1545 if ( t && !foundToken ) { | |
1546 // Handle multiple expressions | |
1547 if ( !t.indexOf(",") ) { | |
1548 // Clean the result set | |
1549 if ( context == ret[0] ) ret.shift(); | |
1550 | |
1551 // Merge the result sets | |
1552 done = jQuery.merge( done, ret ); | |
1553 | |
1554 // Reset the context | |
1555 r = ret = [context]; | |
1556 | |
1557 // Touch up the selector string | |
1558 t = " " + t.substr(1,t.length); | |
1559 | |
1560 } else { | |
1561 // Optimize for the case nodeName#idName | |
1562 var re2 = quickID; | |
1563 var m = re2.exec(t); | |
1564 | |
1565 // Re-organize the results, so that they're consistent | |
1566 if ( m ) { | |
1567 m = [ 0, m[2], m[3], m[1] ]; | |
1568 | |
1569 } else { | |
1570 // Otherwise, do a traditional filter check for | |
1571 // ID, class, and element selectors | |
1572 re2 = quickClass; | |
1573 m = re2.exec(t); | |
1574 } | |
1575 | |
1576 m[2] = m[2].replace(/\\/g, ""); | |
1577 | |
1578 var elem = ret[ret.length-1]; | |
1579 | |
1580 // Try to do a global search by ID, where we can | |
1581 if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) { | |
1582 // Optimization for HTML document case | |
1583 var oid = elem.getElementById(m[2]); | |
1584 | |
1585 // Do a quick check for the existence of the actual ID attribute | |
1586 // to avoid selecting by the name attribute in IE | |
1587 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form | |
1588 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] ) | |
1589 oid = jQuery('[@id="'+m[2]+'"]', elem)[0]; | |
1590 | |
1591 // Do a quick check for node name (where applicable) so | |
1592 // that div#foo searches will be really fast | |
1593 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : []; | |
1594 } else { | |
1595 // We need to find all descendant elements | |
1596 for ( var i = 0; ret[i]; i++ ) { | |
1597 // Grab the tag name being searched for | |
1598 var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2]; | |
1599 | |
1600 // Handle IE7 being really dumb about <object>s | |
1601 if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" ) | |
1602 tag = "param"; | |
1603 | |
1604 r = jQuery.merge( r, ret[i].getElementsByTagName( tag )); | |
1605 } | |
1606 | |
1607 // It's faster to filter by class and be done with it | |
1608 if ( m[1] == "." ) | |
1609 r = jQuery.classFilter( r, m[2] ); | |
1610 | |
1611 // Same with ID filtering | |
1612 if ( m[1] == "#" ) { | |
1613 var tmp = []; | |
1614 | |
1615 // Try to find the element with the ID | |
1616 for ( var i = 0; r[i]; i++ ) | |
1617 if ( r[i].getAttribute("id") == m[2] ) { | |
1618 tmp = [ r[i] ]; | |
1619 break; | |
1620 } | |
1621 | |
1622 r = tmp; | |
1623 } | |
1624 | |
1625 ret = r; | |
1626 } | |
1627 | |
1628 t = t.replace( re2, "" ); | |
1629 } | |
1630 | |
1631 } | |
1632 | |
1633 // If a selector string still exists | |
1634 if ( t ) { | |
1635 // Attempt to filter it | |
1636 var val = jQuery.filter(t,r); | |
1637 ret = r = val.r; | |
1638 t = jQuery.trim(val.t); | |
1639 } | |
1640 } | |
1641 | |
1642 // An error occurred with the selector; | |
1643 // just return an empty set instead | |
1644 if ( t ) | |
1645 ret = []; | |
1646 | |
1647 // Remove the root context | |
1648 if ( ret && context == ret[0] ) | |
1649 ret.shift(); | |
1650 | |
1651 // And combine the results | |
1652 done = jQuery.merge( done, ret ); | |
1653 | |
1654 return done; | |
1655 }, | |
1656 | |
1657 classFilter: function(r,m,not){ | |
1658 m = " " + m + " "; | |
1659 var tmp = []; | |
1660 for ( var i = 0; r[i]; i++ ) { | |
1661 var pass = (" " + r[i].className + " ").indexOf( m ) >= 0; | |
1662 if ( !not && pass || not && !pass ) | |
1663 tmp.push( r[i] ); | |
1664 } | |
1665 return tmp; | |
1666 }, | |
1667 | |
1668 filter: function(t,r,not) { | |
1669 var last; | |
1670 | |
1671 // Look for common filter expressions | |
1672 while ( t && t != last ) { | |
1673 last = t; | |
1674 | |
1675 var p = jQuery.parse, m; | |
1676 | |
1677 for ( var i = 0; p[i]; i++ ) { | |
1678 m = p[i].exec( t ); | |
1679 | |
1680 if ( m ) { | |
1681 // Remove what we just matched | |
1682 t = t.substring( m[0].length ); | |
1683 | |
1684 m[2] = m[2].replace(/\\/g, ""); | |
1685 break; | |
1686 } | |
1687 } | |
1688 | |
1689 if ( !m ) | |
1690 break; | |
1691 | |
1692 // :not() is a special case that can be optimized by | |
1693 // keeping it out of the expression list | |
1694 if ( m[1] == ":" && m[2] == "not" ) | |
1695 // optimize if only one selector found (most common case) | |
1696 r = isSimple.test( m[3] ) ? | |
1697 jQuery.filter(m[3], r, true).r : | |
1698 jQuery( r ).not( m[3] ); | |
1699 | |
1700 // We can get a big speed boost by filtering by class here | |
1701 else if ( m[1] == "." ) | |
1702 r = jQuery.classFilter(r, m[2], not); | |
1703 | |
1704 else if ( m[1] == "[" ) { | |
1705 var tmp = [], type = m[3]; | |
1706 | |
1707 for ( var i = 0, rl = r.length; i < rl; i++ ) { | |
1708 var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ]; | |
1709 | |
1710 if ( z == null || /href|src|selected/.test(m[2]) ) | |
1711 z = jQuery.attr(a,m[2]) || ''; | |
1712 | |
1713 if ( (type == "" && !!z || | |
1714 type == "=" && z == m[5] || | |
1715 type == "!=" && z != m[5] || | |
1716 type == "^=" && z && !z.indexOf(m[5]) || | |
1717 type == "$=" && z.substr(z.length - m[5].length) == m[5] || | |
1718 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not ) | |
1719 tmp.push( a ); | |
1720 } | |
1721 | |
1722 r = tmp; | |
1723 | |
1724 // We can get a speed boost by handling nth-child here | |
1725 } else if ( m[1] == ":" && m[2] == "nth-child" ) { | |
1726 var merge = {}, tmp = [], | |
1727 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' | |
1728 test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( | |
1729 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" || | |
1730 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]), | |
1731 // calculate the numbers (first)n+(last) including if they are negative | |
1732 first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0; | |
1733 | |
1734 // loop through all the elements left in the jQuery object | |
1735 for ( var i = 0, rl = r.length; i < rl; i++ ) { | |
1736 var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode); | |
1737 | |
1738 if ( !merge[id] ) { | |
1739 var c = 1; | |
1740 | |
1741 for ( var n = parentNode.firstChild; n; n = n.nextSibling ) | |
1742 if ( n.nodeType == 1 ) | |
1743 n.nodeIndex = c++; | |
1744 | |
1745 merge[id] = true; | |
1746 } | |
1747 | |
1748 var add = false; | |
1749 | |
1750 if ( first == 0 ) { | |
1751 if ( node.nodeIndex == last ) | |
1752 add = true; | |
1753 } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 ) | |
1754 add = true; | |
1755 | |
1756 if ( add ^ not ) | |
1757 tmp.push( node ); | |
1758 } | |
1759 | |
1760 r = tmp; | |
1761 | |
1762 // Otherwise, find the expression to execute | |
1763 } else { | |
1764 var fn = jQuery.expr[ m[1] ]; | |
1765 if ( typeof fn == "object" ) | |
1766 fn = fn[ m[2] ]; | |
1767 | |
1768 if ( typeof fn == "string" ) | |
1769 fn = eval("false||function(a,i){return " + fn + ";}"); | |
1770 | |
1771 // Execute it against the current filter | |
1772 r = jQuery.grep( r, function(elem, i){ | |
1773 return fn(elem, i, m, r); | |
1774 }, not ); | |
1775 } | |
1776 } | |
1777 | |
1778 // Return an array of filtered elements (r) | |
1779 // and the modified expression string (t) | |
1780 return { r: r, t: t }; | |
1781 }, | |
1782 | |
1783 dir: function( elem, dir ){ | |
1784 var matched = [], | |
1785 cur = elem[dir]; | |
1786 while ( cur && cur != document ) { | |
1787 if ( cur.nodeType == 1 ) | |
1788 matched.push( cur ); | |
1789 cur = cur[dir]; | |
1790 } | |
1791 return matched; | |
1792 }, | |
1793 | |
1794 nth: function(cur,result,dir,elem){ | |
1795 result = result || 1; | |
1796 var num = 0; | |
1797 | |
1798 for ( ; cur; cur = cur[dir] ) | |
1799 if ( cur.nodeType == 1 && ++num == result ) | |
1800 break; | |
1801 | |
1802 return cur; | |
1803 }, | |
1804 | |
1805 sibling: function( n, elem ) { | |
1806 var r = []; | |
1807 | |
1808 for ( ; n; n = n.nextSibling ) { | |
1809 if ( n.nodeType == 1 && n != elem ) | |
1810 r.push( n ); | |
1811 } | |
1812 | |
1813 return r; | |
1814 } | |
1815 }); | |
1816 /* | |
1817 * A number of helper functions used for managing events. | |
1818 * Many of the ideas behind this code orignated from | |
1819 * Dean Edwards' addEvent library. | |
1820 */ | |
1821 jQuery.event = { | |
1822 | |
1823 // Bind an event to an element | |
1824 // Original by Dean Edwards | |
1825 add: function(elem, types, handler, data) { | |
1826 if ( elem.nodeType == 3 || elem.nodeType == 8 ) | |
1827 return; | |
1828 | |
1829 // For whatever reason, IE has trouble passing the window object | |
1830 // around, causing it to be cloned in the process | |
1831 if ( jQuery.browser.msie && elem.setInterval ) | |
1832 elem = window; | |
1833 | |
1834 // Make sure that the function being executed has a unique ID | |
1835 if ( !handler.guid ) | |
1836 handler.guid = this.guid++; | |
1837 | |
1838 // if data is passed, bind to handler | |
1839 if( data != undefined ) { | |
1840 // Create temporary function pointer to original handler | |
1841 var fn = handler; | |
1842 | |
1843 // Create unique handler function, wrapped around original handler | |
1844 handler = this.proxy( fn, function() { | |
1845 // Pass arguments and context to original handler | |
1846 return fn.apply(this, arguments); | |
1847 }); | |
1848 | |
1849 // Store data in unique handler | |
1850 handler.data = data; | |
1851 } | |
1852 | |
1853 // Init the element's event structure | |
1854 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), | |
1855 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ | |
1856 // Handle the second event of a trigger and when | |
1857 // an event is called after a page has unloaded | |
1858 if ( typeof jQuery != "undefined" && !jQuery.event.triggered ) | |
1859 return jQuery.event.handle.apply(arguments.callee.elem, arguments); | |
1860 }); | |
1861 // Add elem as a property of the handle function | |
1862 // This is to prevent a memory leak with non-native | |
1863 // event in IE. | |
1864 handle.elem = elem; | |
1865 | |
1866 // Handle multiple events separated by a space | |
1867 // jQuery(...).bind("mouseover mouseout", fn); | |
1868 jQuery.each(types.split(/\s+/), function(index, type) { | |
1869 // Namespaced event handlers | |
1870 var parts = type.split("."); | |
1871 type = parts[0]; | |
1872 handler.type = parts[1]; | |
1873 | |
1874 // Get the current list of functions bound to this event | |
1875 var handlers = events[type]; | |
1876 | |
1877 // Init the event handler queue | |
1878 if (!handlers) { | |
1879 handlers = events[type] = {}; | |
1880 | |
1881 // Check for a special event handler | |
1882 // Only use addEventListener/attachEvent if the special | |
1883 // events handler returns false | |
1884 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) { | |
1885 // Bind the global event handler to the element | |
1886 if (elem.addEventListener) | |
1887 elem.addEventListener(type, handle, false); | |
1888 else if (elem.attachEvent) | |
1889 elem.attachEvent("on" + type, handle); | |
1890 } | |
1891 } | |
1892 | |
1893 // Add the function to the element's handler list | |
1894 handlers[handler.guid] = handler; | |
1895 | |
1896 // Keep track of which events have been used, for global triggering | |
1897 jQuery.event.global[type] = true; | |
1898 }); | |
1899 | |
1900 // Nullify elem to prevent memory leaks in IE | |
1901 elem = null; | |
1902 }, | |
1903 | |
1904 guid: 1, | |
1905 global: {}, | |
1906 | |
1907 // Detach an event or set of events from an element | |
1908 remove: function(elem, types, handler) { | |
1909 // don't do events on text and comment nodes | |
1910 if ( elem.nodeType == 3 || elem.nodeType == 8 ) | |
1911 return; | |
1912 | |
1913 var events = jQuery.data(elem, "events"), ret, index; | |
1914 | |
1915 if ( events ) { | |
1916 // Unbind all events for the element | |
1917 if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") ) | |
1918 for ( var type in events ) | |
1919 this.remove( elem, type + (types || "") ); | |
1920 else { | |
1921 // types is actually an event object here | |
1922 if ( types.type ) { | |
1923 handler = types.handler; | |
1924 types = types.type; | |
1925 } | |
1926 | |
1927 // Handle multiple events seperated by a space | |
1928 // jQuery(...).unbind("mouseover mouseout", fn); | |
1929 jQuery.each(types.split(/\s+/), function(index, type){ | |
1930 // Namespaced event handlers | |
1931 var parts = type.split("."); | |
1932 type = parts[0]; | |
1933 | |
1934 if ( events[type] ) { | |
1935 // remove the given handler for the given type | |
1936 if ( handler ) | |
1937 delete events[type][handler.guid]; | |
1938 | |
1939 // remove all handlers for the given type | |
1940 else | |
1941 for ( handler in events[type] ) | |
1942 // Handle the removal of namespaced events | |
1943 if ( !parts[1] || events[type][handler].type == parts[1] ) | |
1944 delete events[type][handler]; | |
1945 | |
1946 // remove generic event handler if no more handlers exist | |
1947 for ( ret in events[type] ) break; | |
1948 if ( !ret ) { | |
1949 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) { | |
1950 if (elem.removeEventListener) | |
1951 elem.removeEventListener(type, jQuery.data(elem, "handle"), false); | |
1952 else if (elem.detachEvent) | |
1953 elem.detachEvent("on" + type, jQuery.data(elem, "handle")); | |
1954 } | |
1955 ret = null; | |
1956 delete events[type]; | |
1957 } | |
1958 } | |
1959 }); | |
1960 } | |
1961 | |
1962 // Remove the expando if it's no longer used | |
1963 for ( ret in events ) break; | |
1964 if ( !ret ) { | |
1965 var handle = jQuery.data( elem, "handle" ); | |
1966 if ( handle ) handle.elem = null; | |
1967 jQuery.removeData( elem, "events" ); | |
1968 jQuery.removeData( elem, "handle" ); | |
1969 } | |
1970 } | |
1971 }, | |
1972 | |
1973 trigger: function(type, data, elem, donative, extra) { | |
1974 // Clone the incoming data, if any | |
1975 data = jQuery.makeArray(data); | |
1976 | |
1977 if ( type.indexOf("!") >= 0 ) { | |
1978 type = type.slice(0, -1); | |
1979 var exclusive = true; | |
1980 } | |
1981 | |
1982 // Handle a global trigger | |
1983 if ( !elem ) { | |
1984 // Only trigger if we've ever bound an event for it | |
1985 if ( this.global[type] ) | |
1986 jQuery("*").add([window, document]).trigger(type, data); | |
1987 | |
1988 // Handle triggering a single element | |
1989 } else { | |
1990 // don't do events on text and comment nodes | |
1991 if ( elem.nodeType == 3 || elem.nodeType == 8 ) | |
1992 return undefined; | |
1993 | |
1994 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ), | |
1995 // Check to see if we need to provide a fake event, or not | |
1996 event = !data[0] || !data[0].preventDefault; | |
1997 | |
1998 // Pass along a fake event | |
1999 if ( event ) { | |
2000 data.unshift({ | |
2001 type: type, | |
2002 target: elem, | |
2003 preventDefault: function(){}, | |
2004 stopPropagation: function(){}, | |
2005 timeStamp: now() | |
2006 }); | |
2007 data[0][expando] = true; // no need to fix fake event | |
2008 } | |
2009 | |
2010 // Enforce the right trigger type | |
2011 data[0].type = type; | |
2012 if ( exclusive ) | |
2013 data[0].exclusive = true; | |
2014 | |
2015 // Trigger the event, it is assumed that "handle" is a function | |
2016 var handle = jQuery.data(elem, "handle"); | |
2017 if ( handle ) | |
2018 val = handle.apply( elem, data ); | |
2019 | |
2020 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links) | |
2021 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) | |
2022 val = false; | |
2023 | |
2024 // Extra functions don't get the custom event object | |
2025 if ( event ) | |
2026 data.shift(); | |
2027 | |
2028 // Handle triggering of extra function | |
2029 if ( extra && jQuery.isFunction( extra ) ) { | |
2030 // call the extra function and tack the current return value on the end for possible inspection | |
2031 ret = extra.apply( elem, val == null ? data : data.concat( val ) ); | |
2032 // if anything is returned, give it precedence and have it overwrite the previous value | |
2033 if (ret !== undefined) | |
2034 val = ret; | |
2035 } | |
2036 | |
2037 // Trigger the native events (except for clicks on links) | |
2038 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) { | |
2039 this.triggered = true; | |
2040 try { | |
2041 elem[ type ](); | |
2042 // prevent IE from throwing an error for some hidden elements | |
2043 } catch (e) {} | |
2044 } | |
2045 | |
2046 this.triggered = false; | |
2047 } | |
2048 | |
2049 return val; | |
2050 }, | |
2051 | |
2052 handle: function(event) { | |
2053 // returned undefined or false | |
2054 var val, ret, namespace, all, handlers; | |
2055 | |
2056 event = arguments[0] = jQuery.event.fix( event || window.event ); | |
2057 | |
2058 // Namespaced event handlers | |
2059 namespace = event.type.split("."); | |
2060 event.type = namespace[0]; | |
2061 namespace = namespace[1]; | |
2062 // Cache this now, all = true means, any handler | |
2063 all = !namespace && !event.exclusive; | |
2064 | |
2065 handlers = ( jQuery.data(this, "events") || {} )[event.type]; | |
2066 | |
2067 for ( var j in handlers ) { | |
2068 var handler = handlers[j]; | |
2069 | |
2070 // Filter the functions by class | |
2071 if ( all || handler.type == namespace ) { | |
2072 // Pass in a reference to the handler function itself | |
2073 // So that we can later remove it | |
2074 event.handler = handler; | |
2075 event.data = handler.data; | |
2076 | |
2077 ret = handler.apply( this, arguments ); | |
2078 | |
2079 if ( val !== false ) | |
2080 val = ret; | |
2081 | |
2082 if ( ret === false ) { | |
2083 event.preventDefault(); | |
2084 event.stopPropagation(); | |
2085 } | |
2086 } | |
2087 } | |
2088 | |
2089 return val; | |
2090 }, | |
2091 | |
2092 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" "), | |
2093 | |
2094 fix: function(event) { | |
2095 if ( event[expando] == true ) | |
2096 return event; | |
2097 | |
2098 // store a copy of the original event object | |
2099 // and "clone" to set read-only properties | |
2100 var originalEvent = event; | |
2101 event = { originalEvent: originalEvent }; | |
2102 | |
2103 for ( var i = this.props.length, prop; i; ){ | |
2104 prop = this.props[ --i ]; | |
2105 event[ prop ] = originalEvent[ prop ]; | |
2106 } | |
2107 | |
2108 // Mark it as fixed | |
2109 event[expando] = true; | |
2110 | |
2111 // add preventDefault and stopPropagation since | |
2112 // they will not work on the clone | |
2113 event.preventDefault = function() { | |
2114 // if preventDefault exists run it on the original event | |
2115 if (originalEvent.preventDefault) | |
2116 originalEvent.preventDefault(); | |
2117 // otherwise set the returnValue property of the original event to false (IE) | |
2118 originalEvent.returnValue = false; | |
2119 }; | |
2120 event.stopPropagation = function() { | |
2121 // if stopPropagation exists run it on the original event | |
2122 if (originalEvent.stopPropagation) | |
2123 originalEvent.stopPropagation(); | |
2124 // otherwise set the cancelBubble property of the original event to true (IE) | |
2125 originalEvent.cancelBubble = true; | |
2126 }; | |
2127 | |
2128 // Fix timeStamp | |
2129 event.timeStamp = event.timeStamp || now(); | |
2130 | |
2131 // Fix target property, if necessary | |
2132 if ( !event.target ) | |
2133 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either | |
2134 | |
2135 // check if target is a textnode (safari) | |
2136 if ( event.target.nodeType == 3 ) | |
2137 event.target = event.target.parentNode; | |
2138 | |
2139 // Add relatedTarget, if necessary | |
2140 if ( !event.relatedTarget && event.fromElement ) | |
2141 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; | |
2142 | |
2143 // Calculate pageX/Y if missing and clientX/Y available | |
2144 if ( event.pageX == null && event.clientX != null ) { | |
2145 var doc = document.documentElement, body = document.body; | |
2146 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); | |
2147 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); | |
2148 } | |
2149 | |
2150 // Add which for key events | |
2151 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) | |
2152 event.which = event.charCode || event.keyCode; | |
2153 | |
2154 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) | |
2155 if ( !event.metaKey && event.ctrlKey ) | |
2156 event.metaKey = event.ctrlKey; | |
2157 | |
2158 // Add which for click: 1 == left; 2 == middle; 3 == right | |
2159 // Note: button is not normalized, so don't use it | |
2160 if ( !event.which && event.button ) | |
2161 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); | |
2162 | |
2163 return event; | |
2164 }, | |
2165 | |
2166 proxy: function( fn, proxy ){ | |
2167 // Set the guid of unique handler to the same of original handler, so it can be removed | |
2168 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++; | |
2169 // So proxy can be declared as an argument | |
2170 return proxy; | |
2171 }, | |
2172 | |
2173 special: { | |
2174 ready: { | |
2175 setup: function() { | |
2176 // Make sure the ready event is setup | |
2177 bindReady(); | |
2178 return; | |
2179 }, | |
2180 | |
2181 teardown: function() { return; } | |
2182 }, | |
2183 | |
2184 mouseenter: { | |
2185 setup: function() { | |
2186 if ( jQuery.browser.msie ) return false; | |
2187 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler); | |
2188 return true; | |
2189 }, | |
2190 | |
2191 teardown: function() { | |
2192 if ( jQuery.browser.msie ) return false; | |
2193 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler); | |
2194 return true; | |
2195 }, | |
2196 | |
2197 handler: function(event) { | |
2198 // If we actually just moused on to a sub-element, ignore it | |
2199 if ( withinElement(event, this) ) return true; | |
2200 // Execute the right handlers by setting the event type to mouseenter | |
2201 event.type = "mouseenter"; | |
2202 return jQuery.event.handle.apply(this, arguments); | |
2203 } | |
2204 }, | |
2205 | |
2206 mouseleave: { | |
2207 setup: function() { | |
2208 if ( jQuery.browser.msie ) return false; | |
2209 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler); | |
2210 return true; | |
2211 }, | |
2212 | |
2213 teardown: function() { | |
2214 if ( jQuery.browser.msie ) return false; | |
2215 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler); | |
2216 return true; | |
2217 }, | |
2218 | |
2219 handler: function(event) { | |
2220 // If we actually just moused on to a sub-element, ignore it | |
2221 if ( withinElement(event, this) ) return true; | |
2222 // Execute the right handlers by setting the event type to mouseleave | |
2223 event.type = "mouseleave"; | |
2224 return jQuery.event.handle.apply(this, arguments); | |
2225 } | |
2226 } | |
2227 } | |
2228 }; | |
2229 | |
2230 jQuery.fn.extend({ | |
2231 bind: function( type, data, fn ) { | |
2232 return type == "unload" ? this.one(type, data, fn) : this.each(function(){ | |
2233 jQuery.event.add( this, type, fn || data, fn && data ); | |
2234 }); | |
2235 }, | |
2236 | |
2237 one: function( type, data, fn ) { | |
2238 var one = jQuery.event.proxy( fn || data, function(event) { | |
2239 jQuery(this).unbind(event, one); | |
2240 return (fn || data).apply( this, arguments ); | |
2241 }); | |
2242 return this.each(function(){ | |
2243 jQuery.event.add( this, type, one, fn && data); | |
2244 }); | |
2245 }, | |
2246 | |
2247 unbind: function( type, fn ) { | |
2248 return this.each(function(){ | |
2249 jQuery.event.remove( this, type, fn ); | |
2250 }); | |
2251 }, | |
2252 | |
2253 trigger: function( type, data, fn ) { | |
2254 return this.each(function(){ | |
2255 jQuery.event.trigger( type, data, this, true, fn ); | |
2256 }); | |
2257 }, | |
2258 | |
2259 triggerHandler: function( type, data, fn ) { | |
2260 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn ); | |
2261 }, | |
2262 | |
2263 toggle: function( fn ) { | |
2264 // Save reference to arguments for access in closure | |
2265 var args = arguments, i = 1; | |
2266 | |
2267 // link all the functions, so any of them can unbind this click handler | |
2268 while( i < args.length ) | |
2269 jQuery.event.proxy( fn, args[i++] ); | |
2270 | |
2271 return this.click( jQuery.event.proxy( fn, function(event) { | |
2272 // Figure out which function to execute | |
2273 this.lastToggle = ( this.lastToggle || 0 ) % i; | |
2274 | |
2275 // Make sure that clicks stop | |
2276 event.preventDefault(); | |
2277 | |
2278 // and execute the function | |
2279 return args[ this.lastToggle++ ].apply( this, arguments ) || false; | |
2280 })); | |
2281 }, | |
2282 | |
2283 hover: function(fnOver, fnOut) { | |
2284 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut); | |
2285 }, | |
2286 | |
2287 ready: function(fn) { | |
2288 // Attach the listeners | |
2289 bindReady(); | |
2290 | |
2291 // If the DOM is already ready | |
2292 if ( jQuery.isReady ) | |
2293 // Execute the function immediately | |
2294 fn.call( document, jQuery ); | |
2295 | |
2296 // Otherwise, remember the function for later | |
2297 else | |
2298 // Add the function to the wait list | |
2299 jQuery.readyList.push( function() { return fn.call(this, jQuery); } ); | |
2300 | |
2301 return this; | |
2302 } | |
2303 }); | |
2304 | |
2305 jQuery.extend({ | |
2306 isReady: false, | |
2307 readyList: [], | |
2308 // Handle when the DOM is ready | |
2309 ready: function() { | |
2310 // Make sure that the DOM is not already loaded | |
2311 if ( !jQuery.isReady ) { | |
2312 // Remember that the DOM is ready | |
2313 jQuery.isReady = true; | |
2314 | |
2315 // If there are functions bound, to execute | |
2316 if ( jQuery.readyList ) { | |
2317 // Execute all of them | |
2318 jQuery.each( jQuery.readyList, function(){ | |
2319 this.call( document ); | |
2320 }); | |
2321 | |
2322 // Reset the list of functions | |
2323 jQuery.readyList = null; | |
2324 } | |
2325 | |
2326 // Trigger any bound ready events | |
2327 jQuery(document).triggerHandler("ready"); | |
2328 } | |
2329 } | |
2330 }); | |
2331 | |
2332 var readyBound = false; | |
2333 | |
2334 function bindReady(){ | |
2335 if ( readyBound ) return; | |
2336 readyBound = true; | |
2337 | |
2338 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event | |
2339 if ( document.addEventListener && !jQuery.browser.opera) | |
2340 // Use the handy event callback | |
2341 document.addEventListener( "DOMContentLoaded", jQuery.ready, false ); | |
2342 | |
2343 // If IE is used and is not in a frame | |
2344 // Continually check to see if the document is ready | |
2345 if ( jQuery.browser.msie && window == top ) (function(){ | |
2346 if (jQuery.isReady) return; | |
2347 try { | |
2348 // If IE is used, use the trick by Diego Perini | |
2349 // http://javascript.nwbox.com/IEContentLoaded/ | |
2350 document.documentElement.doScroll("left"); | |
2351 } catch( error ) { | |
2352 setTimeout( arguments.callee, 0 ); | |
2353 return; | |
2354 } | |
2355 // and execute any waiting functions | |
2356 jQuery.ready(); | |
2357 })(); | |
2358 | |
2359 if ( jQuery.browser.opera ) | |
2360 document.addEventListener( "DOMContentLoaded", function () { | |
2361 if (jQuery.isReady) return; | |
2362 for (var i = 0; i < document.styleSheets.length; i++) | |
2363 if (document.styleSheets[i].disabled) { | |
2364 setTimeout( arguments.callee, 0 ); | |
2365 return; | |
2366 } | |
2367 // and execute any waiting functions | |
2368 jQuery.ready(); | |
2369 }, false); | |
2370 | |
2371 if ( jQuery.browser.safari ) { | |
2372 var numStyles; | |
2373 (function(){ | |
2374 if (jQuery.isReady) return; | |
2375 if ( document.readyState != "loaded" && document.readyState != "complete" ) { | |
2376 setTimeout( arguments.callee, 0 ); | |
2377 return; | |
2378 } | |
2379 if ( numStyles === undefined ) | |
2380 numStyles = jQuery("style, link[rel=stylesheet]").length; | |
2381 if ( document.styleSheets.length != numStyles ) { | |
2382 setTimeout( arguments.callee, 0 ); | |
2383 return; | |
2384 } | |
2385 // and execute any waiting functions | |
2386 jQuery.ready(); | |
2387 })(); | |
2388 } | |
2389 | |
2390 // A fallback to window.onload, that will always work | |
2391 jQuery.event.add( window, "load", jQuery.ready ); | |
2392 } | |
2393 | |
2394 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + | |
2395 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + | |
2396 "submit,keydown,keypress,keyup,error").split(","), function(i, name){ | |
2397 | |
2398 // Handle event binding | |
2399 jQuery.fn[name] = function(fn){ | |
2400 return fn ? this.bind(name, fn) : this.trigger(name); | |
2401 }; | |
2402 }); | |
2403 | |
2404 // Checks if an event happened on an element within another element | |
2405 // Used in jQuery.event.special.mouseenter and mouseleave handlers | |
2406 var withinElement = function(event, elem) { | |
2407 // Check if mouse(over|out) are still within the same parent element | |
2408 var parent = event.relatedTarget; | |
2409 // Traverse up the tree | |
2410 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; } | |
2411 // Return true if we actually just moused on to a sub-element | |
2412 return parent == elem; | |
2413 }; | |
2414 | |
2415 // Prevent memory leaks in IE | |
2416 // And prevent errors on refresh with events like mouseover in other browsers | |
2417 // Window isn't included so as not to unbind existing unload events | |
2418 jQuery(window).bind("unload", function() { | |
2419 jQuery("*").add(document).unbind(); | |
2420 }); | |
2421 jQuery.fn.extend({ | |
2422 // Keep a copy of the old load | |
2423 _load: jQuery.fn.load, | |
2424 | |
2425 load: function( url, params, callback ) { | |
2426 if ( typeof url != 'string' ) | |
2427 return this._load( url ); | |
2428 | |
2429 var off = url.indexOf(" "); | |
2430 if ( off >= 0 ) { | |
2431 var selector = url.slice(off, url.length); | |
2432 url = url.slice(0, off); | |
2433 } | |
2434 | |
2435 callback = callback || function(){}; | |
2436 | |
2437 // Default to a GET request | |
2438 var type = "GET"; | |
2439 | |
2440 // If the second parameter was provided | |
2441 if ( params ) | |
2442 // If it's a function | |
2443 if ( jQuery.isFunction( params ) ) { | |
2444 // We assume that it's the callback | |
2445 callback = params; | |
2446 params = null; | |
2447 | |
2448 // Otherwise, build a param string | |
2449 } else if( typeof params == 'object' ) { | |
2450 params = jQuery.param( params ); | |
2451 type = "POST"; | |
2452 } | |
2453 | |
2454 var self = this; | |
2455 | |
2456 // Request the remote document | |
2457 jQuery.ajax({ | |
2458 url: url, | |
2459 type: type, | |
2460 dataType: "html", | |
2461 data: params, | |
2462 complete: function(res, status){ | |
2463 // If successful, inject the HTML into all the matched elements | |
2464 if ( status == "success" || status == "notmodified" ) | |
2465 // See if a selector was specified | |
2466 self.html( selector ? | |
2467 // Create a dummy div to hold the results | |
2468 jQuery("<div/>") | |
2469 // inject the contents of the document in, removing the scripts | |
2470 // to avoid any 'Permission Denied' errors in IE | |
2471 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) | |
2472 | |
2473 // Locate the specified elements | |
2474 .find(selector) : | |
2475 | |
2476 // If not, just inject the full result | |
2477 res.responseText ); | |
2478 | |
2479 self.each( callback, [res.responseText, status, res] ); | |
2480 } | |
2481 }); | |
2482 return this; | |
2483 }, | |
2484 | |
2485 serialize: function() { | |
2486 return jQuery.param(this.serializeArray()); | |
2487 }, | |
2488 serializeArray: function() { | |
2489 return this.map(function(){ | |
2490 return jQuery.nodeName(this, "form") ? | |
2491 jQuery.makeArray(this.elements) : this; | |
2492 }) | |
2493 .filter(function(){ | |
2494 return this.name && !this.disabled && | |
2495 (this.checked || /select|textarea/i.test(this.nodeName) || | |
2496 /text|hidden|password/i.test(this.type)); | |
2497 }) | |
2498 .map(function(i, elem){ | |
2499 var val = jQuery(this).val(); | |
2500 return val == null ? null : | |
2501 val.constructor == Array ? | |
2502 jQuery.map( val, function(val, i){ | |
2503 return {name: elem.name, value: val}; | |
2504 }) : | |
2505 {name: elem.name, value: val}; | |
2506 }).get(); | |
2507 } | |
2508 }); | |
2509 | |
2510 // Attach a bunch of functions for handling common AJAX events | |
2511 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ | |
2512 jQuery.fn[o] = function(f){ | |
2513 return this.bind(o, f); | |
2514 }; | |
2515 }); | |
2516 | |
2517 var jsc = now(); | |
2518 | |
2519 jQuery.extend({ | |
2520 get: function( url, data, callback, type ) { | |
2521 // shift arguments if data argument was ommited | |
2522 if ( jQuery.isFunction( data ) ) { | |
2523 callback = data; | |
2524 data = null; | |
2525 } | |
2526 | |
2527 return jQuery.ajax({ | |
2528 type: "GET", | |
2529 url: url, | |
2530 data: data, | |
2531 success: callback, | |
2532 dataType: type | |
2533 }); | |
2534 }, | |
2535 | |
2536 getScript: function( url, callback ) { | |
2537 return jQuery.get(url, null, callback, "script"); | |
2538 }, | |
2539 | |
2540 getJSON: function( url, data, callback ) { | |
2541 return jQuery.get(url, data, callback, "json"); | |
2542 }, | |
2543 | |
2544 post: function( url, data, callback, type ) { | |
2545 if ( jQuery.isFunction( data ) ) { | |
2546 callback = data; | |
2547 data = {}; | |
2548 } | |
2549 | |
2550 return jQuery.ajax({ | |
2551 type: "POST", | |
2552 url: url, | |
2553 data: data, | |
2554 success: callback, | |
2555 dataType: type | |
2556 }); | |
2557 }, | |
2558 | |
2559 ajaxSetup: function( settings ) { | |
2560 jQuery.extend( jQuery.ajaxSettings, settings ); | |
2561 }, | |
2562 | |
2563 ajaxSettings: { | |
2564 url: location.href, | |
2565 global: true, | |
2566 type: "GET", | |
2567 timeout: 0, | |
2568 contentType: "application/x-www-form-urlencoded", | |
2569 processData: true, | |
2570 async: true, | |
2571 data: null, | |
2572 username: null, | |
2573 password: null, | |
2574 accepts: { | |
2575 xml: "application/xml, text/xml", | |
2576 html: "text/html", | |
2577 script: "text/javascript, application/javascript", | |
2578 json: "application/json, text/javascript", | |
2579 text: "text/plain", | |
2580 _default: "*/*" | |
2581 } | |
2582 }, | |
2583 | |
2584 // Last-Modified header cache for next request | |
2585 lastModified: {}, | |
2586 | |
2587 ajax: function( s ) { | |
2588 // Extend the settings, but re-extend 's' so that it can be | |
2589 // checked again later (in the test suite, specifically) | |
2590 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); | |
2591 | |
2592 var jsonp, jsre = /=\?(&|$)/g, status, data, | |
2593 type = s.type.toUpperCase(); | |
2594 | |
2595 // convert data if not already a string | |
2596 if ( s.data && s.processData && typeof s.data != "string" ) | |
2597 s.data = jQuery.param(s.data); | |
2598 | |
2599 // Handle JSONP Parameter Callbacks | |
2600 if ( s.dataType == "jsonp" ) { | |
2601 if ( type == "GET" ) { | |
2602 if ( !s.url.match(jsre) ) | |
2603 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; | |
2604 } else if ( !s.data || !s.data.match(jsre) ) | |
2605 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; | |
2606 s.dataType = "json"; | |
2607 } | |
2608 | |
2609 // Build temporary JSONP function | |
2610 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { | |
2611 jsonp = "jsonp" + jsc++; | |
2612 | |
2613 // Replace the =? sequence both in the query string and the data | |
2614 if ( s.data ) | |
2615 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); | |
2616 s.url = s.url.replace(jsre, "=" + jsonp + "$1"); | |
2617 | |
2618 // We need to make sure | |
2619 // that a JSONP style response is executed properly | |
2620 s.dataType = "script"; | |
2621 | |
2622 // Handle JSONP-style loading | |
2623 window[ jsonp ] = function(tmp){ | |
2624 data = tmp; | |
2625 success(); | |
2626 complete(); | |
2627 // Garbage collect | |
2628 window[ jsonp ] = undefined; | |
2629 try{ delete window[ jsonp ]; } catch(e){} | |
2630 if ( head ) | |
2631 head.removeChild( script ); | |
2632 }; | |
2633 } | |
2634 | |
2635 if ( s.dataType == "script" && s.cache == null ) | |
2636 s.cache = false; | |
2637 | |
2638 if ( s.cache === false && type == "GET" ) { | |
2639 var ts = now(); | |
2640 // try replacing _= if it is there | |
2641 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); | |
2642 // if nothing was replaced, add timestamp to the end | |
2643 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); | |
2644 } | |
2645 | |
2646 // If data is available, append data to url for get requests | |
2647 if ( s.data && type == "GET" ) { | |
2648 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; | |
2649 | |
2650 // IE likes to send both get and post data, prevent this | |
2651 s.data = null; | |
2652 } | |
2653 | |
2654 // Watch for a new set of requests | |
2655 if ( s.global && ! jQuery.active++ ) | |
2656 jQuery.event.trigger( "ajaxStart" ); | |
2657 | |
2658 // Matches an absolute URL, and saves the domain | |
2659 var remote = /^(?:\w+:)?\/\/([^\/?#]+)/; | |
2660 | |
2661 // If we're requesting a remote document | |
2662 // and trying to load JSON or Script with a GET | |
2663 if ( s.dataType == "script" && type == "GET" | |
2664 && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){ | |
2665 var head = document.getElementsByTagName("head")[0]; | |
2666 var script = document.createElement("script"); | |
2667 script.src = s.url; | |
2668 if (s.scriptCharset) | |
2669 script.charset = s.scriptCharset; | |
2670 | |
2671 // Handle Script loading | |
2672 if ( !jsonp ) { | |
2673 var done = false; | |
2674 | |
2675 // Attach handlers for all browsers | |
2676 script.onload = script.onreadystatechange = function(){ | |
2677 if ( !done && (!this.readyState || | |
2678 this.readyState == "loaded" || this.readyState == "complete") ) { | |
2679 done = true; | |
2680 success(); | |
2681 complete(); | |
2682 head.removeChild( script ); | |
2683 } | |
2684 }; | |
2685 } | |
2686 | |
2687 head.appendChild(script); | |
2688 | |
2689 // We handle everything using the script element injection | |
2690 return undefined; | |
2691 } | |
2692 | |
2693 var requestDone = false; | |
2694 | |
2695 // Create the request object; Microsoft failed to properly | |
2696 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available | |
2697 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); | |
2698 | |
2699 // Open the socket | |
2700 // Passing null username, generates a login popup on Opera (#2865) | |
2701 if( s.username ) | |
2702 xhr.open(type, s.url, s.async, s.username, s.password); | |
2703 else | |
2704 xhr.open(type, s.url, s.async); | |
2705 | |
2706 // Need an extra try/catch for cross domain requests in Firefox 3 | |
2707 try { | |
2708 // Set the correct header, if data is being sent | |
2709 if ( s.data ) | |
2710 xhr.setRequestHeader("Content-Type", s.contentType); | |
2711 | |
2712 // Set the If-Modified-Since header, if ifModified mode. | |
2713 if ( s.ifModified ) | |
2714 xhr.setRequestHeader("If-Modified-Since", | |
2715 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); | |
2716 | |
2717 // Set header so the called script knows that it's an XMLHttpRequest | |
2718 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | |
2719 | |
2720 // Set the Accepts header for the server, depending on the dataType | |
2721 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? | |
2722 s.accepts[ s.dataType ] + ", */*" : | |
2723 s.accepts._default ); | |
2724 } catch(e){} | |
2725 | |
2726 // Allow custom headers/mimetypes | |
2727 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { | |
2728 // cleanup active request counter | |
2729 s.global && jQuery.active--; | |
2730 // close opended socket | |
2731 xhr.abort(); | |
2732 return false; | |
2733 } | |
2734 | |
2735 if ( s.global ) | |
2736 jQuery.event.trigger("ajaxSend", [xhr, s]); | |
2737 | |
2738 // Wait for a response to come back | |
2739 var onreadystatechange = function(isTimeout){ | |
2740 // The transfer is complete and the data is available, or the request timed out | |
2741 if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { | |
2742 requestDone = true; | |
2743 | |
2744 // clear poll interval | |
2745 if (ival) { | |
2746 clearInterval(ival); | |
2747 ival = null; | |
2748 } | |
2749 | |
2750 status = isTimeout == "timeout" ? "timeout" : | |
2751 !jQuery.httpSuccess( xhr ) ? "error" : | |
2752 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" : | |
2753 "success"; | |
2754 | |
2755 if ( status == "success" ) { | |
2756 // Watch for, and catch, XML document parse errors | |
2757 try { | |
2758 // process the data (runs the xml through httpData regardless of callback) | |
2759 data = jQuery.httpData( xhr, s.dataType, s.dataFilter ); | |
2760 } catch(e) { | |
2761 status = "parsererror"; | |
2762 } | |
2763 } | |
2764 | |
2765 // Make sure that the request was successful or notmodified | |
2766 if ( status == "success" ) { | |
2767 // Cache Last-Modified header, if ifModified mode. | |
2768 var modRes; | |
2769 try { | |
2770 modRes = xhr.getResponseHeader("Last-Modified"); | |
2771 } catch(e) {} // swallow exception thrown by FF if header is not available | |
2772 | |
2773 if ( s.ifModified && modRes ) | |
2774 jQuery.lastModified[s.url] = modRes; | |
2775 | |
2776 // JSONP handles its own success callback | |
2777 if ( !jsonp ) | |
2778 success(); | |
2779 } else | |
2780 jQuery.handleError(s, xhr, status); | |
2781 | |
2782 // Fire the complete handlers | |
2783 complete(); | |
2784 | |
2785 // Stop memory leaks | |
2786 if ( s.async ) | |
2787 xhr = null; | |
2788 } | |
2789 }; | |
2790 | |
2791 if ( s.async ) { | |
2792 // don't attach the handler to the request, just poll it instead | |
2793 var ival = setInterval(onreadystatechange, 13); | |
2794 | |
2795 // Timeout checker | |
2796 if ( s.timeout > 0 ) | |
2797 setTimeout(function(){ | |
2798 // Check to see if the request is still happening | |
2799 if ( xhr ) { | |
2800 // Cancel the request | |
2801 xhr.abort(); | |
2802 | |
2803 if( !requestDone ) | |
2804 onreadystatechange( "timeout" ); | |
2805 } | |
2806 }, s.timeout); | |
2807 } | |
2808 | |
2809 // Send the data | |
2810 try { | |
2811 xhr.send(s.data); | |
2812 } catch(e) { | |
2813 jQuery.handleError(s, xhr, null, e); | |
2814 } | |
2815 | |
2816 // firefox 1.5 doesn't fire statechange for sync requests | |
2817 if ( !s.async ) | |
2818 onreadystatechange(); | |
2819 | |
2820 function success(){ | |
2821 // If a local callback was specified, fire it and pass it the data | |
2822 if ( s.success ) | |
2823 s.success( data, status ); | |
2824 | |
2825 // Fire the global callback | |
2826 if ( s.global ) | |
2827 jQuery.event.trigger( "ajaxSuccess", [xhr, s] ); | |
2828 } | |
2829 | |
2830 function complete(){ | |
2831 // Process result | |
2832 if ( s.complete ) | |
2833 s.complete(xhr, status); | |
2834 | |
2835 // The request was completed | |
2836 if ( s.global ) | |
2837 jQuery.event.trigger( "ajaxComplete", [xhr, s] ); | |
2838 | |
2839 // Handle the global AJAX counter | |
2840 if ( s.global && ! --jQuery.active ) | |
2841 jQuery.event.trigger( "ajaxStop" ); | |
2842 } | |
2843 | |
2844 // return XMLHttpRequest to allow aborting the request etc. | |
2845 return xhr; | |
2846 }, | |
2847 | |
2848 handleError: function( s, xhr, status, e ) { | |
2849 // If a local callback was specified, fire it | |
2850 if ( s.error ) s.error( xhr, status, e ); | |
2851 | |
2852 // Fire the global callback | |
2853 if ( s.global ) | |
2854 jQuery.event.trigger( "ajaxError", [xhr, s, e] ); | |
2855 }, | |
2856 | |
2857 // Counter for holding the number of active queries | |
2858 active: 0, | |
2859 | |
2860 // Determines if an XMLHttpRequest was successful or not | |
2861 httpSuccess: function( xhr ) { | |
2862 try { | |
2863 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 | |
2864 return !xhr.status && location.protocol == "file:" || | |
2865 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 || | |
2866 jQuery.browser.safari && xhr.status == undefined; | |
2867 } catch(e){} | |
2868 return false; | |
2869 }, | |
2870 | |
2871 // Determines if an XMLHttpRequest returns NotModified | |
2872 httpNotModified: function( xhr, url ) { | |
2873 try { | |
2874 var xhrRes = xhr.getResponseHeader("Last-Modified"); | |
2875 | |
2876 // Firefox always returns 200. check Last-Modified date | |
2877 return xhr.status == 304 || xhrRes == jQuery.lastModified[url] || | |
2878 jQuery.browser.safari && xhr.status == undefined; | |
2879 } catch(e){} | |
2880 return false; | |
2881 }, | |
2882 | |
2883 httpData: function( xhr, type, filter ) { | |
2884 var ct = xhr.getResponseHeader("content-type"), | |
2885 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, | |
2886 data = xml ? xhr.responseXML : xhr.responseText; | |
2887 | |
2888 if ( xml && data.documentElement.tagName == "parsererror" ) | |
2889 throw "parsererror"; | |
2890 | |
2891 // Allow a pre-filtering function to sanitize the response | |
2892 if( filter ) | |
2893 data = filter( data, type ); | |
2894 | |
2895 // If the type is "script", eval it in global context | |
2896 if ( type == "script" ) | |
2897 jQuery.globalEval( data ); | |
2898 | |
2899 // Get the JavaScript object, if JSON is used. | |
2900 if ( type == "json" ) | |
2901 data = eval("(" + data + ")"); | |
2902 | |
2903 return data; | |
2904 }, | |
2905 | |
2906 // Serialize an array of form elements or a set of | |
2907 // key/values into a query string | |
2908 param: function( a ) { | |
2909 var s = [ ]; | |
2910 | |
2911 function add( key, value ){ | |
2912 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); | |
2913 }; | |
2914 | |
2915 // If an array was passed in, assume that it is an array | |
2916 // of form elements | |
2917 if ( a.constructor == Array || a.jquery ) | |
2918 // Serialize the form elements | |
2919 jQuery.each( a, function(){ | |
2920 add( this.name, this.value ); | |
2921 }); | |
2922 | |
2923 // Otherwise, assume that it's an object of key/value pairs | |
2924 else | |
2925 // Serialize the key/values | |
2926 for ( var j in a ) | |
2927 // If the value is an array then the key names need to be repeated | |
2928 if ( a[j] && a[j].constructor == Array ) | |
2929 jQuery.each( a[j], function(){ | |
2930 add( j, this ); | |
2931 }); | |
2932 else | |
2933 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); | |
2934 | |
2935 // Return the resulting serialization | |
2936 return s.join("&").replace(/%20/g, "+"); | |
2937 } | |
2938 | |
2939 }); | |
2940 jQuery.fn.extend({ | |
2941 show: function(speed,callback){ | |
2942 return speed ? | |
2943 this.animate({ | |
2944 height: "show", width: "show", opacity: "show" | |
2945 }, speed, callback) : | |
2946 | |
2947 this.filter(":hidden").each(function(){ | |
2948 this.style.display = this.oldblock || ""; | |
2949 if ( jQuery.css(this,"display") == "none" ) { | |
2950 var elem = jQuery("<" + this.tagName + " />").appendTo("body"); | |
2951 this.style.display = elem.css("display"); | |
2952 // handle an edge condition where css is - div { display:none; } or similar | |
2953 if (this.style.display == "none") | |
2954 this.style.display = "block"; | |
2955 elem.remove(); | |
2956 } | |
2957 }).end(); | |
2958 }, | |
2959 | |
2960 hide: function(speed,callback){ | |
2961 return speed ? | |
2962 this.animate({ | |
2963 height: "hide", width: "hide", opacity: "hide" | |
2964 }, speed, callback) : | |
2965 | |
2966 this.filter(":visible").each(function(){ | |
2967 this.oldblock = this.oldblock || jQuery.css(this,"display"); | |
2968 this.style.display = "none"; | |
2969 }).end(); | |
2970 }, | |
2971 | |
2972 // Save the old toggle function | |
2973 _toggle: jQuery.fn.toggle, | |
2974 | |
2975 toggle: function( fn, fn2 ){ | |
2976 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? | |
2977 this._toggle.apply( this, arguments ) : | |
2978 fn ? | |
2979 this.animate({ | |
2980 height: "toggle", width: "toggle", opacity: "toggle" | |
2981 }, fn, fn2) : | |
2982 this.each(function(){ | |
2983 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); | |
2984 }); | |
2985 }, | |
2986 | |
2987 slideDown: function(speed,callback){ | |
2988 return this.animate({height: "show"}, speed, callback); | |
2989 }, | |
2990 | |
2991 slideUp: function(speed,callback){ | |
2992 return this.animate({height: "hide"}, speed, callback); | |
2993 }, | |
2994 | |
2995 slideToggle: function(speed, callback){ | |
2996 return this.animate({height: "toggle"}, speed, callback); | |
2997 }, | |
2998 | |
2999 fadeIn: function(speed, callback){ | |
3000 return this.animate({opacity: "show"}, speed, callback); | |
3001 }, | |
3002 | |
3003 fadeOut: function(speed, callback){ | |
3004 return this.animate({opacity: "hide"}, speed, callback); | |
3005 }, | |
3006 | |
3007 fadeTo: function(speed,to,callback){ | |
3008 return this.animate({opacity: to}, speed, callback); | |
3009 }, | |
3010 | |
3011 animate: function( prop, speed, easing, callback ) { | |
3012 var optall = jQuery.speed(speed, easing, callback); | |
3013 | |
3014 return this[ optall.queue === false ? "each" : "queue" ](function(){ | |
3015 if ( this.nodeType != 1) | |
3016 return false; | |
3017 | |
3018 var opt = jQuery.extend({}, optall), p, | |
3019 hidden = jQuery(this).is(":hidden"), self = this; | |
3020 | |
3021 for ( p in prop ) { | |
3022 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) | |
3023 return opt.complete.call(this); | |
3024 | |
3025 if ( p == "height" || p == "width" ) { | |
3026 // Store display property | |
3027 opt.display = jQuery.css(this, "display"); | |
3028 | |
3029 // Make sure that nothing sneaks out | |
3030 opt.overflow = this.style.overflow; | |
3031 } | |
3032 } | |
3033 | |
3034 if ( opt.overflow != null ) | |
3035 this.style.overflow = "hidden"; | |
3036 | |
3037 opt.curAnim = jQuery.extend({}, prop); | |
3038 | |
3039 jQuery.each( prop, function(name, val){ | |
3040 var e = new jQuery.fx( self, opt, name ); | |
3041 | |
3042 if ( /toggle|show|hide/.test(val) ) | |
3043 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop ); | |
3044 else { | |
3045 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), | |
3046 start = e.cur(true) || 0; | |
3047 | |
3048 if ( parts ) { | |
3049 var end = parseFloat(parts[2]), | |
3050 unit = parts[3] || "px"; | |
3051 | |
3052 // We need to compute starting value | |
3053 if ( unit != "px" ) { | |
3054 self.style[ name ] = (end || 1) + unit; | |
3055 start = ((end || 1) / e.cur(true)) * start; | |
3056 self.style[ name ] = start + unit; | |
3057 } | |
3058 | |
3059 // If a +=/-= token was provided, we're doing a relative animation | |
3060 if ( parts[1] ) | |
3061 end = ((parts[1] == "-=" ? -1 : 1) * end) + start; | |
3062 | |
3063 e.custom( start, end, unit ); | |
3064 } else | |
3065 e.custom( start, val, "" ); | |
3066 } | |
3067 }); | |
3068 | |
3069 // For JS strict compliance | |
3070 return true; | |
3071 }); | |
3072 }, | |
3073 | |
3074 queue: function(type, fn){ | |
3075 if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) { | |
3076 fn = type; | |
3077 type = "fx"; | |
3078 } | |
3079 | |
3080 if ( !type || (typeof type == "string" && !fn) ) | |
3081 return queue( this[0], type ); | |
3082 | |
3083 return this.each(function(){ | |
3084 if ( fn.constructor == Array ) | |
3085 queue(this, type, fn); | |
3086 else { | |
3087 queue(this, type).push( fn ); | |
3088 | |
3089 if ( queue(this, type).length == 1 ) | |
3090 fn.call(this); | |
3091 } | |
3092 }); | |
3093 }, | |
3094 | |
3095 stop: function(clearQueue, gotoEnd){ | |
3096 var timers = jQuery.timers; | |
3097 | |
3098 if (clearQueue) | |
3099 this.queue([]); | |
3100 | |
3101 this.each(function(){ | |
3102 // go in reverse order so anything added to the queue during the loop is ignored | |
3103 for ( var i = timers.length - 1; i >= 0; i-- ) | |
3104 if ( timers[i].elem == this ) { | |
3105 if (gotoEnd) | |
3106 // force the next step to be the last | |
3107 timers[i](true); | |
3108 timers.splice(i, 1); | |
3109 } | |
3110 }); | |
3111 | |
3112 // start the next in the queue if the last step wasn't forced | |
3113 if (!gotoEnd) | |
3114 this.dequeue(); | |
3115 | |
3116 return this; | |
3117 } | |
3118 | |
3119 }); | |
3120 | |
3121 var queue = function( elem, type, array ) { | |
3122 if ( elem ){ | |
3123 | |
3124 type = type || "fx"; | |
3125 | |
3126 var q = jQuery.data( elem, type + "queue" ); | |
3127 | |
3128 if ( !q || array ) | |
3129 q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) ); | |
3130 | |
3131 } | |
3132 return q; | |
3133 }; | |
3134 | |
3135 jQuery.fn.dequeue = function(type){ | |
3136 type = type || "fx"; | |
3137 | |
3138 return this.each(function(){ | |
3139 var q = queue(this, type); | |
3140 | |
3141 q.shift(); | |
3142 | |
3143 if ( q.length ) | |
3144 q[0].call( this ); | |
3145 }); | |
3146 }; | |
3147 | |
3148 jQuery.extend({ | |
3149 | |
3150 speed: function(speed, easing, fn) { | |
3151 var opt = speed && speed.constructor == Object ? speed : { | |
3152 complete: fn || !fn && easing || | |
3153 jQuery.isFunction( speed ) && speed, | |
3154 duration: speed, | |
3155 easing: fn && easing || easing && easing.constructor != Function && easing | |
3156 }; | |
3157 | |
3158 opt.duration = (opt.duration && opt.duration.constructor == Number ? | |
3159 opt.duration : | |
3160 jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def; | |
3161 | |
3162 // Queueing | |
3163 opt.old = opt.complete; | |
3164 opt.complete = function(){ | |
3165 if ( opt.queue !== false ) | |
3166 jQuery(this).dequeue(); | |
3167 if ( jQuery.isFunction( opt.old ) ) | |
3168 opt.old.call( this ); | |
3169 }; | |
3170 | |
3171 return opt; | |
3172 }, | |
3173 | |
3174 easing: { | |
3175 linear: function( p, n, firstNum, diff ) { | |
3176 return firstNum + diff * p; | |
3177 }, | |
3178 swing: function( p, n, firstNum, diff ) { | |
3179 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; | |
3180 } | |
3181 }, | |
3182 | |
3183 timers: [], | |
3184 timerId: null, | |
3185 | |
3186 fx: function( elem, options, prop ){ | |
3187 this.options = options; | |
3188 this.elem = elem; | |
3189 this.prop = prop; | |
3190 | |
3191 if ( !options.orig ) | |
3192 options.orig = {}; | |
3193 } | |
3194 | |
3195 }); | |
3196 | |
3197 jQuery.fx.prototype = { | |
3198 | |
3199 // Simple function for setting a style value | |
3200 update: function(){ | |
3201 if ( this.options.step ) | |
3202 this.options.step.call( this.elem, this.now, this ); | |
3203 | |
3204 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); | |
3205 | |
3206 // Set display property to block for height/width animations | |
3207 if ( this.prop == "height" || this.prop == "width" ) | |
3208 this.elem.style.display = "block"; | |
3209 }, | |
3210 | |
3211 // Get the current size | |
3212 cur: function(force){ | |
3213 if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null ) | |
3214 return this.elem[ this.prop ]; | |
3215 | |
3216 var r = parseFloat(jQuery.css(this.elem, this.prop, force)); | |
3217 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0; | |
3218 }, | |
3219 | |
3220 // Start an animation from one number to another | |
3221 custom: function(from, to, unit){ | |
3222 this.startTime = now(); | |
3223 this.start = from; | |
3224 this.end = to; | |
3225 this.unit = unit || this.unit || "px"; | |
3226 this.now = this.start; | |
3227 this.pos = this.state = 0; | |
3228 this.update(); | |
3229 | |
3230 var self = this; | |
3231 function t(gotoEnd){ | |
3232 return self.step(gotoEnd); | |
3233 } | |
3234 | |
3235 t.elem = this.elem; | |
3236 | |
3237 jQuery.timers.push(t); | |
3238 | |
3239 if ( jQuery.timerId == null ) { | |
3240 jQuery.timerId = setInterval(function(){ | |
3241 var timers = jQuery.timers; | |
3242 | |
3243 for ( var i = 0; i < timers.length; i++ ) | |
3244 if ( !timers[i]() ) | |
3245 timers.splice(i--, 1); | |
3246 | |
3247 if ( !timers.length ) { | |
3248 clearInterval( jQuery.timerId ); | |
3249 jQuery.timerId = null; | |
3250 } | |
3251 }, 13); | |
3252 } | |
3253 }, | |
3254 | |
3255 // Simple 'show' function | |
3256 show: function(){ | |
3257 // Remember where we started, so that we can go back to it later | |
3258 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); | |
3259 this.options.show = true; | |
3260 | |
3261 // Begin the animation | |
3262 this.custom(0, this.cur()); | |
3263 | |
3264 // Make sure that we start at a small width/height to avoid any | |
3265 // flash of content | |
3266 if ( this.prop == "width" || this.prop == "height" ) | |
3267 this.elem.style[this.prop] = "1px"; | |
3268 | |
3269 // Start by showing the element | |
3270 jQuery(this.elem).show(); | |
3271 }, | |
3272 | |
3273 // Simple 'hide' function | |
3274 hide: function(){ | |
3275 // Remember where we started, so that we can go back to it later | |
3276 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); | |
3277 this.options.hide = true; | |
3278 | |
3279 // Begin the animation | |
3280 this.custom(this.cur(), 0); | |
3281 }, | |
3282 | |
3283 // Each step of an animation | |
3284 step: function(gotoEnd){ | |
3285 var t = now(); | |
3286 | |
3287 if ( gotoEnd || t > this.options.duration + this.startTime ) { | |
3288 this.now = this.end; | |
3289 this.pos = this.state = 1; | |
3290 this.update(); | |
3291 | |
3292 this.options.curAnim[ this.prop ] = true; | |
3293 | |
3294 var done = true; | |
3295 for ( var i in this.options.curAnim ) | |
3296 if ( this.options.curAnim[i] !== true ) | |
3297 done = false; | |
3298 | |
3299 if ( done ) { | |
3300 if ( this.options.display != null ) { | |
3301 // Reset the overflow | |
3302 this.elem.style.overflow = this.options.overflow; | |
3303 | |
3304 // Reset the display | |
3305 this.elem.style.display = this.options.display; | |
3306 if ( jQuery.css(this.elem, "display") == "none" ) | |
3307 this.elem.style.display = "block"; | |
3308 } | |
3309 | |
3310 // Hide the element if the "hide" operation was done | |
3311 if ( this.options.hide ) | |
3312 this.elem.style.display = "none"; | |
3313 | |
3314 // Reset the properties, if the item has been hidden or shown | |
3315 if ( this.options.hide || this.options.show ) | |
3316 for ( var p in this.options.curAnim ) | |
3317 jQuery.attr(this.elem.style, p, this.options.orig[p]); | |
3318 } | |
3319 | |
3320 if ( done ) | |
3321 // Execute the complete function | |
3322 this.options.complete.call( this.elem ); | |
3323 | |
3324 return false; | |
3325 } else { | |
3326 var n = t - this.startTime; | |
3327 this.state = n / this.options.duration; | |
3328 | |
3329 // Perform the easing function, defaults to swing | |
3330 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration); | |
3331 this.now = this.start + ((this.end - this.start) * this.pos); | |
3332 | |
3333 // Perform the next step of the animation | |
3334 this.update(); | |
3335 } | |
3336 | |
3337 return true; | |
3338 } | |
3339 | |
3340 }; | |
3341 | |
3342 jQuery.extend( jQuery.fx, { | |
3343 speeds:{ | |
3344 slow: 600, | |
3345 fast: 200, | |
3346 // Default speed | |
3347 def: 400 | |
3348 }, | |
3349 step: { | |
3350 scrollLeft: function(fx){ | |
3351 fx.elem.scrollLeft = fx.now; | |
3352 }, | |
3353 | |
3354 scrollTop: function(fx){ | |
3355 fx.elem.scrollTop = fx.now; | |
3356 }, | |
3357 | |
3358 opacity: function(fx){ | |
3359 jQuery.attr(fx.elem.style, "opacity", fx.now); | |
3360 }, | |
3361 | |
3362 _default: function(fx){ | |
3363 fx.elem.style[ fx.prop ] = fx.now + fx.unit; | |
3364 } | |
3365 } | |
3366 }); | |
3367 // The Offset Method | |
3368 // Originally By Brandon Aaron, part of the Dimension Plugin | |
3369 // http://jquery.com/plugins/project/dimensions | |
3370 jQuery.fn.offset = function() { | |
3371 var left = 0, top = 0, elem = this[0], results; | |
3372 | |
3373 if ( elem ) with ( jQuery.browser ) { | |
3374 var parent = elem.parentNode, | |
3375 offsetChild = elem, | |
3376 offsetParent = elem.offsetParent, | |
3377 doc = elem.ownerDocument, | |
3378 safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent), | |
3379 css = jQuery.curCSS, | |
3380 fixed = css(elem, "position") == "fixed"; | |
3381 | |
3382 // Use getBoundingClientRect if available | |
3383 if ( !(mozilla && elem == document.body) && elem.getBoundingClientRect ) { | |
3384 var box = elem.getBoundingClientRect(); | |
3385 | |
3386 // Add the document scroll offsets | |
3387 add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), | |
3388 box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop)); | |
3389 | |
3390 // IE adds the HTML element's border, by default it is medium which is 2px | |
3391 // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; } | |
3392 // IE 7 standards mode, the border is always 2px | |
3393 // This border/offset is typically represented by the clientLeft and clientTop properties | |
3394 // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS | |
3395 // Therefore this method will be off by 2px in IE while in quirksmode | |
3396 add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop ); | |
3397 | |
3398 // Otherwise loop through the offsetParents and parentNodes | |
3399 } else { | |
3400 | |
3401 // Initial element offsets | |
3402 add( elem.offsetLeft, elem.offsetTop ); | |
3403 | |
3404 // Get parent offsets | |
3405 while ( offsetParent ) { | |
3406 // Add offsetParent offsets | |
3407 add( offsetParent.offsetLeft, offsetParent.offsetTop ); | |
3408 | |
3409 // Mozilla and Safari > 2 does not include the border on offset parents | |
3410 // However Mozilla adds the border for table or table cells | |
3411 if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 ) | |
3412 border( offsetParent ); | |
3413 | |
3414 // Add the document scroll offsets if position is fixed on any offsetParent | |
3415 if ( !fixed && css(offsetParent, "position") == "fixed" ) | |
3416 fixed = true; | |
3417 | |
3418 // Set offsetChild to previous offsetParent unless it is the body element | |
3419 offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent; | |
3420 // Get next offsetParent | |
3421 offsetParent = offsetParent.offsetParent; | |
3422 } | |
3423 | |
3424 // Get parent scroll offsets | |
3425 while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) { | |
3426 // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug | |
3427 if ( !/^inline|table.*$/i.test(css(parent, "display")) ) | |
3428 // Subtract parent scroll offsets | |
3429 add( -parent.scrollLeft, -parent.scrollTop ); | |
3430 | |
3431 // Mozilla does not add the border for a parent that has overflow != visible | |
3432 if ( mozilla && css(parent, "overflow") != "visible" ) | |
3433 border( parent ); | |
3434 | |
3435 // Get next parent | |
3436 parent = parent.parentNode; | |
3437 } | |
3438 | |
3439 // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild | |
3440 // Mozilla doubles body offsets with a non-absolutely positioned offsetChild | |
3441 if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) || | |
3442 (mozilla && css(offsetChild, "position") != "absolute") ) | |
3443 add( -doc.body.offsetLeft, -doc.body.offsetTop ); | |
3444 | |
3445 // Add the document scroll offsets if position is fixed | |
3446 if ( fixed ) | |
3447 add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), | |
3448 Math.max(doc.documentElement.scrollTop, doc.body.scrollTop)); | |
3449 } | |
3450 | |
3451 // Return an object with top and left properties | |
3452 results = { top: top, left: left }; | |
3453 } | |
3454 | |
3455 function border(elem) { | |
3456 add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) ); | |
3457 } | |
3458 | |
3459 function add(l, t) { | |
3460 left += parseInt(l, 10) || 0; | |
3461 top += parseInt(t, 10) || 0; | |
3462 } | |
3463 | |
3464 return results; | |
3465 }; | |
3466 | |
3467 | |
3468 jQuery.fn.extend({ | |
3469 position: function() { | |
3470 var left = 0, top = 0, results; | |
3471 | |
3472 if ( this[0] ) { | |
3473 // Get *real* offsetParent | |
3474 var offsetParent = this.offsetParent(), | |
3475 | |
3476 // Get correct offsets | |
3477 offset = this.offset(), | |
3478 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset(); | |
3479 | |
3480 // Subtract element margins | |
3481 // note: when an element has margin: auto the offsetLeft and marginLeft | |
3482 // are the same in Safari causing offset.left to incorrectly be 0 | |
3483 offset.top -= num( this, 'marginTop' ); | |
3484 offset.left -= num( this, 'marginLeft' ); | |
3485 | |
3486 // Add offsetParent borders | |
3487 parentOffset.top += num( offsetParent, 'borderTopWidth' ); | |
3488 parentOffset.left += num( offsetParent, 'borderLeftWidth' ); | |
3489 | |
3490 // Subtract the two offsets | |
3491 results = { | |
3492 top: offset.top - parentOffset.top, | |
3493 left: offset.left - parentOffset.left | |
3494 }; | |
3495 } | |
3496 | |
3497 return results; | |
3498 }, | |
3499 | |
3500 offsetParent: function() { | |
3501 var offsetParent = this[0].offsetParent; | |
3502 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) | |
3503 offsetParent = offsetParent.offsetParent; | |
3504 return jQuery(offsetParent); | |
3505 } | |
3506 }); | |
3507 | |
3508 | |
3509 // Create scrollLeft and scrollTop methods | |
3510 jQuery.each( ['Left', 'Top'], function(i, name) { | |
3511 var method = 'scroll' + name; | |
3512 | |
3513 jQuery.fn[ method ] = function(val) { | |
3514 if (!this[0]) return; | |
3515 | |
3516 return val != undefined ? | |
3517 | |
3518 // Set the scroll offset | |
3519 this.each(function() { | |
3520 this == window || this == document ? | |
3521 window.scrollTo( | |
3522 !i ? val : jQuery(window).scrollLeft(), | |
3523 i ? val : jQuery(window).scrollTop() | |
3524 ) : | |
3525 this[ method ] = val; | |
3526 }) : | |
3527 | |
3528 // Return the scroll offset | |
3529 this[0] == window || this[0] == document ? | |
3530 self[ i ? 'pageYOffset' : 'pageXOffset' ] || | |
3531 jQuery.boxModel && document.documentElement[ method ] || | |
3532 document.body[ method ] : | |
3533 this[0][ method ]; | |
3534 }; | |
3535 }); | |
3536 // Create innerHeight, innerWidth, outerHeight and outerWidth methods | |
3537 jQuery.each([ "Height", "Width" ], function(i, name){ | |
3538 | |
3539 var tl = i ? "Left" : "Top", // top or left | |
3540 br = i ? "Right" : "Bottom"; // bottom or right | |
3541 | |
3542 // innerHeight and innerWidth | |
3543 jQuery.fn["inner" + name] = function(){ | |
3544 return this[ name.toLowerCase() ]() + | |
3545 num(this, "padding" + tl) + | |
3546 num(this, "padding" + br); | |
3547 }; | |
3548 | |
3549 // outerHeight and outerWidth | |
3550 jQuery.fn["outer" + name] = function(margin) { | |
3551 return this["inner" + name]() + | |
3552 num(this, "border" + tl + "Width") + | |
3553 num(this, "border" + br + "Width") + | |
3554 (margin ? | |
3555 num(this, "margin" + tl) + num(this, "margin" + br) : 0); | |
3556 }; | |
3557 | |
3558 });})(); |