Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebApplication/MVC2/HeuristicLabWeb.PluginHost/HLWebPluginHost/Scripts/jquery-1.4.1.js @ 5728

Last change on this file since 5728 was 4604, checked in by dkahn, 14 years ago

#1198 Imported new Plugin Host solution for the new MVC2 based web application

File size: 164.8 KB
Line 
1/*!
2 * jQuery JavaScript Library v1.4.1
3 * http://jquery.com/
4 *
5 * Copyright 2010, John Resig
6 *
7 * Includes Sizzle.js
8 * http://sizzlejs.com/
9 * Copyright 2010, The Dojo Foundation
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining
12 * a copy of this software and associated documentation files (the
13 * "Software"), to deal in the Software without restriction, including
14 * without limitation the rights to use, copy, modify, merge, publish,
15 * distribute, sublicense, and/or sell copies of the Software, and to
16 * permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be
20 * included in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Date: Mon Jan 25 19:43:33 2010 -0500
30 */
31(function( window, undefined ) {
32
33// Define a local copy of jQuery
34var jQuery = function( selector, context ) {
35    // The jQuery object is actually just the init constructor 'enhanced'
36    return new jQuery.fn.init( selector, context );
37  },
38
39  // Map over jQuery in case of overwrite
40  _jQuery = window.jQuery,
41
42  // Map over the $ in case of overwrite
43  _$ = window.$,
44
45  // Use the correct document accordingly with window argument (sandbox)
46  document = window.document,
47
48  // A central reference to the root jQuery(document)
49  rootjQuery,
50
51  // A simple way to check for HTML strings or ID strings
52  // (both of which we optimize for)
53  quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
54
55  // Is it a simple selector
56  isSimple = /^.[^:#\[\.,]*$/,
57
58  // Check if a string has a non-whitespace character in it
59  rnotwhite = /\S/,
60
61  // Used for trimming whitespace
62  rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
63
64  // Match a standalone tag
65  rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
66
67  // Keep a UserAgent string for use with jQuery.browser
68  userAgent = navigator.userAgent,
69
70  // For matching the engine and version of the browser
71  browserMatch,
72 
73  // Has the ready events already been bound?
74  readyBound = false,
75 
76  // The functions to execute on DOM ready
77  readyList = [],
78
79  // The ready event handler
80  DOMContentLoaded,
81
82  // Save a reference to some core methods
83  toString = Object.prototype.toString,
84  hasOwnProperty = Object.prototype.hasOwnProperty,
85  push = Array.prototype.push,
86  slice = Array.prototype.slice,
87  indexOf = Array.prototype.indexOf;
88
89jQuery.fn = jQuery.prototype = {
90  init: function( selector, context ) {
91    var match, elem, ret, doc;
92
93    // Handle $(""), $(null), or $(undefined)
94    if ( !selector ) {
95      return this;
96    }
97
98    // Handle $(DOMElement)
99    if ( selector.nodeType ) {
100      this.context = this[0] = selector;
101      this.length = 1;
102      return this;
103    }
104
105    // Handle HTML strings
106    if ( typeof selector === "string" ) {
107      // Are we dealing with HTML string or an ID?
108      match = quickExpr.exec( selector );
109
110      // Verify a match, and that no context was specified for #id
111      if ( match && (match[1] || !context) ) {
112
113        // HANDLE: $(html) -> $(array)
114        if ( match[1] ) {
115          doc = (context ? context.ownerDocument || context : document);
116
117          // If a single string is passed in and it's a single tag
118          // just do a createElement and skip the rest
119          ret = rsingleTag.exec( selector );
120
121          if ( ret ) {
122            if ( jQuery.isPlainObject( context ) ) {
123              selector = [ document.createElement( ret[1] ) ];
124              jQuery.fn.attr.call( selector, context, true );
125
126            } else {
127              selector = [ doc.createElement( ret[1] ) ];
128            }
129
130          } else {
131            ret = buildFragment( [ match[1] ], [ doc ] );
132            selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
133          }
134
135        // HANDLE: $("#id")
136        } else {
137          elem = document.getElementById( match[2] );
138
139          if ( elem ) {
140            // Handle the case where IE and Opera return items
141            // by name instead of ID
142            if ( elem.id !== match[2] ) {
143              return rootjQuery.find( selector );
144            }
145
146            // Otherwise, we inject the element directly into the jQuery object
147            this.length = 1;
148            this[0] = elem;
149          }
150
151          this.context = document;
152          this.selector = selector;
153          return this;
154        }
155
156      // HANDLE: $("TAG")
157      } else if ( !context && /^\w+$/.test( selector ) ) {
158        this.selector = selector;
159        this.context = document;
160        selector = document.getElementsByTagName( selector );
161
162      // HANDLE: $(expr, $(...))
163      } else if ( !context || context.jquery ) {
164        return (context || rootjQuery).find( selector );
165
166      // HANDLE: $(expr, context)
167      // (which is just equivalent to: $(context).find(expr)
168      } else {
169        return jQuery( context ).find( selector );
170      }
171
172    // HANDLE: $(function)
173    // Shortcut for document ready
174    } else if ( jQuery.isFunction( selector ) ) {
175      return rootjQuery.ready( selector );
176    }
177
178    if (selector.selector !== undefined) {
179      this.selector = selector.selector;
180      this.context = selector.context;
181    }
182
183    return jQuery.isArray( selector ) ?
184      this.setArray( selector ) :
185      jQuery.makeArray( selector, this );
186  },
187
188  // Start with an empty selector
189  selector: "",
190
191  // The current version of jQuery being used
192  jquery: "1.4.1",
193
194  // The default length of a jQuery object is 0
195  length: 0,
196
197  // The number of elements contained in the matched element set
198  size: function() {
199    return this.length;
200  },
201
202  toArray: function() {
203    return slice.call( this, 0 );
204  },
205
206  // Get the Nth element in the matched element set OR
207  // Get the whole matched element set as a clean array
208  get: function( num ) {
209    return num == null ?
210
211      // Return a 'clean' array
212      this.toArray() :
213
214      // Return just the object
215      ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
216  },
217
218  // Take an array of elements and push it onto the stack
219  // (returning the new matched element set)
220  pushStack: function( elems, name, selector ) {
221    // Build a new jQuery matched element set
222    var ret = jQuery( elems || null );
223
224    // Add the old object onto the stack (as a reference)
225    ret.prevObject = this;
226
227    ret.context = this.context;
228
229    if ( name === "find" ) {
230      ret.selector = this.selector + (this.selector ? " " : "") + selector;
231    } else if ( name ) {
232      ret.selector = this.selector + "." + name + "(" + selector + ")";
233    }
234
235    // Return the newly-formed element set
236    return ret;
237  },
238
239  // Force the current matched set of elements to become
240  // the specified array of elements (destroying the stack in the process)
241  // You should use pushStack() in order to do this, but maintain the stack
242  setArray: function( elems ) {
243    // Resetting the length to 0, then using the native Array push
244    // is a super-fast way to populate an object with array-like properties
245    this.length = 0;
246    push.apply( this, elems );
247
248    return this;
249  },
250
251  // Execute a callback for every element in the matched set.
252  // (You can seed the arguments with an array of args, but this is
253  // only used internally.)
254  each: function( callback, args ) {
255    return jQuery.each( this, callback, args );
256  },
257 
258  ready: function( fn ) {
259    // Attach the listeners
260    jQuery.bindReady();
261
262    // If the DOM is already ready
263    if ( jQuery.isReady ) {
264      // Execute the function immediately
265      fn.call( document, jQuery );
266
267    // Otherwise, remember the function for later
268    } else if ( readyList ) {
269      // Add the function to the wait list
270      readyList.push( fn );
271    }
272
273    return this;
274  },
275 
276  eq: function( i ) {
277    return i === -1 ?
278      this.slice( i ) :
279      this.slice( i, +i + 1 );
280  },
281
282  first: function() {
283    return this.eq( 0 );
284  },
285
286  last: function() {
287    return this.eq( -1 );
288  },
289
290  slice: function() {
291    return this.pushStack( slice.apply( this, arguments ),
292      "slice", slice.call(arguments).join(",") );
293  },
294
295  map: function( callback ) {
296    return this.pushStack( jQuery.map(this, function( elem, i ) {
297      return callback.call( elem, i, elem );
298    }));
299  },
300 
301  end: function() {
302    return this.prevObject || jQuery(null);
303  },
304
305  // For internal use only.
306  // Behaves like an Array's method, not like a jQuery method.
307  push: push,
308  sort: [].sort,
309  splice: [].splice
310};
311
312// Give the init function the jQuery prototype for later instantiation
313jQuery.fn.init.prototype = jQuery.fn;
314
315jQuery.extend = jQuery.fn.extend = function() {
316  // copy reference to target object
317  var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
318
319  // Handle a deep copy situation
320  if ( typeof target === "boolean" ) {
321    deep = target;
322    target = arguments[1] || {};
323    // skip the boolean and the target
324    i = 2;
325  }
326
327  // Handle case when target is a string or something (possible in deep copy)
328  if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
329    target = {};
330  }
331
332  // extend jQuery itself if only one argument is passed
333  if ( length === i ) {
334    target = this;
335    --i;
336  }
337
338  for ( ; i < length; i++ ) {
339    // Only deal with non-null/undefined values
340    if ( (options = arguments[ i ]) != null ) {
341      // Extend the base object
342      for ( name in options ) {
343        src = target[ name ];
344        copy = options[ name ];
345
346        // Prevent never-ending loop
347        if ( target === copy ) {
348          continue;
349        }
350
351        // Recurse if we're merging object literal values or arrays
352        if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
353          var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
354            : jQuery.isArray(copy) ? [] : {};
355
356          // Never move original objects, clone them
357          target[ name ] = jQuery.extend( deep, clone, copy );
358
359        // Don't bring in undefined values
360        } else if ( copy !== undefined ) {
361          target[ name ] = copy;
362        }
363      }
364    }
365  }
366
367  // Return the modified object
368  return target;
369};
370
371jQuery.extend({
372  noConflict: function( deep ) {
373    window.$ = _$;
374
375    if ( deep ) {
376      window.jQuery = _jQuery;
377    }
378
379    return jQuery;
380  },
381 
382  // Is the DOM ready to be used? Set to true once it occurs.
383  isReady: false,
384 
385  // Handle when the DOM is ready
386  ready: function() {
387    // Make sure that the DOM is not already loaded
388    if ( !jQuery.isReady ) {
389      // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
390      if ( !document.body ) {
391        return setTimeout( jQuery.ready, 13 );
392      }
393
394      // Remember that the DOM is ready
395      jQuery.isReady = true;
396
397      // If there are functions bound, to execute
398      if ( readyList ) {
399        // Execute all of them
400        var fn, i = 0;
401        while ( (fn = readyList[ i++ ]) ) {
402          fn.call( document, jQuery );
403        }
404
405        // Reset the list of functions
406        readyList = null;
407      }
408
409      // Trigger any bound ready events
410      if ( jQuery.fn.triggerHandler ) {
411        jQuery( document ).triggerHandler( "ready" );
412      }
413    }
414  },
415 
416  bindReady: function() {
417    if ( readyBound ) {
418      return;
419    }
420
421    readyBound = true;
422
423    // Catch cases where $(document).ready() is called after the
424    // browser event has already occurred.
425    if ( document.readyState === "complete" ) {
426      return jQuery.ready();
427    }
428
429    // Mozilla, Opera and webkit nightlies currently support this event
430    if ( document.addEventListener ) {
431      // Use the handy event callback
432      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
433     
434      // A fallback to window.onload, that will always work
435      window.addEventListener( "load", jQuery.ready, false );
436
437    // If IE event model is used
438    } else if ( document.attachEvent ) {
439      // ensure firing before onload,
440      // maybe late but safe also for iframes
441      document.attachEvent("onreadystatechange", DOMContentLoaded);
442     
443      // A fallback to window.onload, that will always work
444      window.attachEvent( "onload", jQuery.ready );
445
446      // If IE and not a frame
447      // continually check to see if the document is ready
448      var toplevel = false;
449
450      try {
451        toplevel = window.frameElement == null;
452      } catch(e) {}
453
454      if ( document.documentElement.doScroll && toplevel ) {
455        doScrollCheck();
456      }
457    }
458  },
459
460  // See test/unit/core.js for details concerning isFunction.
461  // Since version 1.3, DOM methods and functions like alert
462  // aren't supported. They return false on IE (#2968).
463  isFunction: function( obj ) {
464    return toString.call(obj) === "[object Function]";
465  },
466
467  isArray: function( obj ) {
468    return toString.call(obj) === "[object Array]";
469  },
470
471  isPlainObject: function( obj ) {
472    // Must be an Object.
473    // Because of IE, we also have to check the presence of the constructor property.
474    // Make sure that DOM nodes and window objects don't pass through, as well
475    if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
476      return false;
477    }
478   
479    // Not own constructor property must be Object
480    if ( obj.constructor
481      && !hasOwnProperty.call(obj, "constructor")
482      && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
483      return false;
484    }
485   
486    // Own properties are enumerated firstly, so to speed up,
487    // if last one is own, then all properties are own.
488 
489    var key;
490    for ( key in obj ) {}
491   
492    return key === undefined || hasOwnProperty.call( obj, key );
493  },
494
495  isEmptyObject: function( obj ) {
496    for ( var name in obj ) {
497      return false;
498    }
499    return true;
500  },
501 
502  error: function( msg ) {
503    throw msg;
504  },
505 
506  parseJSON: function( data ) {
507    if ( typeof data !== "string" || !data ) {
508      return null;
509    }
510   
511    // Make sure the incoming data is actual JSON
512    // Logic borrowed from http://json.org/json2.js
513    if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
514      .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
515      .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
516
517      // Try to use the native JSON parser first
518      return window.JSON && window.JSON.parse ?
519        window.JSON.parse( data ) :
520        (new Function("return " + data))();
521
522    } else {
523      jQuery.error( "Invalid JSON: " + data );
524    }
525  },
526
527  noop: function() {},
528
529  // Evalulates a script in a global context
530  globalEval: function( data ) {
531    if ( data && rnotwhite.test(data) ) {
532      // Inspired by code by Andrea Giammarchi
533      // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
534      var head = document.getElementsByTagName("head")[0] || document.documentElement,
535        script = document.createElement("script");
536
537      script.type = "text/javascript";
538
539      if ( jQuery.support.scriptEval ) {
540        script.appendChild( document.createTextNode( data ) );
541      } else {
542        script.text = data;
543      }
544
545      // Use insertBefore instead of appendChild to circumvent an IE6 bug.
546      // This arises when a base node is used (#2709).
547      head.insertBefore( script, head.firstChild );
548      head.removeChild( script );
549    }
550  },
551
552  nodeName: function( elem, name ) {
553    return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
554  },
555
556  // args is for internal usage only
557  each: function( object, callback, args ) {
558    var name, i = 0,
559      length = object.length,
560      isObj = length === undefined || jQuery.isFunction(object);
561
562    if ( args ) {
563      if ( isObj ) {
564        for ( name in object ) {
565          if ( callback.apply( object[ name ], args ) === false ) {
566            break;
567          }
568        }
569      } else {
570        for ( ; i < length; ) {
571          if ( callback.apply( object[ i++ ], args ) === false ) {
572            break;
573          }
574        }
575      }
576
577    // A special, fast, case for the most common use of each
578    } else {
579      if ( isObj ) {
580        for ( name in object ) {
581          if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
582            break;
583          }
584        }
585      } else {
586        for ( var value = object[0];
587          i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
588      }
589    }
590
591    return object;
592  },
593
594  trim: function( text ) {
595    return (text || "").replace( rtrim, "" );
596  },
597
598  // results is for internal usage only
599  makeArray: function( array, results ) {
600    var ret = results || [];
601
602    if ( array != null ) {
603      // The window, strings (and functions) also have 'length'
604      // The extra typeof function check is to prevent crashes
605      // in Safari 2 (See: #3039)
606      if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
607        push.call( ret, array );
608      } else {
609        jQuery.merge( ret, array );
610      }
611    }
612
613    return ret;
614  },
615
616  inArray: function( elem, array ) {
617    if ( array.indexOf ) {
618      return array.indexOf( elem );
619    }
620
621    for ( var i = 0, length = array.length; i < length; i++ ) {
622      if ( array[ i ] === elem ) {
623        return i;
624      }
625    }
626
627    return -1;
628  },
629
630  merge: function( first, second ) {
631    var i = first.length, j = 0;
632
633    if ( typeof second.length === "number" ) {
634      for ( var l = second.length; j < l; j++ ) {
635        first[ i++ ] = second[ j ];
636      }
637    } else {
638      while ( second[j] !== undefined ) {
639        first[ i++ ] = second[ j++ ];
640      }
641    }
642
643    first.length = i;
644
645    return first;
646  },
647
648  grep: function( elems, callback, inv ) {
649    var ret = [];
650
651    // Go through the array, only saving the items
652    // that pass the validator function
653    for ( var i = 0, length = elems.length; i < length; i++ ) {
654      if ( !inv !== !callback( elems[ i ], i ) ) {
655        ret.push( elems[ i ] );
656      }
657    }
658
659    return ret;
660  },
661
662  // arg is for internal usage only
663  map: function( elems, callback, arg ) {
664    var ret = [], value;
665
666    // Go through the array, translating each of the items to their
667    // new value (or values).
668    for ( var i = 0, length = elems.length; i < length; i++ ) {
669      value = callback( elems[ i ], i, arg );
670
671      if ( value != null ) {
672        ret[ ret.length ] = value;
673      }
674    }
675
676    return ret.concat.apply( [], ret );
677  },
678
679  // A global GUID counter for objects
680  guid: 1,
681
682  proxy: function( fn, proxy, thisObject ) {
683    if ( arguments.length === 2 ) {
684      if ( typeof proxy === "string" ) {
685        thisObject = fn;
686        fn = thisObject[ proxy ];
687        proxy = undefined;
688
689      } else if ( proxy && !jQuery.isFunction( proxy ) ) {
690        thisObject = proxy;
691        proxy = undefined;
692      }
693    }
694
695    if ( !proxy && fn ) {
696      proxy = function() {
697        return fn.apply( thisObject || this, arguments );
698      };
699    }
700
701    // Set the guid of unique handler to the same of original handler, so it can be removed
702    if ( fn ) {
703      proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
704    }
705
706    // So proxy can be declared as an argument
707    return proxy;
708  },
709
710  // Use of jQuery.browser is frowned upon.
711  // More details: http://docs.jquery.com/Utilities/jQuery.browser
712  uaMatch: function( ua ) {
713    ua = ua.toLowerCase();
714
715    var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
716      /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
717      /(msie) ([\w.]+)/.exec( ua ) ||
718      !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
719        [];
720
721    return { browser: match[1] || "", version: match[2] || "0" };
722  },
723
724  browser: {}
725});
726
727browserMatch = jQuery.uaMatch( userAgent );
728if ( browserMatch.browser ) {
729  jQuery.browser[ browserMatch.browser ] = true;
730  jQuery.browser.version = browserMatch.version;
731}
732
733// Deprecated, use jQuery.browser.webkit instead
734if ( jQuery.browser.webkit ) {
735  jQuery.browser.safari = true;
736}
737
738if ( indexOf ) {
739  jQuery.inArray = function( elem, array ) {
740    return indexOf.call( array, elem );
741  };
742}
743
744// All jQuery objects should point back to these
745rootjQuery = jQuery(document);
746
747// Cleanup functions for the document ready method
748if ( document.addEventListener ) {
749  DOMContentLoaded = function() {
750    document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
751    jQuery.ready();
752  };
753
754} else if ( document.attachEvent ) {
755  DOMContentLoaded = function() {
756    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
757    if ( document.readyState === "complete" ) {
758      document.detachEvent( "onreadystatechange", DOMContentLoaded );
759      jQuery.ready();
760    }
761  };
762}
763
764// The DOM ready check for Internet Explorer
765function doScrollCheck() {
766  if ( jQuery.isReady ) {
767    return;
768  }
769
770  try {
771    // If IE is used, use the trick by Diego Perini
772    // http://javascript.nwbox.com/IEContentLoaded/
773    document.documentElement.doScroll("left");
774  } catch( error ) {
775    setTimeout( doScrollCheck, 1 );
776    return;
777  }
778
779  // and execute any waiting functions
780  jQuery.ready();
781}
782
783function evalScript( i, elem ) {
784  if ( elem.src ) {
785    jQuery.ajax({
786      url: elem.src,
787      async: false,
788      dataType: "script"
789    });
790  } else {
791    jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
792  }
793
794  if ( elem.parentNode ) {
795    elem.parentNode.removeChild( elem );
796  }
797}
798
799// Mutifunctional method to get and set values to a collection
800// The value/s can be optionally by executed if its a function
801function access( elems, key, value, exec, fn, pass ) {
802  var length = elems.length;
803 
804  // Setting many attributes
805  if ( typeof key === "object" ) {
806    for ( var k in key ) {
807      access( elems, k, key[k], exec, fn, value );
808    }
809    return elems;
810  }
811 
812  // Setting one attribute
813  if ( value !== undefined ) {
814    // Optionally, function values get executed if exec is true
815    exec = !pass && exec && jQuery.isFunction(value);
816   
817    for ( var i = 0; i < length; i++ ) {
818      fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
819    }
820   
821    return elems;
822  }
823 
824  // Getting an attribute
825  return length ? fn( elems[0], key ) : null;
826}
827
828function now() {
829  return (new Date).getTime();
830}
831(function() {
832
833  jQuery.support = {};
834
835  var root = document.documentElement,
836    script = document.createElement("script"),
837    div = document.createElement("div"),
838    id = "script" + now();
839
840  div.style.display = "none";
841  div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
842
843  var all = div.getElementsByTagName("*"),
844    a = div.getElementsByTagName("a")[0];
845
846  // Can't get basic test support
847  if ( !all || !all.length || !a ) {
848    return;
849  }
850
851  jQuery.support = {
852    // IE strips leading whitespace when .innerHTML is used
853    leadingWhitespace: div.firstChild.nodeType === 3,
854
855    // Make sure that tbody elements aren't automatically inserted
856    // IE will insert them into empty tables
857    tbody: !div.getElementsByTagName("tbody").length,
858
859    // Make sure that link elements get serialized correctly by innerHTML
860    // This requires a wrapper element in IE
861    htmlSerialize: !!div.getElementsByTagName("link").length,
862
863    // Get the style information from getAttribute
864    // (IE uses .cssText insted)
865    style: /red/.test( a.getAttribute("style") ),
866
867    // Make sure that URLs aren't manipulated
868    // (IE normalizes it by default)
869    hrefNormalized: a.getAttribute("href") === "/a",
870
871    // Make sure that element opacity exists
872    // (IE uses filter instead)
873    // Use a regex to work around a WebKit issue. See #5145
874    opacity: /^0.55$/.test( a.style.opacity ),
875
876    // Verify style float existence
877    // (IE uses styleFloat instead of cssFloat)
878    cssFloat: !!a.style.cssFloat,
879
880    // Make sure that if no value is specified for a checkbox
881    // that it defaults to "on".
882    // (WebKit defaults to "" instead)
883    checkOn: div.getElementsByTagName("input")[0].value === "on",
884
885    // Make sure that a selected-by-default option has a working selected property.
886    // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
887    optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
888
889    // Will be defined later
890    checkClone: false,
891    scriptEval: false,
892    noCloneEvent: true,
893    boxModel: null
894  };
895
896  script.type = "text/javascript";
897  try {
898    script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
899  } catch(e) {}
900
901  root.insertBefore( script, root.firstChild );
902
903  // Make sure that the execution of code works by injecting a script
904  // tag with appendChild/createTextNode
905  // (IE doesn't support this, fails, and uses .text instead)
906  if ( window[ id ] ) {
907    jQuery.support.scriptEval = true;
908    delete window[ id ];
909  }
910
911  root.removeChild( script );
912
913  if ( div.attachEvent && div.fireEvent ) {
914    div.attachEvent("onclick", function click() {
915      // Cloning a node shouldn't copy over any
916      // bound event handlers (IE does this)
917      jQuery.support.noCloneEvent = false;
918      div.detachEvent("onclick", click);
919    });
920    div.cloneNode(true).fireEvent("onclick");
921  }
922
923  div = document.createElement("div");
924  div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
925
926  var fragment = document.createDocumentFragment();
927  fragment.appendChild( div.firstChild );
928
929  // WebKit doesn't clone checked state correctly in fragments
930  jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
931
932  // Figure out if the W3C box model works as expected
933  // document.body must exist before we can do this
934  jQuery(function() {
935    var div = document.createElement("div");
936    div.style.width = div.style.paddingLeft = "1px";
937
938    document.body.appendChild( div );
939    jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
940    document.body.removeChild( div ).style.display = 'none';
941    div = null;
942  });
943
944  // Technique from Juriy Zaytsev
945  // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
946  var eventSupported = function( eventName ) {
947    var el = document.createElement("div");
948    eventName = "on" + eventName;
949
950    var isSupported = (eventName in el);
951    if ( !isSupported ) {
952      el.setAttribute(eventName, "return;");
953      isSupported = typeof el[eventName] === "function";
954    }
955    el = null;
956
957    return isSupported;
958  };
959 
960  jQuery.support.submitBubbles = eventSupported("submit");
961  jQuery.support.changeBubbles = eventSupported("change");
962
963  // release memory in IE
964  root = script = div = all = a = null;
965})();
966
967jQuery.props = {
968  "for": "htmlFor",
969  "class": "className",
970  readonly: "readOnly",
971  maxlength: "maxLength",
972  cellspacing: "cellSpacing",
973  rowspan: "rowSpan",
974  colspan: "colSpan",
975  tabindex: "tabIndex",
976  usemap: "useMap",
977  frameborder: "frameBorder"
978};
979var expando = "jQuery" + now(), uuid = 0, windowData = {};
980var emptyObject = {};
981
982jQuery.extend({
983  cache: {},
984 
985  expando:expando,
986
987  // The following elements throw uncatchable exceptions if you
988  // attempt to add expando properties to them.
989  noData: {
990    "embed": true,
991    "object": true,
992    "applet": true
993  },
994
995  data: function( elem, name, data ) {
996    if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
997      return;
998    }
999
1000    elem = elem == window ?
1001      windowData :
1002      elem;
1003
1004    var id = elem[ expando ], cache = jQuery.cache, thisCache;
1005
1006    // Handle the case where there's no name immediately
1007    if ( !name && !id ) {
1008      return null;
1009    }
1010
1011    // Compute a unique ID for the element
1012    if ( !id ) {
1013      id = ++uuid;
1014    }
1015
1016    // Avoid generating a new cache unless none exists and we
1017    // want to manipulate it.
1018    if ( typeof name === "object" ) {
1019      elem[ expando ] = id;
1020      thisCache = cache[ id ] = jQuery.extend(true, {}, name);
1021    } else if ( cache[ id ] ) {
1022      thisCache = cache[ id ];
1023    } else if ( typeof data === "undefined" ) {
1024      thisCache = emptyObject;
1025    } else {
1026      thisCache = cache[ id ] = {};
1027    }
1028
1029    // Prevent overriding the named cache with undefined values
1030    if ( data !== undefined ) {
1031      elem[ expando ] = id;
1032      thisCache[ name ] = data;
1033    }
1034
1035    return typeof name === "string" ? thisCache[ name ] : thisCache;
1036  },
1037
1038  removeData: function( elem, name ) {
1039    if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
1040      return;
1041    }
1042
1043    elem = elem == window ?
1044      windowData :
1045      elem;
1046
1047    var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
1048
1049    // If we want to remove a specific section of the element's data
1050    if ( name ) {
1051      if ( thisCache ) {
1052        // Remove the section of cache data
1053        delete thisCache[ name ];
1054
1055        // If we've removed all the data, remove the element's cache
1056        if ( jQuery.isEmptyObject(thisCache) ) {
1057          jQuery.removeData( elem );
1058        }
1059      }
1060
1061    // Otherwise, we want to remove all of the element's data
1062    } else {
1063      // Clean up the element expando
1064      try {
1065        delete elem[ expando ];
1066      } catch( e ) {
1067        // IE has trouble directly removing the expando
1068        // but it's ok with using removeAttribute
1069        if ( elem.removeAttribute ) {
1070          elem.removeAttribute( expando );
1071        }
1072      }
1073
1074      // Completely remove the data cache
1075      delete cache[ id ];
1076    }
1077  }
1078});
1079
1080jQuery.fn.extend({
1081  data: function( key, value ) {
1082    if ( typeof key === "undefined" && this.length ) {
1083      return jQuery.data( this[0] );
1084
1085    } else if ( typeof key === "object" ) {
1086      return this.each(function() {
1087        jQuery.data( this, key );
1088      });
1089    }
1090
1091    var parts = key.split(".");
1092    parts[1] = parts[1] ? "." + parts[1] : "";
1093
1094    if ( value === undefined ) {
1095      var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1096
1097      if ( data === undefined && this.length ) {
1098        data = jQuery.data( this[0], key );
1099      }
1100      return data === undefined && parts[1] ?
1101        this.data( parts[0] ) :
1102        data;
1103    } else {
1104      return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
1105        jQuery.data( this, key, value );
1106      });
1107    }
1108  },
1109
1110  removeData: function( key ) {
1111    return this.each(function() {
1112      jQuery.removeData( this, key );
1113    });
1114  }
1115});
1116jQuery.extend({
1117  queue: function( elem, type, data ) {
1118    if ( !elem ) {
1119      return;
1120    }
1121
1122    type = (type || "fx") + "queue";
1123    var q = jQuery.data( elem, type );
1124
1125    // Speed up dequeue by getting out quickly if this is just a lookup
1126    if ( !data ) {
1127      return q || [];
1128    }
1129
1130    if ( !q || jQuery.isArray(data) ) {
1131      q = jQuery.data( elem, type, jQuery.makeArray(data) );
1132
1133    } else {
1134      q.push( data );
1135    }
1136
1137    return q;
1138  },
1139
1140  dequeue: function( elem, type ) {
1141    type = type || "fx";
1142
1143    var queue = jQuery.queue( elem, type ), fn = queue.shift();
1144
1145    // If the fx queue is dequeued, always remove the progress sentinel
1146    if ( fn === "inprogress" ) {
1147      fn = queue.shift();
1148    }
1149
1150    if ( fn ) {
1151      // Add a progress sentinel to prevent the fx queue from being
1152      // automatically dequeued
1153      if ( type === "fx" ) {
1154        queue.unshift("inprogress");
1155      }
1156
1157      fn.call(elem, function() {
1158        jQuery.dequeue(elem, type);
1159      });
1160    }
1161  }
1162});
1163
1164jQuery.fn.extend({
1165  queue: function( type, data ) {
1166    if ( typeof type !== "string" ) {
1167      data = type;
1168      type = "fx";
1169    }
1170
1171    if ( data === undefined ) {
1172      return jQuery.queue( this[0], type );
1173    }
1174    return this.each(function( i, elem ) {
1175      var queue = jQuery.queue( this, type, data );
1176
1177      if ( type === "fx" && queue[0] !== "inprogress" ) {
1178        jQuery.dequeue( this, type );
1179      }
1180    });
1181  },
1182  dequeue: function( type ) {
1183    return this.each(function() {
1184      jQuery.dequeue( this, type );
1185    });
1186  },
1187
1188  // Based off of the plugin by Clint Helfers, with permission.
1189  // http://blindsignals.com/index.php/2009/07/jquery-delay/
1190  delay: function( time, type ) {
1191    time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1192    type = type || "fx";
1193
1194    return this.queue( type, function() {
1195      var elem = this;
1196      setTimeout(function() {
1197        jQuery.dequeue( elem, type );
1198      }, time );
1199    });
1200  },
1201
1202  clearQueue: function( type ) {
1203    return this.queue( type || "fx", [] );
1204  }
1205});
1206var rclass = /[\n\t]/g,
1207  rspace = /\s+/,
1208  rreturn = /\r/g,
1209  rspecialurl = /href|src|style/,
1210  rtype = /(button|input)/i,
1211  rfocusable = /(button|input|object|select|textarea)/i,
1212  rclickable = /^(a|area)$/i,
1213  rradiocheck = /radio|checkbox/;
1214
1215jQuery.fn.extend({
1216  attr: function( name, value ) {
1217    return access( this, name, value, true, jQuery.attr );
1218  },
1219
1220  removeAttr: function( name, fn ) {
1221    return this.each(function(){
1222      jQuery.attr( this, name, "" );
1223      if ( this.nodeType === 1 ) {
1224        this.removeAttribute( name );
1225      }
1226    });
1227  },
1228
1229  addClass: function( value ) {
1230    if ( jQuery.isFunction(value) ) {
1231      return this.each(function(i) {
1232        var self = jQuery(this);
1233        self.addClass( value.call(this, i, self.attr("class")) );
1234      });
1235    }
1236
1237    if ( value && typeof value === "string" ) {
1238      var classNames = (value || "").split( rspace );
1239
1240      for ( var i = 0, l = this.length; i < l; i++ ) {
1241        var elem = this[i];
1242
1243        if ( elem.nodeType === 1 ) {
1244          if ( !elem.className ) {
1245            elem.className = value;
1246
1247          } else {
1248            var className = " " + elem.className + " ";
1249            for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1250              if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
1251                elem.className += " " + classNames[c];
1252              }
1253            }
1254          }
1255        }
1256      }
1257    }
1258
1259    return this;
1260  },
1261
1262  removeClass: function( value ) {
1263    if ( jQuery.isFunction(value) ) {
1264      return this.each(function(i) {
1265        var self = jQuery(this);
1266        self.removeClass( value.call(this, i, self.attr("class")) );
1267      });
1268    }
1269
1270    if ( (value && typeof value === "string") || value === undefined ) {
1271      var classNames = (value || "").split(rspace);
1272
1273      for ( var i = 0, l = this.length; i < l; i++ ) {
1274        var elem = this[i];
1275
1276        if ( elem.nodeType === 1 && elem.className ) {
1277          if ( value ) {
1278            var className = (" " + elem.className + " ").replace(rclass, " ");
1279            for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1280              className = className.replace(" " + classNames[c] + " ", " ");
1281            }
1282            elem.className = className.substring(1, className.length - 1);
1283
1284          } else {
1285            elem.className = "";
1286          }
1287        }
1288      }
1289    }
1290
1291    return this;
1292  },
1293
1294  toggleClass: function( value, stateVal ) {
1295    var type = typeof value, isBool = typeof stateVal === "boolean";
1296
1297    if ( jQuery.isFunction( value ) ) {
1298      return this.each(function(i) {
1299        var self = jQuery(this);
1300        self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
1301      });
1302    }
1303
1304    return this.each(function() {
1305      if ( type === "string" ) {
1306        // toggle individual class names
1307        var className, i = 0, self = jQuery(this),
1308          state = stateVal,
1309          classNames = value.split( rspace );
1310
1311        while ( (className = classNames[ i++ ]) ) {
1312          // check each className given, space seperated list
1313          state = isBool ? state : !self.hasClass( className );
1314          self[ state ? "addClass" : "removeClass" ]( className );
1315        }
1316
1317      } else if ( type === "undefined" || type === "boolean" ) {
1318        if ( this.className ) {
1319          // store className if set
1320          jQuery.data( this, "__className__", this.className );
1321        }
1322
1323        // toggle whole className
1324        this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
1325      }
1326    });
1327  },
1328
1329  hasClass: function( selector ) {
1330    var className = " " + selector + " ";
1331    for ( var i = 0, l = this.length; i < l; i++ ) {
1332      if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
1333        return true;
1334      }
1335    }
1336
1337    return false;
1338  },
1339
1340  val: function( value ) {
1341    if ( value === undefined ) {
1342      var elem = this[0];
1343
1344      if ( elem ) {
1345        if ( jQuery.nodeName( elem, "option" ) ) {
1346          return (elem.attributes.value || {}).specified ? elem.value : elem.text;
1347        }
1348
1349        // We need to handle select boxes special
1350        if ( jQuery.nodeName( elem, "select" ) ) {
1351          var index = elem.selectedIndex,
1352            values = [],
1353            options = elem.options,
1354            one = elem.type === "select-one";
1355
1356          // Nothing was selected
1357          if ( index < 0 ) {
1358            return null;
1359          }
1360
1361          // Loop through all the selected options
1362          for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1363            var option = options[ i ];
1364
1365            if ( option.selected ) {
1366              // Get the specifc value for the option
1367              value = jQuery(option).val();
1368
1369              // We don't need an array for one selects
1370              if ( one ) {
1371                return value;
1372              }
1373
1374              // Multi-Selects return an array
1375              values.push( value );
1376            }
1377          }
1378
1379          return values;
1380        }
1381
1382        // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1383        if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1384          return elem.getAttribute("value") === null ? "on" : elem.value;
1385        }
1386       
1387
1388        // Everything else, we just grab the value
1389        return (elem.value || "").replace(rreturn, "");
1390
1391      }
1392
1393      return undefined;
1394    }
1395
1396    var isFunction = jQuery.isFunction(value);
1397
1398    return this.each(function(i) {
1399      var self = jQuery(this), val = value;
1400
1401      if ( this.nodeType !== 1 ) {
1402        return;
1403      }
1404
1405      if ( isFunction ) {
1406        val = value.call(this, i, self.val());
1407      }
1408
1409      // Typecast each time if the value is a Function and the appended
1410      // value is therefore different each time.
1411      if ( typeof val === "number" ) {
1412        val += "";
1413      }
1414
1415      if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1416        this.checked = jQuery.inArray( self.val(), val ) >= 0;
1417
1418      } else if ( jQuery.nodeName( this, "select" ) ) {
1419        var values = jQuery.makeArray(val);
1420
1421        jQuery( "option", this ).each(function() {
1422          this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
1423        });
1424
1425        if ( !values.length ) {
1426          this.selectedIndex = -1;
1427        }
1428
1429      } else {
1430        this.value = val;
1431      }
1432    });
1433  }
1434});
1435
1436jQuery.extend({
1437  attrFn: {
1438    val: true,
1439    css: true,
1440    html: true,
1441    text: true,
1442    data: true,
1443    width: true,
1444    height: true,
1445    offset: true
1446  },
1447   
1448  attr: function( elem, name, value, pass ) {
1449    // don't set attributes on text and comment nodes
1450    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1451      return undefined;
1452    }
1453
1454    if ( pass && name in jQuery.attrFn ) {
1455      return jQuery(elem)[name](value);
1456    }
1457
1458    var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1459      // Whether we are setting (or getting)
1460      set = value !== undefined;
1461
1462    // Try to normalize/fix the name
1463    name = notxml && jQuery.props[ name ] || name;
1464
1465    // Only do all the following if this is a node (faster for style)
1466    if ( elem.nodeType === 1 ) {
1467      // These attributes require special treatment
1468      var special = rspecialurl.test( name );
1469
1470      // Safari mis-reports the default selected property of an option
1471      // Accessing the parent's selectedIndex property fixes it
1472      if ( name === "selected" && !jQuery.support.optSelected ) {
1473        var parent = elem.parentNode;
1474        if ( parent ) {
1475          parent.selectedIndex;
1476 
1477          // Make sure that it also works with optgroups, see #5701
1478          if ( parent.parentNode ) {
1479            parent.parentNode.selectedIndex;
1480          }
1481        }
1482      }
1483
1484      // If applicable, access the attribute via the DOM 0 way
1485      if ( name in elem && notxml && !special ) {
1486        if ( set ) {
1487          // We can't allow the type property to be changed (since it causes problems in IE)
1488          if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
1489            jQuery.error( "type property can't be changed" );
1490          }
1491
1492          elem[ name ] = value;
1493        }
1494
1495        // browsers index elements by id/name on forms, give priority to attributes.
1496        if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
1497          return elem.getAttributeNode( name ).nodeValue;
1498        }
1499
1500        // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1501        // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1502        if ( name === "tabIndex" ) {
1503          var attributeNode = elem.getAttributeNode( "tabIndex" );
1504
1505          return attributeNode && attributeNode.specified ?
1506            attributeNode.value :
1507            rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
1508              0 :
1509              undefined;
1510        }
1511
1512        return elem[ name ];
1513      }
1514
1515      if ( !jQuery.support.style && notxml && name === "style" ) {
1516        if ( set ) {
1517          elem.style.cssText = "" + value;
1518        }
1519
1520        return elem.style.cssText;
1521      }
1522
1523      if ( set ) {
1524        // convert the value to a string (all browsers do this but IE) see #1070
1525        elem.setAttribute( name, "" + value );
1526      }
1527
1528      var attr = !jQuery.support.hrefNormalized && notxml && special ?
1529          // Some attributes require a special call on IE
1530          elem.getAttribute( name, 2 ) :
1531          elem.getAttribute( name );
1532
1533      // Non-existent attributes return null, we normalize to undefined
1534      return attr === null ? undefined : attr;
1535    }
1536
1537    // elem is actually elem.style ... set the style
1538    // Using attr for specific style information is now deprecated. Use style insead.
1539    return jQuery.style( elem, name, value );
1540  }
1541});
1542var fcleanup = function( nm ) {
1543  return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
1544    return "\\" + ch;
1545  });
1546};
1547
1548/*
1549 * A number of helper functions used for managing events.
1550 * Many of the ideas behind this code originated from
1551 * Dean Edwards' addEvent library.
1552 */
1553jQuery.event = {
1554
1555  // Bind an event to an element
1556  // Original by Dean Edwards
1557  add: function( elem, types, handler, data ) {
1558    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1559      return;
1560    }
1561
1562    // For whatever reason, IE has trouble passing the window object
1563    // around, causing it to be cloned in the process
1564    if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
1565      elem = window;
1566    }
1567
1568    // Make sure that the function being executed has a unique ID
1569    if ( !handler.guid ) {
1570      handler.guid = jQuery.guid++;
1571    }
1572
1573    // if data is passed, bind to handler
1574    if ( data !== undefined ) {
1575      // Create temporary function pointer to original handler
1576      var fn = handler;
1577
1578      // Create unique handler function, wrapped around original handler
1579      handler = jQuery.proxy( fn );
1580
1581      // Store data in unique handler
1582      handler.data = data;
1583    }
1584
1585    // Init the element's event structure
1586    var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
1587      handle = jQuery.data( elem, "handle" ), eventHandle;
1588
1589    if ( !handle ) {
1590      eventHandle = function() {
1591        // Handle the second event of a trigger and when
1592        // an event is called after a page has unloaded
1593        return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
1594          jQuery.event.handle.apply( eventHandle.elem, arguments ) :
1595          undefined;
1596      };
1597
1598      handle = jQuery.data( elem, "handle", eventHandle );
1599    }
1600
1601    // If no handle is found then we must be trying to bind to one of the
1602    // banned noData elements
1603    if ( !handle ) {
1604      return;
1605    }
1606
1607    // Add elem as a property of the handle function
1608    // This is to prevent a memory leak with non-native
1609    // event in IE.
1610    handle.elem = elem;
1611
1612    // Handle multiple events separated by a space
1613    // jQuery(...).bind("mouseover mouseout", fn);
1614    types = types.split( /\s+/ );
1615
1616    var type, i = 0;
1617
1618    while ( (type = types[ i++ ]) ) {
1619      // Namespaced event handlers
1620      var namespaces = type.split(".");
1621      type = namespaces.shift();
1622
1623      if ( i > 1 ) {
1624        handler = jQuery.proxy( handler );
1625
1626        if ( data !== undefined ) {
1627          handler.data = data;
1628        }
1629      }
1630
1631      handler.type = namespaces.slice(0).sort().join(".");
1632
1633      // Get the current list of functions bound to this event
1634      var handlers = events[ type ],
1635        special = this.special[ type ] || {};
1636
1637      // Init the event handler queue
1638      if ( !handlers ) {
1639        handlers = events[ type ] = {};
1640
1641        // Check for a special event handler
1642        // Only use addEventListener/attachEvent if the special
1643        // events handler returns false
1644        if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) {
1645          // Bind the global event handler to the element
1646          if ( elem.addEventListener ) {
1647            elem.addEventListener( type, handle, false );
1648          } else if ( elem.attachEvent ) {
1649            elem.attachEvent( "on" + type, handle );
1650          }
1651        }
1652      }
1653     
1654      if ( special.add ) {
1655        var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers );
1656        if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) {
1657          modifiedHandler.guid = modifiedHandler.guid || handler.guid;
1658          modifiedHandler.data = modifiedHandler.data || handler.data;
1659          modifiedHandler.type = modifiedHandler.type || handler.type;
1660          handler = modifiedHandler;
1661        }
1662      }
1663     
1664      // Add the function to the element's handler list
1665      handlers[ handler.guid ] = handler;
1666
1667      // Keep track of which events have been used, for global triggering
1668      this.global[ type ] = true;
1669    }
1670
1671    // Nullify elem to prevent memory leaks in IE
1672    elem = null;
1673  },
1674
1675  global: {},
1676
1677  // Detach an event or set of events from an element
1678  remove: function( elem, types, handler ) {
1679    // don't do events on text and comment nodes
1680    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1681      return;
1682    }
1683
1684    var events = jQuery.data( elem, "events" ), ret, type, fn;
1685
1686    if ( events ) {
1687      // Unbind all events for the element
1688      if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
1689        for ( type in events ) {
1690          this.remove( elem, type + (types || "") );
1691        }
1692      } else {
1693        // types is actually an event object here
1694        if ( types.type ) {
1695          handler = types.handler;
1696          types = types.type;
1697        }
1698
1699        // Handle multiple events separated by a space
1700        // jQuery(...).unbind("mouseover mouseout", fn);
1701        types = types.split(/\s+/);
1702        var i = 0;
1703        while ( (type = types[ i++ ]) ) {
1704          // Namespaced event handlers
1705          var namespaces = type.split(".");
1706          type = namespaces.shift();
1707          var all = !namespaces.length,
1708            cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
1709            namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
1710            special = this.special[ type ] || {};
1711
1712          if ( events[ type ] ) {
1713            // remove the given handler for the given type
1714            if ( handler ) {
1715              fn = events[ type ][ handler.guid ];
1716              delete events[ type ][ handler.guid ];
1717
1718            // remove all handlers for the given type
1719            } else {
1720              for ( var handle in events[ type ] ) {
1721                // Handle the removal of namespaced events
1722                if ( all || namespace.test( events[ type ][ handle ].type ) ) {
1723                  delete events[ type ][ handle ];
1724                }
1725              }
1726            }
1727
1728            if ( special.remove ) {
1729              special.remove.call( elem, namespaces, fn);
1730            }
1731
1732            // remove generic event handler if no more handlers exist
1733            for ( ret in events[ type ] ) {
1734              break;
1735            }
1736            if ( !ret ) {
1737              if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
1738                if ( elem.removeEventListener ) {
1739                  elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
1740                } else if ( elem.detachEvent ) {
1741                  elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
1742                }
1743              }
1744              ret = null;
1745              delete events[ type ];
1746            }
1747          }
1748        }
1749      }
1750
1751      // Remove the expando if it's no longer used
1752      for ( ret in events ) {
1753        break;
1754      }
1755      if ( !ret ) {
1756        var handle = jQuery.data( elem, "handle" );
1757        if ( handle ) {
1758          handle.elem = null;
1759        }
1760        jQuery.removeData( elem, "events" );
1761        jQuery.removeData( elem, "handle" );
1762      }
1763    }
1764  },
1765
1766  // bubbling is internal
1767  trigger: function( event, data, elem /*, bubbling */ ) {
1768    // Event object or event type
1769    var type = event.type || event,
1770      bubbling = arguments[3];
1771
1772    if ( !bubbling ) {
1773      event = typeof event === "object" ?
1774        // jQuery.Event object
1775        event[expando] ? event :
1776        // Object literal
1777        jQuery.extend( jQuery.Event(type), event ) :
1778        // Just the event type (string)
1779        jQuery.Event(type);
1780
1781      if ( type.indexOf("!") >= 0 ) {
1782        event.type = type = type.slice(0, -1);
1783        event.exclusive = true;
1784      }
1785
1786      // Handle a global trigger
1787      if ( !elem ) {
1788        // Don't bubble custom events when global (to avoid too much overhead)
1789        event.stopPropagation();
1790
1791        // Only trigger if we've ever bound an event for it
1792        if ( this.global[ type ] ) {
1793          jQuery.each( jQuery.cache, function() {
1794            if ( this.events && this.events[type] ) {
1795              jQuery.event.trigger( event, data, this.handle.elem );
1796            }
1797          });
1798        }
1799      }
1800
1801      // Handle triggering a single element
1802
1803      // don't do events on text and comment nodes
1804      if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1805        return undefined;
1806      }
1807
1808      // Clean up in case it is reused
1809      event.result = undefined;
1810      event.target = elem;
1811
1812      // Clone the incoming data, if any
1813      data = jQuery.makeArray( data );
1814      data.unshift( event );
1815    }
1816
1817    event.currentTarget = elem;
1818
1819    // Trigger the event, it is assumed that "handle" is a function
1820    var handle = jQuery.data( elem, "handle" );
1821    if ( handle ) {
1822      handle.apply( elem, data );
1823    }
1824
1825    var parent = elem.parentNode || elem.ownerDocument;
1826
1827    // Trigger an inline bound script
1828    try {
1829      if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
1830        if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
1831          event.result = false;
1832        }
1833      }
1834
1835    // prevent IE from throwing an error for some elements with some event types, see #3533
1836    } catch (e) {}
1837
1838    if ( !event.isPropagationStopped() && parent ) {
1839      jQuery.event.trigger( event, data, parent, true );
1840
1841    } else if ( !event.isDefaultPrevented() ) {
1842      var target = event.target, old,
1843        isClick = jQuery.nodeName(target, "a") && type === "click";
1844
1845      if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
1846        try {
1847          if ( target[ type ] ) {
1848            // Make sure that we don't accidentally re-trigger the onFOO events
1849            old = target[ "on" + type ];
1850
1851            if ( old ) {
1852              target[ "on" + type ] = null;
1853            }
1854
1855            this.triggered = true;
1856            target[ type ]();
1857          }
1858
1859        // prevent IE from throwing an error for some elements with some event types, see #3533
1860        } catch (e) {}
1861
1862        if ( old ) {
1863          target[ "on" + type ] = old;
1864        }
1865
1866        this.triggered = false;
1867      }
1868    }
1869  },
1870
1871  handle: function( event ) {
1872    // returned undefined or false
1873    var all, handlers;
1874
1875    event = arguments[0] = jQuery.event.fix( event || window.event );
1876    event.currentTarget = this;
1877
1878    // Namespaced event handlers
1879    var namespaces = event.type.split(".");
1880    event.type = namespaces.shift();
1881
1882    // Cache this now, all = true means, any handler
1883    all = !namespaces.length && !event.exclusive;
1884
1885    var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
1886
1887    handlers = ( jQuery.data(this, "events") || {} )[ event.type ];
1888
1889    for ( var j in handlers ) {
1890      var handler = handlers[ j ];
1891
1892      // Filter the functions by class
1893      if ( all || namespace.test(handler.type) ) {
1894        // Pass in a reference to the handler function itself
1895        // So that we can later remove it
1896        event.handler = handler;
1897        event.data = handler.data;
1898
1899        var ret = handler.apply( this, arguments );
1900
1901        if ( ret !== undefined ) {
1902          event.result = ret;
1903          if ( ret === false ) {
1904            event.preventDefault();
1905            event.stopPropagation();
1906          }
1907        }
1908
1909        if ( event.isImmediatePropagationStopped() ) {
1910          break;
1911        }
1912
1913      }
1914    }
1915
1916    return event.result;
1917  },
1918
1919  props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
1920
1921  fix: function( event ) {
1922    if ( event[ expando ] ) {
1923      return event;
1924    }
1925
1926    // store a copy of the original event object
1927    // and "clone" to set read-only properties
1928    var originalEvent = event;
1929    event = jQuery.Event( originalEvent );
1930
1931    for ( var i = this.props.length, prop; i; ) {
1932      prop = this.props[ --i ];
1933      event[ prop ] = originalEvent[ prop ];
1934    }
1935
1936    // Fix target property, if necessary
1937    if ( !event.target ) {
1938      event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
1939    }
1940
1941    // check if target is a textnode (safari)
1942    if ( event.target.nodeType === 3 ) {
1943      event.target = event.target.parentNode;
1944    }
1945
1946    // Add relatedTarget, if necessary
1947    if ( !event.relatedTarget && event.fromElement ) {
1948      event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
1949    }
1950
1951    // Calculate pageX/Y if missing and clientX/Y available
1952    if ( event.pageX == null && event.clientX != null ) {
1953      var doc = document.documentElement, body = document.body;
1954      event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
1955      event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
1956    }
1957
1958    // Add which for key events
1959    if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
1960      event.which = event.charCode || event.keyCode;
1961    }
1962
1963    // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
1964    if ( !event.metaKey && event.ctrlKey ) {
1965      event.metaKey = event.ctrlKey;
1966    }
1967
1968    // Add which for click: 1 === left; 2 === middle; 3 === right
1969    // Note: button is not normalized, so don't use it
1970    if ( !event.which && event.button !== undefined ) {
1971      event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
1972    }
1973
1974    return event;
1975  },
1976
1977  // Deprecated, use jQuery.guid instead
1978  guid: 1E8,
1979
1980  // Deprecated, use jQuery.proxy instead
1981  proxy: jQuery.proxy,
1982
1983  special: {
1984    ready: {
1985      // Make sure the ready event is setup
1986      setup: jQuery.bindReady,
1987      teardown: jQuery.noop
1988    },
1989
1990    live: {
1991      add: function( proxy, data, namespaces, live ) {
1992        jQuery.extend( proxy, data || {} );
1993
1994        proxy.guid += data.selector + data.live;
1995        data.liveProxy = proxy;
1996
1997        jQuery.event.add( this, data.live, liveHandler, data );
1998       
1999      },
2000
2001      remove: function( namespaces ) {
2002        if ( namespaces.length ) {
2003          var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2004
2005          jQuery.each( (jQuery.data(this, "events").live || {}), function() {
2006            if ( name.test(this.type) ) {
2007              remove++;
2008            }
2009          });
2010
2011          if ( remove < 1 ) {
2012            jQuery.event.remove( this, namespaces[0], liveHandler );
2013          }
2014        }
2015      },
2016      special: {}
2017    },
2018    beforeunload: {
2019      setup: function( data, namespaces, fn ) {
2020        // We only want to do this special case on windows
2021        if ( this.setInterval ) {
2022          this.onbeforeunload = fn;
2023        }
2024
2025        return false;
2026      },
2027      teardown: function( namespaces, fn ) {
2028        if ( this.onbeforeunload === fn ) {
2029          this.onbeforeunload = null;
2030        }
2031      }
2032    }
2033  }
2034};
2035
2036jQuery.Event = function( src ) {
2037  // Allow instantiation without the 'new' keyword
2038  if ( !this.preventDefault ) {
2039    return new jQuery.Event( src );
2040  }
2041
2042  // Event object
2043  if ( src && src.type ) {
2044    this.originalEvent = src;
2045    this.type = src.type;
2046  // Event type
2047  } else {
2048    this.type = src;
2049  }
2050
2051  // timeStamp is buggy for some events on Firefox(#3843)
2052  // So we won't rely on the native value
2053  this.timeStamp = now();
2054
2055  // Mark it as fixed
2056  this[ expando ] = true;
2057};
2058
2059function returnFalse() {
2060  return false;
2061}
2062function returnTrue() {
2063  return true;
2064}
2065
2066// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2067// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2068jQuery.Event.prototype = {
2069  preventDefault: function() {
2070    this.isDefaultPrevented = returnTrue;
2071
2072    var e = this.originalEvent;
2073    if ( !e ) {
2074      return;
2075    }
2076   
2077    // if preventDefault exists run it on the original event
2078    if ( e.preventDefault ) {
2079      e.preventDefault();
2080    }
2081    // otherwise set the returnValue property of the original event to false (IE)
2082    e.returnValue = false;
2083  },
2084  stopPropagation: function() {
2085    this.isPropagationStopped = returnTrue;
2086
2087    var e = this.originalEvent;
2088    if ( !e ) {
2089      return;
2090    }
2091    // if stopPropagation exists run it on the original event
2092    if ( e.stopPropagation ) {
2093      e.stopPropagation();
2094    }
2095    // otherwise set the cancelBubble property of the original event to true (IE)
2096    e.cancelBubble = true;
2097  },
2098  stopImmediatePropagation: function() {
2099    this.isImmediatePropagationStopped = returnTrue;
2100    this.stopPropagation();
2101  },
2102  isDefaultPrevented: returnFalse,
2103  isPropagationStopped: returnFalse,
2104  isImmediatePropagationStopped: returnFalse
2105};
2106
2107// Checks if an event happened on an element within another element
2108// Used in jQuery.event.special.mouseenter and mouseleave handlers
2109var withinElement = function( event ) {
2110  // Check if mouse(over|out) are still within the same parent element
2111  var parent = event.relatedTarget;
2112
2113  // Traverse up the tree
2114  while ( parent && parent !== this ) {
2115    // Firefox sometimes assigns relatedTarget a XUL element
2116    // which we cannot access the parentNode property of
2117    try {
2118      parent = parent.parentNode;
2119
2120    // assuming we've left the element since we most likely mousedover a xul element
2121    } catch(e) {
2122      break;
2123    }
2124  }
2125
2126  if ( parent !== this ) {
2127    // set the correct event type
2128    event.type = event.data;
2129
2130    // handle event if we actually just moused on to a non sub-element
2131    jQuery.event.handle.apply( this, arguments );
2132  }
2133
2134},
2135
2136// In case of event delegation, we only need to rename the event.type,
2137// liveHandler will take care of the rest.
2138delegate = function( event ) {
2139  event.type = event.data;
2140  jQuery.event.handle.apply( this, arguments );
2141};
2142
2143// Create mouseenter and mouseleave events
2144jQuery.each({
2145  mouseenter: "mouseover",
2146  mouseleave: "mouseout"
2147}, function( orig, fix ) {
2148  jQuery.event.special[ orig ] = {
2149    setup: function( data ) {
2150      jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
2151    },
2152    teardown: function( data ) {
2153      jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
2154    }
2155  };
2156});
2157
2158// submit delegation
2159if ( !jQuery.support.submitBubbles ) {
2160
2161jQuery.event.special.submit = {
2162  setup: function( data, namespaces, fn ) {
2163    if ( this.nodeName.toLowerCase() !== "form" ) {
2164      jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
2165        var elem = e.target, type = elem.type;
2166
2167        if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2168          return trigger( "submit", this, arguments );
2169        }
2170      });
2171   
2172      jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
2173        var elem = e.target, type = elem.type;
2174
2175        if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2176          return trigger( "submit", this, arguments );
2177        }
2178      });
2179
2180    } else {
2181      return false;
2182    }
2183  },
2184
2185  remove: function( namespaces, fn ) {
2186    jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
2187    jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
2188  }
2189};
2190
2191}
2192
2193// change delegation, happens here so we have bind.
2194if ( !jQuery.support.changeBubbles ) {
2195
2196var formElems = /textarea|input|select/i;
2197
2198function getVal( elem ) {
2199  var type = elem.type, val = elem.value;
2200
2201  if ( type === "radio" || type === "checkbox" ) {
2202    val = elem.checked;
2203
2204  } else if ( type === "select-multiple" ) {
2205    val = elem.selectedIndex > -1 ?
2206      jQuery.map( elem.options, function( elem ) {
2207        return elem.selected;
2208      }).join("-") :
2209      "";
2210
2211  } else if ( elem.nodeName.toLowerCase() === "select" ) {
2212    val = elem.selectedIndex;
2213  }
2214
2215  return val;
2216}
2217
2218function testChange( e ) {
2219    var elem = e.target, data, val;
2220
2221    if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
2222      return;
2223    }
2224
2225    data = jQuery.data( elem, "_change_data" );
2226    val = getVal(elem);
2227
2228    // the current data will be also retrieved by beforeactivate
2229    if ( e.type !== "focusout" || elem.type !== "radio" ) {
2230      jQuery.data( elem, "_change_data", val );
2231    }
2232   
2233    if ( data === undefined || val === data ) {
2234      return;
2235    }
2236
2237    if ( data != null || val ) {
2238      e.type = "change";
2239      return jQuery.event.trigger( e, arguments[1], elem );
2240    }
2241}
2242
2243jQuery.event.special.change = {
2244  filters: {
2245    focusout: testChange,
2246
2247    click: function( e ) {
2248      var elem = e.target, type = elem.type;
2249
2250      if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2251        return testChange.call( this, e );
2252      }
2253    },
2254
2255    // Change has to be called before submit
2256    // Keydown will be called before keypress, which is used in submit-event delegation
2257    keydown: function( e ) {
2258      var elem = e.target, type = elem.type;
2259
2260      if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
2261        (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
2262        type === "select-multiple" ) {
2263        return testChange.call( this, e );
2264      }
2265    },
2266
2267    // Beforeactivate happens also before the previous element is blurred
2268    // with this event you can't trigger a change event, but you can store
2269    // information/focus[in] is not needed anymore
2270    beforeactivate: function( e ) {
2271      var elem = e.target;
2272
2273      if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
2274        jQuery.data( elem, "_change_data", getVal(elem) );
2275      }
2276    }
2277  },
2278  setup: function( data, namespaces, fn ) {
2279    for ( var type in changeFilters ) {
2280      jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
2281    }
2282
2283    return formElems.test( this.nodeName );
2284  },
2285  remove: function( namespaces, fn ) {
2286    for ( var type in changeFilters ) {
2287      jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
2288    }
2289
2290    return formElems.test( this.nodeName );
2291  }
2292};
2293
2294var changeFilters = jQuery.event.special.change.filters;
2295
2296}
2297
2298function trigger( type, elem, args ) {
2299  args[0].type = type;
2300  return jQuery.event.handle.apply( elem, args );
2301}
2302
2303// Create "bubbling" focus and blur events
2304if ( document.addEventListener ) {
2305  jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
2306    jQuery.event.special[ fix ] = {
2307      setup: function() {
2308        this.addEventListener( orig, handler, true );
2309      },
2310      teardown: function() {
2311        this.removeEventListener( orig, handler, true );
2312      }
2313    };
2314
2315    function handler( e ) {
2316      e = jQuery.event.fix( e );
2317      e.type = fix;
2318      return jQuery.event.handle.call( this, e );
2319    }
2320  });
2321}
2322
2323jQuery.each(["bind", "one"], function( i, name ) {
2324  jQuery.fn[ name ] = function( type, data, fn ) {
2325    // Handle object literals
2326    if ( typeof type === "object" ) {
2327      for ( var key in type ) {
2328        this[ name ](key, data, type[key], fn);
2329      }
2330      return this;
2331    }
2332   
2333    if ( jQuery.isFunction( data ) ) {
2334      fn = data;
2335      data = undefined;
2336    }
2337
2338    var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2339      jQuery( this ).unbind( event, handler );
2340      return fn.apply( this, arguments );
2341    }) : fn;
2342
2343    return type === "unload" && name !== "one" ?
2344      this.one( type, data, fn ) :
2345      this.each(function() {
2346        jQuery.event.add( this, type, handler, data );
2347      });
2348  };
2349});
2350
2351jQuery.fn.extend({
2352  unbind: function( type, fn ) {
2353    // Handle object literals
2354    if ( typeof type === "object" && !type.preventDefault ) {
2355      for ( var key in type ) {
2356        this.unbind(key, type[key]);
2357      }
2358      return this;
2359    }
2360
2361    return this.each(function() {
2362      jQuery.event.remove( this, type, fn );
2363    });
2364  },
2365  trigger: function( type, data ) {
2366    return this.each(function() {
2367      jQuery.event.trigger( type, data, this );
2368    });
2369  },
2370
2371  triggerHandler: function( type, data ) {
2372    if ( this[0] ) {
2373      var event = jQuery.Event( type );
2374      event.preventDefault();
2375      event.stopPropagation();
2376      jQuery.event.trigger( event, data, this[0] );
2377      return event.result;
2378    }
2379  },
2380
2381  toggle: function( fn ) {
2382    // Save reference to arguments for access in closure
2383    var args = arguments, i = 1;
2384
2385    // link all the functions, so any of them can unbind this click handler
2386    while ( i < args.length ) {
2387      jQuery.proxy( fn, args[ i++ ] );
2388    }
2389
2390    return this.click( jQuery.proxy( fn, function( event ) {
2391      // Figure out which function to execute
2392      var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
2393      jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
2394
2395      // Make sure that clicks stop
2396      event.preventDefault();
2397
2398      // and execute the function
2399      return args[ lastToggle ].apply( this, arguments ) || false;
2400    }));
2401  },
2402
2403  hover: function( fnOver, fnOut ) {
2404    return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
2405  }
2406});
2407
2408jQuery.each(["live", "die"], function( i, name ) {
2409  jQuery.fn[ name ] = function( types, data, fn ) {
2410    var type, i = 0;
2411
2412    if ( jQuery.isFunction( data ) ) {
2413      fn = data;
2414      data = undefined;
2415    }
2416
2417    types = (types || "").split( /\s+/ );
2418
2419    while ( (type = types[ i++ ]) != null ) {
2420      type = type === "focus" ? "focusin" : // focus --> focusin
2421          type === "blur" ? "focusout" : // blur --> focusout
2422          type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
2423          type;
2424     
2425      if ( name === "live" ) {
2426        // bind live handler
2427        jQuery( this.context ).bind( liveConvert( type, this.selector ), {
2428          data: data, selector: this.selector, live: type
2429        }, fn );
2430
2431      } else {
2432        // unbind live handler
2433        jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
2434      }
2435    }
2436   
2437    return this;
2438  }
2439});
2440
2441function liveHandler( event ) {
2442  var stop, elems = [], selectors = [], args = arguments,
2443    related, match, fn, elem, j, i, l, data,
2444    live = jQuery.extend({}, jQuery.data( this, "events" ).live);
2445
2446  // Make sure we avoid non-left-click bubbling in Firefox (#3861)
2447  if ( event.button && event.type === "click" ) {
2448    return;
2449  }
2450
2451  for ( j in live ) {
2452    fn = live[j];
2453    if ( fn.live === event.type ||
2454        fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
2455
2456      data = fn.data;
2457      if ( !(data.beforeFilter && data.beforeFilter[event.type] &&
2458          !data.beforeFilter[event.type](event)) ) {
2459        selectors.push( fn.selector );
2460      }
2461    } else {
2462      delete live[j];
2463    }
2464  }
2465
2466  match = jQuery( event.target ).closest( selectors, event.currentTarget );
2467
2468  for ( i = 0, l = match.length; i < l; i++ ) {
2469    for ( j in live ) {
2470      fn = live[j];
2471      elem = match[i].elem;
2472      related = null;
2473
2474      if ( match[i].selector === fn.selector ) {
2475        // Those two events require additional checking
2476        if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
2477          related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
2478        }
2479
2480        if ( !related || related !== elem ) {
2481          elems.push({ elem: elem, fn: fn });
2482        }
2483      }
2484    }
2485  }
2486
2487  for ( i = 0, l = elems.length; i < l; i++ ) {
2488    match = elems[i];
2489    event.currentTarget = match.elem;
2490    event.data = match.fn.data;
2491    if ( match.fn.apply( match.elem, args ) === false ) {
2492      stop = false;
2493      break;
2494    }
2495  }
2496
2497  return stop;
2498}
2499
2500function liveConvert( type, selector ) {
2501  return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
2502}
2503
2504jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
2505  "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
2506  "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
2507
2508  // Handle event binding
2509  jQuery.fn[ name ] = function( fn ) {
2510    return fn ? this.bind( name, fn ) : this.trigger( name );
2511  };
2512
2513  if ( jQuery.attrFn ) {
2514    jQuery.attrFn[ name ] = true;
2515  }
2516});
2517
2518// Prevent memory leaks in IE
2519// Window isn't included so as not to unbind existing unload events
2520// More info:
2521//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
2522if ( window.attachEvent && !window.addEventListener ) {
2523  window.attachEvent("onunload", function() {
2524    for ( var id in jQuery.cache ) {
2525      if ( jQuery.cache[ id ].handle ) {
2526        // Try/Catch is to handle iframes being unloaded, see #4280
2527        try {
2528          jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2529        } catch(e) {}
2530      }
2531    }
2532  });
2533}
2534/*!
2535 * Sizzle CSS Selector Engine - v1.0
2536 *  Copyright 2009, The Dojo Foundation
2537 *  More information: http://sizzlejs.com/
2538 *
2539 * Permission is hereby granted, free of charge, to any person obtaining
2540 * a copy of this software and associated documentation files (the
2541 * "Software"), to deal in the Software without restriction, including
2542 * without limitation the rights to use, copy, modify, merge, publish,
2543 * distribute, sublicense, and/or sell copies of the Software, and to
2544 * permit persons to whom the Software is furnished to do so, subject to
2545 * the following conditions:
2546 *
2547 * The above copyright notice and this permission notice shall be
2548 * included in all copies or substantial portions of the Software.
2549 *
2550 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2551 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2552 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2553 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2554 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2555 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2556 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2557 */
2558(function(){
2559
2560var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
2561  done = 0,
2562  toString = Object.prototype.toString,
2563  hasDuplicate = false,
2564  baseHasDuplicate = true;
2565
2566// Here we check if the JavaScript engine is using some sort of
2567// optimization where it does not always call our comparision
2568// function. If that is the case, discard the hasDuplicate value.
2569//   Thus far that includes Google Chrome.
2570[0, 0].sort(function(){
2571  baseHasDuplicate = false;
2572  return 0;
2573});
2574
2575var Sizzle = function(selector, context, results, seed) {
2576  results = results || [];
2577  var origContext = context = context || document;
2578
2579  if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
2580    return [];
2581  }
2582 
2583  if ( !selector || typeof selector !== "string" ) {
2584    return results;
2585  }
2586
2587  var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
2588    soFar = selector;
2589 
2590  // Reset the position of the chunker regexp (start from head)
2591  while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
2592    soFar = m[3];
2593   
2594    parts.push( m[1] );
2595   
2596    if ( m[2] ) {
2597      extra = m[3];
2598      break;
2599    }
2600  }
2601
2602  if ( parts.length > 1 && origPOS.exec( selector ) ) {
2603    if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
2604      set = posProcess( parts[0] + parts[1], context );
2605    } else {
2606      set = Expr.relative[ parts[0] ] ?
2607        [ context ] :
2608        Sizzle( parts.shift(), context );
2609
2610      while ( parts.length ) {
2611        selector = parts.shift();
2612
2613        if ( Expr.relative[ selector ] ) {
2614          selector += parts.shift();
2615        }
2616       
2617        set = posProcess( selector, set );
2618      }
2619    }
2620  } else {
2621    // Take a shortcut and set the context if the root selector is an ID
2622    // (but not if it'll be faster if the inner selector is an ID)
2623    if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
2624        Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
2625      var ret = Sizzle.find( parts.shift(), context, contextXML );
2626      context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
2627    }
2628
2629    if ( context ) {
2630      var ret = seed ?
2631        { expr: parts.pop(), set: makeArray(seed) } :
2632        Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
2633      set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
2634
2635      if ( parts.length > 0 ) {
2636        checkSet = makeArray(set);
2637      } else {
2638        prune = false;
2639      }
2640
2641      while ( parts.length ) {
2642        var cur = parts.pop(), pop = cur;
2643
2644        if ( !Expr.relative[ cur ] ) {
2645          cur = "";
2646        } else {
2647          pop = parts.pop();
2648        }
2649
2650        if ( pop == null ) {
2651          pop = context;
2652        }
2653
2654        Expr.relative[ cur ]( checkSet, pop, contextXML );
2655      }
2656    } else {
2657      checkSet = parts = [];
2658    }
2659  }
2660
2661  if ( !checkSet ) {
2662    checkSet = set;
2663  }
2664
2665  if ( !checkSet ) {
2666    Sizzle.error( cur || selector );
2667  }
2668
2669  if ( toString.call(checkSet) === "[object Array]" ) {
2670    if ( !prune ) {
2671      results.push.apply( results, checkSet );
2672    } else if ( context && context.nodeType === 1 ) {
2673      for ( var i = 0; checkSet[i] != null; i++ ) {
2674        if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
2675          results.push( set[i] );
2676        }
2677      }
2678    } else {
2679      for ( var i = 0; checkSet[i] != null; i++ ) {
2680        if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
2681          results.push( set[i] );
2682        }
2683      }
2684    }
2685  } else {
2686    makeArray( checkSet, results );
2687  }
2688
2689  if ( extra ) {
2690    Sizzle( extra, origContext, results, seed );
2691    Sizzle.uniqueSort( results );
2692  }
2693
2694  return results;
2695};
2696
2697Sizzle.uniqueSort = function(results){
2698  if ( sortOrder ) {
2699    hasDuplicate = baseHasDuplicate;
2700    results.sort(sortOrder);
2701
2702    if ( hasDuplicate ) {
2703      for ( var i = 1; i < results.length; i++ ) {
2704        if ( results[i] === results[i-1] ) {
2705          results.splice(i--, 1);
2706        }
2707      }
2708    }
2709  }
2710
2711  return results;
2712};
2713
2714Sizzle.matches = function(expr, set){
2715  return Sizzle(expr, null, null, set);
2716};
2717
2718Sizzle.find = function(expr, context, isXML){
2719  var set, match;
2720
2721  if ( !expr ) {
2722    return [];
2723  }
2724
2725  for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
2726    var type = Expr.order[i], match;
2727   
2728    if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
2729      var left = match[1];
2730      match.splice(1,1);
2731
2732      if ( left.substr( left.length - 1 ) !== "\\" ) {
2733        match[1] = (match[1] || "").replace(/\\/g, "");
2734        set = Expr.find[ type ]( match, context, isXML );
2735        if ( set != null ) {
2736          expr = expr.replace( Expr.match[ type ], "" );
2737          break;
2738        }
2739      }
2740    }
2741  }
2742
2743  if ( !set ) {
2744    set = context.getElementsByTagName("*");
2745  }
2746
2747  return {set: set, expr: expr};
2748};
2749
2750Sizzle.filter = function(expr, set, inplace, not){
2751  var old = expr, result = [], curLoop = set, match, anyFound,
2752    isXMLFilter = set && set[0] && isXML(set[0]);
2753
2754  while ( expr && set.length ) {
2755    for ( var type in Expr.filter ) {
2756      if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
2757        var filter = Expr.filter[ type ], found, item, left = match[1];
2758        anyFound = false;
2759
2760        match.splice(1,1);
2761
2762        if ( left.substr( left.length - 1 ) === "\\" ) {
2763          continue;
2764        }
2765
2766        if ( curLoop === result ) {
2767          result = [];
2768        }
2769
2770        if ( Expr.preFilter[ type ] ) {
2771          match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
2772
2773          if ( !match ) {
2774            anyFound = found = true;
2775          } else if ( match === true ) {
2776            continue;
2777          }
2778        }
2779
2780        if ( match ) {
2781          for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
2782            if ( item ) {
2783              found = filter( item, match, i, curLoop );
2784              var pass = not ^ !!found;
2785
2786              if ( inplace && found != null ) {
2787                if ( pass ) {
2788                  anyFound = true;
2789                } else {
2790                  curLoop[i] = false;
2791                }
2792              } else if ( pass ) {
2793                result.push( item );
2794                anyFound = true;
2795              }
2796            }
2797          }
2798        }
2799
2800        if ( found !== undefined ) {
2801          if ( !inplace ) {
2802            curLoop = result;
2803          }
2804
2805          expr = expr.replace( Expr.match[ type ], "" );
2806
2807          if ( !anyFound ) {
2808            return [];
2809          }
2810
2811          break;
2812        }
2813      }
2814    }
2815
2816    // Improper expression
2817    if ( expr === old ) {
2818      if ( anyFound == null ) {
2819        Sizzle.error( expr );
2820      } else {
2821        break;
2822      }
2823    }
2824
2825    old = expr;
2826  }
2827
2828  return curLoop;
2829};
2830
2831Sizzle.error = function( msg ) {
2832  throw "Syntax error, unrecognized expression: " + msg;
2833};
2834
2835var Expr = Sizzle.selectors = {
2836  order: [ "ID", "NAME", "TAG" ],
2837  match: {
2838    ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2839    CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2840    NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
2841    ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
2842    TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
2843    CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
2844    POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
2845    PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
2846  },
2847  leftMatch: {},
2848  attrMap: {
2849    "class": "className",
2850    "for": "htmlFor"
2851  },
2852  attrHandle: {
2853    href: function(elem){
2854      return elem.getAttribute("href");
2855    }
2856  },
2857  relative: {
2858    "+": function(checkSet, part){
2859      var isPartStr = typeof part === "string",
2860        isTag = isPartStr && !/\W/.test(part),
2861        isPartStrNotTag = isPartStr && !isTag;
2862
2863      if ( isTag ) {
2864        part = part.toLowerCase();
2865      }
2866
2867      for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
2868        if ( (elem = checkSet[i]) ) {
2869          while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
2870
2871          checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
2872            elem || false :
2873            elem === part;
2874        }
2875      }
2876
2877      if ( isPartStrNotTag ) {
2878        Sizzle.filter( part, checkSet, true );
2879      }
2880    },
2881    ">": function(checkSet, part){
2882      var isPartStr = typeof part === "string";
2883
2884      if ( isPartStr && !/\W/.test(part) ) {
2885        part = part.toLowerCase();
2886
2887        for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2888          var elem = checkSet[i];
2889          if ( elem ) {
2890            var parent = elem.parentNode;
2891            checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
2892          }
2893        }
2894      } else {
2895        for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2896          var elem = checkSet[i];
2897          if ( elem ) {
2898            checkSet[i] = isPartStr ?
2899              elem.parentNode :
2900              elem.parentNode === part;
2901          }
2902        }
2903
2904        if ( isPartStr ) {
2905          Sizzle.filter( part, checkSet, true );
2906        }
2907      }
2908    },
2909    "": function(checkSet, part, isXML){
2910      var doneName = done++, checkFn = dirCheck;
2911
2912      if ( typeof part === "string" && !/\W/.test(part) ) {
2913        var nodeCheck = part = part.toLowerCase();
2914        checkFn = dirNodeCheck;
2915      }
2916
2917      checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
2918    },
2919    "~": function(checkSet, part, isXML){
2920      var doneName = done++, checkFn = dirCheck;
2921
2922      if ( typeof part === "string" && !/\W/.test(part) ) {
2923        var nodeCheck = part = part.toLowerCase();
2924        checkFn = dirNodeCheck;
2925      }
2926
2927      checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
2928    }
2929  },
2930  find: {
2931    ID: function(match, context, isXML){
2932      if ( typeof context.getElementById !== "undefined" && !isXML ) {
2933        var m = context.getElementById(match[1]);
2934        return m ? [m] : [];
2935      }
2936    },
2937    NAME: function(match, context){
2938      if ( typeof context.getElementsByName !== "undefined" ) {
2939        var ret = [], results = context.getElementsByName(match[1]);
2940
2941        for ( var i = 0, l = results.length; i < l; i++ ) {
2942          if ( results[i].getAttribute("name") === match[1] ) {
2943            ret.push( results[i] );
2944          }
2945        }
2946
2947        return ret.length === 0 ? null : ret;
2948      }
2949    },
2950    TAG: function(match, context){
2951      return context.getElementsByTagName(match[1]);
2952    }
2953  },
2954  preFilter: {
2955    CLASS: function(match, curLoop, inplace, result, not, isXML){
2956      match = " " + match[1].replace(/\\/g, "") + " ";
2957
2958      if ( isXML ) {
2959        return match;
2960      }
2961
2962      for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
2963        if ( elem ) {
2964          if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
2965            if ( !inplace ) {
2966              result.push( elem );
2967            }
2968          } else if ( inplace ) {
2969            curLoop[i] = false;
2970          }
2971        }
2972      }
2973
2974      return false;
2975    },
2976    ID: function(match){
2977      return match[1].replace(/\\/g, "");
2978    },
2979    TAG: function(match, curLoop){
2980      return match[1].toLowerCase();
2981    },
2982    CHILD: function(match){
2983      if ( match[1] === "nth" ) {
2984        // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
2985        var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
2986          match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
2987          !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
2988
2989        // calculate the numbers (first)n+(last) including if they are negative
2990        match[2] = (test[1] + (test[2] || 1)) - 0;
2991        match[3] = test[3] - 0;
2992      }
2993
2994      // TODO: Move to normal caching system
2995      match[0] = done++;
2996
2997      return match;
2998    },
2999    ATTR: function(match, curLoop, inplace, result, not, isXML){
3000      var name = match[1].replace(/\\/g, "");
3001     
3002      if ( !isXML && Expr.attrMap[name] ) {
3003        match[1] = Expr.attrMap[name];
3004      }
3005
3006      if ( match[2] === "~=" ) {
3007        match[4] = " " + match[4] + " ";
3008      }
3009
3010      return match;
3011    },
3012    PSEUDO: function(match, curLoop, inplace, result, not){
3013      if ( match[1] === "not" ) {
3014        // If we're dealing with a complex expression, or a simple one
3015        if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
3016          match[3] = Sizzle(match[3], null, null, curLoop);
3017        } else {
3018          var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
3019          if ( !inplace ) {
3020            result.push.apply( result, ret );
3021          }
3022          return false;
3023        }
3024      } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
3025        return true;
3026      }
3027     
3028      return match;
3029    },
3030    POS: function(match){
3031      match.unshift( true );
3032      return match;
3033    }
3034  },
3035  filters: {
3036    enabled: function(elem){
3037      return elem.disabled === false && elem.type !== "hidden";
3038    },
3039    disabled: function(elem){
3040      return elem.disabled === true;
3041    },
3042    checked: function(elem){
3043      return elem.checked === true;
3044    },
3045    selected: function(elem){
3046      // Accessing this property makes selected-by-default
3047      // options in Safari work properly
3048      elem.parentNode.selectedIndex;
3049      return elem.selected === true;
3050    },
3051    parent: function(elem){
3052      return !!elem.firstChild;
3053    },
3054    empty: function(elem){
3055      return !elem.firstChild;
3056    },
3057    has: function(elem, i, match){
3058      return !!Sizzle( match[3], elem ).length;
3059    },
3060    header: function(elem){
3061      return /h\d/i.test( elem.nodeName );
3062    },
3063    text: function(elem){
3064      return "text" === elem.type;
3065    },
3066    radio: function(elem){
3067      return "radio" === elem.type;
3068    },
3069    checkbox: function(elem){
3070      return "checkbox" === elem.type;
3071    },
3072    file: function(elem){
3073      return "file" === elem.type;
3074    },
3075    password: function(elem){
3076      return "password" === elem.type;
3077    },
3078    submit: function(elem){
3079      return "submit" === elem.type;
3080    },
3081    image: function(elem){
3082      return "image" === elem.type;
3083    },
3084    reset: function(elem){
3085      return "reset" === elem.type;
3086    },
3087    button: function(elem){
3088      return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
3089    },
3090    input: function(elem){
3091      return /input|select|textarea|button/i.test(elem.nodeName);
3092    }
3093  },
3094  setFilters: {
3095    first: function(elem, i){
3096      return i === 0;
3097    },
3098    last: function(elem, i, match, array){
3099      return i === array.length - 1;
3100    },
3101    even: function(elem, i){
3102      return i % 2 === 0;
3103    },
3104    odd: function(elem, i){
3105      return i % 2 === 1;
3106    },
3107    lt: function(elem, i, match){
3108      return i < match[3] - 0;
3109    },
3110    gt: function(elem, i, match){
3111      return i > match[3] - 0;
3112    },
3113    nth: function(elem, i, match){
3114      return match[3] - 0 === i;
3115    },
3116    eq: function(elem, i, match){
3117      return match[3] - 0 === i;
3118    }
3119  },
3120  filter: {
3121    PSEUDO: function(elem, match, i, array){
3122      var name = match[1], filter = Expr.filters[ name ];
3123
3124      if ( filter ) {
3125        return filter( elem, i, match, array );
3126      } else if ( name === "contains" ) {
3127        return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
3128      } else if ( name === "not" ) {
3129        var not = match[3];
3130
3131        for ( var i = 0, l = not.length; i < l; i++ ) {
3132          if ( not[i] === elem ) {
3133            return false;
3134          }
3135        }
3136
3137        return true;
3138      } else {
3139        Sizzle.error( "Syntax error, unrecognized expression: " + name );
3140      }
3141    },
3142    CHILD: function(elem, match){
3143      var type = match[1], node = elem;
3144      switch (type) {
3145        case 'only':
3146        case 'first':
3147          while ( (node = node.previousSibling) )  {
3148            if ( node.nodeType === 1 ) {
3149              return false;
3150            }
3151          }
3152          if ( type === "first" ) {
3153            return true;
3154          }
3155          node = elem;
3156        case 'last':
3157          while ( (node = node.nextSibling) )  {
3158            if ( node.nodeType === 1 ) {
3159              return false;
3160            }
3161          }
3162          return true;
3163        case 'nth':
3164          var first = match[2], last = match[3];
3165
3166          if ( first === 1 && last === 0 ) {
3167            return true;
3168          }
3169         
3170          var doneName = match[0],
3171            parent = elem.parentNode;
3172 
3173          if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
3174            var count = 0;
3175            for ( node = parent.firstChild; node; node = node.nextSibling ) {
3176              if ( node.nodeType === 1 ) {
3177                node.nodeIndex = ++count;
3178              }
3179            }
3180            parent.sizcache = doneName;
3181          }
3182         
3183          var diff = elem.nodeIndex - last;
3184          if ( first === 0 ) {
3185            return diff === 0;
3186          } else {
3187            return ( diff % first === 0 && diff / first >= 0 );
3188          }
3189      }
3190    },
3191    ID: function(elem, match){
3192      return elem.nodeType === 1 && elem.getAttribute("id") === match;
3193    },
3194    TAG: function(elem, match){
3195      return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
3196    },
3197    CLASS: function(elem, match){
3198      return (" " + (elem.className || elem.getAttribute("class")) + " ")
3199        .indexOf( match ) > -1;
3200    },
3201    ATTR: function(elem, match){
3202      var name = match[1],
3203        result = Expr.attrHandle[ name ] ?
3204          Expr.attrHandle[ name ]( elem ) :
3205          elem[ name ] != null ?
3206            elem[ name ] :
3207            elem.getAttribute( name ),
3208        value = result + "",
3209        type = match[2],
3210        check = match[4];
3211
3212      return result == null ?
3213        type === "!=" :
3214        type === "=" ?
3215        value === check :
3216        type === "*=" ?
3217        value.indexOf(check) >= 0 :
3218        type === "~=" ?
3219        (" " + value + " ").indexOf(check) >= 0 :
3220        !check ?
3221        value && result !== false :
3222        type === "!=" ?
3223        value !== check :
3224        type === "^=" ?
3225        value.indexOf(check) === 0 :
3226        type === "$=" ?
3227        value.substr(value.length - check.length) === check :
3228        type === "|=" ?
3229        value === check || value.substr(0, check.length + 1) === check + "-" :
3230        false;
3231    },
3232    POS: function(elem, match, i, array){
3233      var name = match[2], filter = Expr.setFilters[ name ];
3234
3235      if ( filter ) {
3236        return filter( elem, i, match, array );
3237      }
3238    }
3239  }
3240};
3241
3242var origPOS = Expr.match.POS;
3243
3244for ( var type in Expr.match ) {
3245  Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
3246  Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
3247    return "\\" + (num - 0 + 1);
3248  }));
3249}
3250
3251var makeArray = function(array, results) {
3252  array = Array.prototype.slice.call( array, 0 );
3253
3254  if ( results ) {
3255    results.push.apply( results, array );
3256    return results;
3257  }
3258 
3259  return array;
3260};
3261
3262// Perform a simple check to determine if the browser is capable of
3263// converting a NodeList to an array using builtin methods.
3264try {
3265  Array.prototype.slice.call( document.documentElement.childNodes, 0 );
3266
3267// Provide a fallback method if it does not work
3268} catch(e){
3269  makeArray = function(array, results) {
3270    var ret = results || [];
3271
3272    if ( toString.call(array) === "[object Array]" ) {
3273      Array.prototype.push.apply( ret, array );
3274    } else {
3275      if ( typeof array.length === "number" ) {
3276        for ( var i = 0, l = array.length; i < l; i++ ) {
3277          ret.push( array[i] );
3278        }
3279      } else {
3280        for ( var i = 0; array[i]; i++ ) {
3281          ret.push( array[i] );
3282        }
3283      }
3284    }
3285
3286    return ret;
3287  };
3288}
3289
3290var sortOrder;
3291
3292if ( document.documentElement.compareDocumentPosition ) {
3293  sortOrder = function( a, b ) {
3294    if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
3295      if ( a == b ) {
3296        hasDuplicate = true;
3297      }
3298      return a.compareDocumentPosition ? -1 : 1;
3299    }
3300
3301    var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
3302    if ( ret === 0 ) {
3303      hasDuplicate = true;
3304    }
3305    return ret;
3306  };
3307} else if ( "sourceIndex" in document.documentElement ) {
3308  sortOrder = function( a, b ) {
3309    if ( !a.sourceIndex || !b.sourceIndex ) {
3310      if ( a == b ) {
3311        hasDuplicate = true;
3312      }
3313      return a.sourceIndex ? -1 : 1;
3314    }
3315
3316    var ret = a.sourceIndex - b.sourceIndex;
3317    if ( ret === 0 ) {
3318      hasDuplicate = true;
3319    }
3320    return ret;
3321  };
3322} else if ( document.createRange ) {
3323  sortOrder = function( a, b ) {
3324    if ( !a.ownerDocument || !b.ownerDocument ) {
3325      if ( a == b ) {
3326        hasDuplicate = true;
3327      }
3328      return a.ownerDocument ? -1 : 1;
3329    }
3330
3331    var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
3332    aRange.setStart(a, 0);
3333    aRange.setEnd(a, 0);
3334    bRange.setStart(b, 0);
3335    bRange.setEnd(b, 0);
3336    var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
3337    if ( ret === 0 ) {
3338      hasDuplicate = true;
3339    }
3340    return ret;
3341  };
3342}
3343
3344// Utility function for retreiving the text value of an array of DOM nodes
3345function getText( elems ) {
3346  var ret = "", elem;
3347
3348  for ( var i = 0; elems[i]; i++ ) {
3349    elem = elems[i];
3350
3351    // Get the text from text nodes and CDATA nodes
3352    if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
3353      ret += elem.nodeValue;
3354
3355    // Traverse everything else, except comment nodes
3356    } else if ( elem.nodeType !== 8 ) {
3357      ret += getText( elem.childNodes );
3358    }
3359  }
3360
3361  return ret;
3362}
3363
3364// Check to see if the browser returns elements by name when
3365// querying by getElementById (and provide a workaround)
3366(function(){
3367  // We're going to inject a fake input element with a specified name
3368  var form = document.createElement("div"),
3369    id = "script" + (new Date).getTime();
3370  form.innerHTML = "<a name='" + id + "'/>";
3371
3372  // Inject it into the root element, check its status, and remove it quickly
3373  var root = document.documentElement;
3374  root.insertBefore( form, root.firstChild );
3375
3376  // The workaround has to do additional checks after a getElementById
3377  // Which slows things down for other browsers (hence the branching)
3378  if ( document.getElementById( id ) ) {
3379    Expr.find.ID = function(match, context, isXML){
3380      if ( typeof context.getElementById !== "undefined" && !isXML ) {
3381        var m = context.getElementById(match[1]);
3382        return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
3383      }
3384    };
3385
3386    Expr.filter.ID = function(elem, match){
3387      var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
3388      return elem.nodeType === 1 && node && node.nodeValue === match;
3389    };
3390  }
3391
3392  root.removeChild( form );
3393  root = form = null; // release memory in IE
3394})();
3395
3396(function(){
3397  // Check to see if the browser returns only elements
3398  // when doing getElementsByTagName("*")
3399
3400  // Create a fake element
3401  var div = document.createElement("div");
3402  div.appendChild( document.createComment("") );
3403
3404  // Make sure no comments are found
3405  if ( div.getElementsByTagName("*").length > 0 ) {
3406    Expr.find.TAG = function(match, context){
3407      var results = context.getElementsByTagName(match[1]);
3408
3409      // Filter out possible comments
3410      if ( match[1] === "*" ) {
3411        var tmp = [];
3412
3413        for ( var i = 0; results[i]; i++ ) {
3414          if ( results[i].nodeType === 1 ) {
3415            tmp.push( results[i] );
3416          }
3417        }
3418
3419        results = tmp;
3420      }
3421
3422      return results;
3423    };
3424  }
3425
3426  // Check to see if an attribute returns normalized href attributes
3427  div.innerHTML = "<a href='#'></a>";
3428  if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
3429      div.firstChild.getAttribute("href") !== "#" ) {
3430    Expr.attrHandle.href = function(elem){
3431      return elem.getAttribute("href", 2);
3432    };
3433  }
3434
3435  div = null; // release memory in IE
3436})();
3437
3438if ( document.querySelectorAll ) {
3439  (function(){
3440    var oldSizzle = Sizzle, div = document.createElement("div");
3441    div.innerHTML = "<p class='TEST'></p>";
3442
3443    // Safari can't handle uppercase or unicode characters when
3444    // in quirks mode.
3445    if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
3446      return;
3447    }
3448 
3449    Sizzle = function(query, context, extra, seed){
3450      context = context || document;
3451
3452      // Only use querySelectorAll on non-XML documents
3453      // (ID selectors don't work in non-HTML documents)
3454      if ( !seed && context.nodeType === 9 && !isXML(context) ) {
3455        try {
3456          return makeArray( context.querySelectorAll(query), extra );
3457        } catch(e){}
3458      }
3459   
3460      return oldSizzle(query, context, extra, seed);
3461    };
3462
3463    for ( var prop in oldSizzle ) {
3464      Sizzle[ prop ] = oldSizzle[ prop ];
3465    }
3466
3467    div = null; // release memory in IE
3468  })();
3469}
3470
3471(function(){
3472  var div = document.createElement("div");
3473
3474  div.innerHTML = "<div class='test e'></div><div class='test'></div>";
3475
3476  // Opera can't find a second classname (in 9.6)
3477  // Also, make sure that getElementsByClassName actually exists
3478  if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
3479    return;
3480  }
3481
3482  // Safari caches class attributes, doesn't catch changes (in 3.2)
3483  div.lastChild.className = "e";
3484
3485  if ( div.getElementsByClassName("e").length === 1 ) {
3486    return;
3487  }
3488 
3489  Expr.order.splice(1, 0, "CLASS");
3490  Expr.find.CLASS = function(match, context, isXML) {
3491    if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
3492      return context.getElementsByClassName(match[1]);
3493    }
3494  };
3495
3496  div = null; // release memory in IE
3497})();
3498
3499function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3500  for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3501    var elem = checkSet[i];
3502    if ( elem ) {
3503      elem = elem[dir];
3504      var match = false;
3505
3506      while ( elem ) {
3507        if ( elem.sizcache === doneName ) {
3508          match = checkSet[elem.sizset];
3509          break;
3510        }
3511
3512        if ( elem.nodeType === 1 && !isXML ){
3513          elem.sizcache = doneName;
3514          elem.sizset = i;
3515        }
3516
3517        if ( elem.nodeName.toLowerCase() === cur ) {
3518          match = elem;
3519          break;
3520        }
3521
3522        elem = elem[dir];
3523      }
3524
3525      checkSet[i] = match;
3526    }
3527  }
3528}
3529
3530function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3531  for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3532    var elem = checkSet[i];
3533    if ( elem ) {
3534      elem = elem[dir];
3535      var match = false;
3536
3537      while ( elem ) {
3538        if ( elem.sizcache === doneName ) {
3539          match = checkSet[elem.sizset];
3540          break;
3541        }
3542
3543        if ( elem.nodeType === 1 ) {
3544          if ( !isXML ) {
3545            elem.sizcache = doneName;
3546            elem.sizset = i;
3547          }
3548          if ( typeof cur !== "string" ) {
3549            if ( elem === cur ) {
3550              match = true;
3551              break;
3552            }
3553
3554          } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
3555            match = elem;
3556            break;
3557          }
3558        }
3559
3560        elem = elem[dir];
3561      }
3562
3563      checkSet[i] = match;
3564    }
3565  }
3566}
3567
3568var contains = document.compareDocumentPosition ? function(a, b){
3569  return a.compareDocumentPosition(b) & 16;
3570} : function(a, b){
3571  return a !== b && (a.contains ? a.contains(b) : true);
3572};
3573
3574var isXML = function(elem){
3575  // documentElement is verified for cases where it doesn't yet exist
3576  // (such as loading iframes in IE - #4833)
3577  var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
3578  return documentElement ? documentElement.nodeName !== "HTML" : false;
3579};
3580
3581var posProcess = function(selector, context){
3582  var tmpSet = [], later = "", match,
3583    root = context.nodeType ? [context] : context;
3584
3585  // Position selectors must be done after the filter
3586  // And so must :not(positional) so we move all PSEUDOs to the end
3587  while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
3588    later += match[0];
3589    selector = selector.replace( Expr.match.PSEUDO, "" );
3590  }
3591
3592  selector = Expr.relative[selector] ? selector + "*" : selector;
3593
3594  for ( var i = 0, l = root.length; i < l; i++ ) {
3595    Sizzle( selector, root[i], tmpSet );
3596  }
3597
3598  return Sizzle.filter( later, tmpSet );
3599};
3600
3601// EXPOSE
3602jQuery.find = Sizzle;
3603jQuery.expr = Sizzle.selectors;
3604jQuery.expr[":"] = jQuery.expr.filters;
3605jQuery.unique = Sizzle.uniqueSort;
3606jQuery.getText = getText;
3607jQuery.isXMLDoc = isXML;
3608jQuery.contains = contains;
3609
3610return;
3611
3612window.Sizzle = Sizzle;
3613
3614})();
3615var runtil = /Until$/,
3616  rparentsprev = /^(?:parents|prevUntil|prevAll)/,
3617  // Note: This RegExp should be improved, or likely pulled from Sizzle
3618  rmultiselector = /,/,
3619  slice = Array.prototype.slice;
3620
3621// Implement the identical functionality for filter and not
3622var winnow = function( elements, qualifier, keep ) {
3623  if ( jQuery.isFunction( qualifier ) ) {
3624    return jQuery.grep(elements, function( elem, i ) {
3625      return !!qualifier.call( elem, i, elem ) === keep;
3626    });
3627
3628  } else if ( qualifier.nodeType ) {
3629    return jQuery.grep(elements, function( elem, i ) {
3630      return (elem === qualifier) === keep;
3631    });
3632
3633  } else if ( typeof qualifier === "string" ) {
3634    var filtered = jQuery.grep(elements, function( elem ) {
3635      return elem.nodeType === 1;
3636    });
3637
3638    if ( isSimple.test( qualifier ) ) {
3639      return jQuery.filter(qualifier, filtered, !keep);
3640    } else {
3641      qualifier = jQuery.filter( qualifier, filtered );
3642    }
3643  }
3644
3645  return jQuery.grep(elements, function( elem, i ) {
3646    return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
3647  });
3648};
3649
3650jQuery.fn.extend({
3651  find: function( selector ) {
3652    var ret = this.pushStack( "", "find", selector ), length = 0;
3653
3654    for ( var i = 0, l = this.length; i < l; i++ ) {
3655      length = ret.length;
3656      jQuery.find( selector, this[i], ret );
3657
3658      if ( i > 0 ) {
3659        // Make sure that the results are unique
3660        for ( var n = length; n < ret.length; n++ ) {
3661          for ( var r = 0; r < length; r++ ) {
3662            if ( ret[r] === ret[n] ) {
3663              ret.splice(n--, 1);
3664              break;
3665            }
3666          }
3667        }
3668      }
3669    }
3670
3671    return ret;
3672  },
3673
3674  has: function( target ) {
3675    var targets = jQuery( target );
3676    return this.filter(function() {
3677      for ( var i = 0, l = targets.length; i < l; i++ ) {
3678        if ( jQuery.contains( this, targets[i] ) ) {
3679          return true;
3680        }
3681      }
3682    });
3683  },
3684
3685  not: function( selector ) {
3686    return this.pushStack( winnow(this, selector, false), "not", selector);
3687  },
3688
3689  filter: function( selector ) {
3690    return this.pushStack( winnow(this, selector, true), "filter", selector );
3691  },
3692 
3693  is: function( selector ) {
3694    return !!selector && jQuery.filter( selector, this ).length > 0;
3695  },
3696
3697  closest: function( selectors, context ) {
3698    if ( jQuery.isArray( selectors ) ) {
3699      var ret = [], cur = this[0], match, matches = {}, selector;
3700
3701      if ( cur && selectors.length ) {
3702        for ( var i = 0, l = selectors.length; i < l; i++ ) {
3703          selector = selectors[i];
3704
3705          if ( !matches[selector] ) {
3706            matches[selector] = jQuery.expr.match.POS.test( selector ) ?
3707              jQuery( selector, context || this.context ) :
3708              selector;
3709          }
3710        }
3711
3712        while ( cur && cur.ownerDocument && cur !== context ) {
3713          for ( selector in matches ) {
3714            match = matches[selector];
3715
3716            if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
3717              ret.push({ selector: selector, elem: cur });
3718              delete matches[selector];
3719            }
3720          }
3721          cur = cur.parentNode;
3722        }
3723      }
3724
3725      return ret;
3726    }
3727
3728    var pos = jQuery.expr.match.POS.test( selectors ) ?
3729      jQuery( selectors, context || this.context ) : null;
3730
3731    return this.map(function( i, cur ) {
3732      while ( cur && cur.ownerDocument && cur !== context ) {
3733        if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
3734          return cur;
3735        }
3736        cur = cur.parentNode;
3737      }
3738      return null;
3739    });
3740  },
3741 
3742  // Determine the position of an element within
3743  // the matched set of elements
3744  index: function( elem ) {
3745    if ( !elem || typeof elem === "string" ) {
3746      return jQuery.inArray( this[0],
3747        // If it receives a string, the selector is used
3748        // If it receives nothing, the siblings are used
3749        elem ? jQuery( elem ) : this.parent().children() );
3750    }
3751    // Locate the position of the desired element
3752    return jQuery.inArray(
3753      // If it receives a jQuery object, the first element is used
3754      elem.jquery ? elem[0] : elem, this );
3755  },
3756
3757  add: function( selector, context ) {
3758    var set = typeof selector === "string" ?
3759        jQuery( selector, context || this.context ) :
3760        jQuery.makeArray( selector ),
3761      all = jQuery.merge( this.get(), set );
3762
3763    return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
3764      all :
3765      jQuery.unique( all ) );
3766  },
3767
3768  andSelf: function() {
3769    return this.add( this.prevObject );
3770  }
3771});
3772
3773// A painfully simple check to see if an element is disconnected
3774// from a document (should be improved, where feasible).
3775function isDisconnected( node ) {
3776  return !node || !node.parentNode || node.parentNode.nodeType === 11;
3777}
3778
3779jQuery.each({
3780  parent: function( elem ) {
3781    var parent = elem.parentNode;
3782    return parent && parent.nodeType !== 11 ? parent : null;
3783  },
3784  parents: function( elem ) {
3785    return jQuery.dir( elem, "parentNode" );
3786  },
3787  parentsUntil: function( elem, i, until ) {
3788    return jQuery.dir( elem, "parentNode", until );
3789  },
3790  next: function( elem ) {
3791    return jQuery.nth( elem, 2, "nextSibling" );
3792  },
3793  prev: function( elem ) {
3794    return jQuery.nth( elem, 2, "previousSibling" );
3795  },
3796  nextAll: function( elem ) {
3797    return jQuery.dir( elem, "nextSibling" );
3798  },
3799  prevAll: function( elem ) {
3800    return jQuery.dir( elem, "previousSibling" );
3801  },
3802  nextUntil: function( elem, i, until ) {
3803    return jQuery.dir( elem, "nextSibling", until );
3804  },
3805  prevUntil: function( elem, i, until ) {
3806    return jQuery.dir( elem, "previousSibling", until );
3807  },
3808  siblings: function( elem ) {
3809    return jQuery.sibling( elem.parentNode.firstChild, elem );
3810  },
3811  children: function( elem ) {
3812    return jQuery.sibling( elem.firstChild );
3813  },
3814  contents: function( elem ) {
3815    return jQuery.nodeName( elem, "iframe" ) ?
3816      elem.contentDocument || elem.contentWindow.document :
3817      jQuery.makeArray( elem.childNodes );
3818  }
3819}, function( name, fn ) {
3820  jQuery.fn[ name ] = function( until, selector ) {
3821    var ret = jQuery.map( this, fn, until );
3822   
3823    if ( !runtil.test( name ) ) {
3824      selector = until;
3825    }
3826
3827    if ( selector && typeof selector === "string" ) {
3828      ret = jQuery.filter( selector, ret );
3829    }
3830
3831    ret = this.length > 1 ? jQuery.unique( ret ) : ret;
3832
3833    if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
3834      ret = ret.reverse();
3835    }
3836
3837    return this.pushStack( ret, name, slice.call(arguments).join(",") );
3838  };
3839});
3840
3841jQuery.extend({
3842  filter: function( expr, elems, not ) {
3843    if ( not ) {
3844      expr = ":not(" + expr + ")";
3845    }
3846
3847    return jQuery.find.matches(expr, elems);
3848  },
3849 
3850  dir: function( elem, dir, until ) {
3851    var matched = [], cur = elem[dir];
3852    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
3853      if ( cur.nodeType === 1 ) {
3854        matched.push( cur );
3855      }
3856      cur = cur[dir];
3857    }
3858    return matched;
3859  },
3860
3861  nth: function( cur, result, dir, elem ) {
3862    result = result || 1;
3863    var num = 0;
3864
3865    for ( ; cur; cur = cur[dir] ) {
3866      if ( cur.nodeType === 1 && ++num === result ) {
3867        break;
3868      }
3869    }
3870
3871    return cur;
3872  },
3873
3874  sibling: function( n, elem ) {
3875    var r = [];
3876
3877    for ( ; n; n = n.nextSibling ) {
3878      if ( n.nodeType === 1 && n !== elem ) {
3879        r.push( n );
3880      }
3881    }
3882
3883    return r;
3884  }
3885});
3886var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
3887  rleadingWhitespace = /^\s+/,
3888  rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
3889  rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
3890  rtagName = /<([\w:]+)/,
3891  rtbody = /<tbody/i,
3892  rhtml = /<|&\w+;/,
3893  rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,  // checked="checked" or checked (html5)
3894  fcloseTag = function( all, front, tag ) {
3895    return rselfClosing.test( tag ) ?
3896      all :
3897      front + "></" + tag + ">";
3898  },
3899  wrapMap = {
3900    option: [ 1, "<select multiple='multiple'>", "</select>" ],
3901    legend: [ 1, "<fieldset>", "</fieldset>" ],
3902    thead: [ 1, "<table>", "</table>" ],
3903    tr: [ 2, "<table><tbody>", "</tbody></table>" ],
3904    td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
3905    col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
3906    area: [ 1, "<map>", "</map>" ],
3907    _default: [ 0, "", "" ]
3908  };
3909
3910wrapMap.optgroup = wrapMap.option;
3911wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
3912wrapMap.th = wrapMap.td;
3913
3914// IE can't serialize <link> and <script> tags normally
3915if ( !jQuery.support.htmlSerialize ) {
3916  wrapMap._default = [ 1, "div<div>", "</div>" ];
3917}
3918
3919jQuery.fn.extend({
3920  text: function( text ) {
3921    if ( jQuery.isFunction(text) ) {
3922      return this.each(function(i) {
3923        var self = jQuery(this);
3924        self.text( text.call(this, i, self.text()) );
3925      });
3926    }
3927
3928    if ( typeof text !== "object" && text !== undefined ) {
3929      return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
3930    }
3931
3932    return jQuery.getText( this );
3933  },
3934
3935  wrapAll: function( html ) {
3936    if ( jQuery.isFunction( html ) ) {
3937      return this.each(function(i) {
3938        jQuery(this).wrapAll( html.call(this, i) );
3939      });
3940    }
3941
3942    if ( this[0] ) {
3943      // The elements to wrap the target around
3944      var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
3945
3946      if ( this[0].parentNode ) {
3947        wrap.insertBefore( this[0] );
3948      }
3949
3950      wrap.map(function() {
3951        var elem = this;
3952
3953        while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
3954          elem = elem.firstChild;
3955        }
3956
3957        return elem;
3958      }).append(this);
3959    }
3960
3961    return this;
3962  },
3963
3964  wrapInner: function( html ) {
3965    if ( jQuery.isFunction( html ) ) {
3966      return this.each(function(i) {
3967        jQuery(this).wrapInner( html.call(this, i) );
3968      });
3969    }
3970
3971    return this.each(function() {
3972      var self = jQuery( this ), contents = self.contents();
3973
3974      if ( contents.length ) {
3975        contents.wrapAll( html );
3976
3977      } else {
3978        self.append( html );
3979      }
3980    });
3981  },
3982
3983  wrap: function( html ) {
3984    return this.each(function() {
3985      jQuery( this ).wrapAll( html );
3986    });
3987  },
3988
3989  unwrap: function() {
3990    return this.parent().each(function() {
3991      if ( !jQuery.nodeName( this, "body" ) ) {
3992        jQuery( this ).replaceWith( this.childNodes );
3993      }
3994    }).end();
3995  },
3996
3997  append: function() {
3998    return this.domManip(arguments, true, function( elem ) {
3999      if ( this.nodeType === 1 ) {
4000        this.appendChild( elem );
4001      }
4002    });
4003  },
4004
4005  prepend: function() {
4006    return this.domManip(arguments, true, function( elem ) {
4007      if ( this.nodeType === 1 ) {
4008        this.insertBefore( elem, this.firstChild );
4009      }
4010    });
4011  },
4012
4013  before: function() {
4014    if ( this[0] && this[0].parentNode ) {
4015      return this.domManip(arguments, false, function( elem ) {
4016        this.parentNode.insertBefore( elem, this );
4017      });
4018    } else if ( arguments.length ) {
4019      var set = jQuery(arguments[0]);
4020      set.push.apply( set, this.toArray() );
4021      return this.pushStack( set, "before", arguments );
4022    }
4023  },
4024
4025  after: function() {
4026    if ( this[0] && this[0].parentNode ) {
4027      return this.domManip(arguments, false, function( elem ) {
4028        this.parentNode.insertBefore( elem, this.nextSibling );
4029      });
4030    } else if ( arguments.length ) {
4031      var set = this.pushStack( this, "after", arguments );
4032      set.push.apply( set, jQuery(arguments[0]).toArray() );
4033      return set;
4034    }
4035  },
4036
4037  clone: function( events ) {
4038    // Do the clone
4039    var ret = this.map(function() {
4040      if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
4041        // IE copies events bound via attachEvent when
4042        // using cloneNode. Calling detachEvent on the
4043        // clone will also remove the events from the orignal
4044        // In order to get around this, we use innerHTML.
4045        // Unfortunately, this means some modifications to
4046        // attributes in IE that are actually only stored
4047        // as properties will not be copied (such as the
4048        // the name attribute on an input).
4049        var html = this.outerHTML, ownerDocument = this.ownerDocument;
4050        if ( !html ) {
4051          var div = ownerDocument.createElement("div");
4052          div.appendChild( this.cloneNode(true) );
4053          html = div.innerHTML;
4054        }
4055
4056        return jQuery.clean([html.replace(rinlinejQuery, "")
4057          .replace(rleadingWhitespace, "")], ownerDocument)[0];
4058      } else {
4059        return this.cloneNode(true);
4060      }
4061    });
4062
4063    // Copy the events from the original to the clone
4064    if ( events === true ) {
4065      cloneCopyEvent( this, ret );
4066      cloneCopyEvent( this.find("*"), ret.find("*") );
4067    }
4068
4069    // Return the cloned set
4070    return ret;
4071  },
4072
4073  html: function( value ) {
4074    if ( value === undefined ) {
4075      return this[0] && this[0].nodeType === 1 ?
4076        this[0].innerHTML.replace(rinlinejQuery, "") :
4077        null;
4078
4079    // See if we can take a shortcut and just use innerHTML
4080    } else if ( typeof value === "string" && !/<script/i.test( value ) &&
4081      (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
4082      !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
4083
4084      value = value.replace(rxhtmlTag, fcloseTag);
4085
4086      try {
4087        for ( var i = 0, l = this.length; i < l; i++ ) {
4088          // Remove element nodes and prevent memory leaks
4089          if ( this[i].nodeType === 1 ) {
4090            jQuery.cleanData( this[i].getElementsByTagName("*") );
4091            this[i].innerHTML = value;
4092          }
4093        }
4094
4095      // If using innerHTML throws an exception, use the fallback method
4096      } catch(e) {
4097        this.empty().append( value );
4098      }
4099
4100    } else if ( jQuery.isFunction( value ) ) {
4101      this.each(function(i){
4102        var self = jQuery(this), old = self.html();
4103        self.empty().append(function(){
4104          return value.call( this, i, old );
4105        });
4106      });
4107
4108    } else {
4109      this.empty().append( value );
4110    }
4111
4112    return this;
4113  },
4114
4115  replaceWith: function( value ) {
4116    if ( this[0] && this[0].parentNode ) {
4117      // Make sure that the elements are removed from the DOM before they are inserted
4118      // this can help fix replacing a parent with child elements
4119      if ( !jQuery.isFunction( value ) ) {
4120        value = jQuery( value ).detach();
4121
4122      } else {
4123        return this.each(function(i) {
4124          var self = jQuery(this), old = self.html();
4125          self.replaceWith( value.call( this, i, old ) );
4126        });
4127      }
4128
4129      return this.each(function() {
4130        var next = this.nextSibling, parent = this.parentNode;
4131
4132        jQuery(this).remove();
4133
4134        if ( next ) {
4135          jQuery(next).before( value );
4136        } else {
4137          jQuery(parent).append( value );
4138        }
4139      });
4140    } else {
4141      return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
4142    }
4143  },
4144
4145  detach: function( selector ) {
4146    return this.remove( selector, true );
4147  },
4148
4149  domManip: function( args, table, callback ) {
4150    var results, first, value = args[0], scripts = [];
4151
4152    // We can't cloneNode fragments that contain checked, in WebKit
4153    if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
4154      return this.each(function() {
4155        jQuery(this).domManip( args, table, callback, true );
4156      });
4157    }
4158
4159    if ( jQuery.isFunction(value) ) {
4160      return this.each(function(i) {
4161        var self = jQuery(this);
4162        args[0] = value.call(this, i, table ? self.html() : undefined);
4163        self.domManip( args, table, callback );
4164      });
4165    }
4166
4167    if ( this[0] ) {
4168      // If we're in a fragment, just use that instead of building a new one
4169      if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) {
4170        results = { fragment: args[0].parentNode };
4171      } else {
4172        results = buildFragment( args, this, scripts );
4173      }
4174
4175      first = results.fragment.firstChild;
4176
4177      if ( first ) {
4178        table = table && jQuery.nodeName( first, "tr" );
4179
4180        for ( var i = 0, l = this.length; i < l; i++ ) {
4181          callback.call(
4182            table ?
4183              root(this[i], first) :
4184              this[i],
4185            results.cacheable || this.length > 1 || i > 0 ?
4186              results.fragment.cloneNode(true) :
4187              results.fragment
4188          );
4189        }
4190      }
4191
4192      if ( scripts ) {
4193        jQuery.each( scripts, evalScript );
4194      }
4195    }
4196
4197    return this;
4198
4199    function root( elem, cur ) {
4200      return jQuery.nodeName(elem, "table") ?
4201        (elem.getElementsByTagName("tbody")[0] ||
4202        elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
4203        elem;
4204    }
4205  }
4206});
4207
4208function cloneCopyEvent(orig, ret) {
4209  var i = 0;
4210
4211  ret.each(function() {
4212    if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
4213      return;
4214    }
4215
4216    var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
4217
4218    if ( events ) {
4219      delete curData.handle;
4220      curData.events = {};
4221
4222      for ( var type in events ) {
4223        for ( var handler in events[ type ] ) {
4224          jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
4225        }
4226      }
4227    }
4228  });
4229}
4230
4231function buildFragment( args, nodes, scripts ) {
4232  var fragment, cacheable, cacheresults, doc;
4233
4234  // webkit does not clone 'checked' attribute of radio inputs on cloneNode, so don't cache if string has a checked
4235  if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
4236    cacheable = true;
4237    cacheresults = jQuery.fragments[ args[0] ];
4238    if ( cacheresults ) {
4239      if ( cacheresults !== 1 ) {
4240        fragment = cacheresults;
4241      }
4242    }
4243  }
4244
4245  if ( !fragment ) {
4246    doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
4247    fragment = doc.createDocumentFragment();
4248    jQuery.clean( args, doc, fragment, scripts );
4249  }
4250
4251  if ( cacheable ) {
4252    jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
4253  }
4254
4255  return { fragment: fragment, cacheable: cacheable };
4256}
4257
4258jQuery.fragments = {};
4259
4260jQuery.each({
4261  appendTo: "append",
4262  prependTo: "prepend",
4263  insertBefore: "before",
4264  insertAfter: "after",
4265  replaceAll: "replaceWith"
4266}, function( name, original ) {
4267  jQuery.fn[ name ] = function( selector ) {
4268    var ret = [], insert = jQuery( selector );
4269
4270    for ( var i = 0, l = insert.length; i < l; i++ ) {
4271      var elems = (i > 0 ? this.clone(true) : this).get();
4272      jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
4273      ret = ret.concat( elems );
4274    }
4275    return this.pushStack( ret, name, insert.selector );
4276  };
4277});
4278
4279jQuery.each({
4280  // keepData is for internal use only--do not document
4281  remove: function( selector, keepData ) {
4282    if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
4283      if ( !keepData && this.nodeType === 1 ) {
4284        jQuery.cleanData( this.getElementsByTagName("*") );
4285        jQuery.cleanData( [ this ] );
4286      }
4287
4288      if ( this.parentNode ) {
4289         this.parentNode.removeChild( this );
4290      }
4291    }
4292  },
4293
4294  empty: function() {
4295    // Remove element nodes and prevent memory leaks
4296    if ( this.nodeType === 1 ) {
4297      jQuery.cleanData( this.getElementsByTagName("*") );
4298    }
4299
4300    // Remove any remaining nodes
4301    while ( this.firstChild ) {
4302      this.removeChild( this.firstChild );
4303    }
4304  }
4305}, function( name, fn ) {
4306  jQuery.fn[ name ] = function() {
4307    return this.each( fn, arguments );
4308  };
4309});
4310
4311jQuery.extend({
4312  clean: function( elems, context, fragment, scripts ) {
4313    context = context || document;
4314
4315    // !context.createElement fails in IE with an error but returns typeof 'object'
4316    if ( typeof context.createElement === "undefined" ) {
4317      context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
4318    }
4319
4320    var ret = [];
4321
4322    jQuery.each(elems, function( i, elem ) {
4323      if ( typeof elem === "number" ) {
4324        elem += "";
4325      }
4326
4327      if ( !elem ) {
4328        return;
4329      }
4330
4331      // Convert html string into DOM nodes
4332      if ( typeof elem === "string" && !rhtml.test( elem ) ) {
4333        elem = context.createTextNode( elem );
4334
4335      } else if ( typeof elem === "string" ) {
4336        // Fix "XHTML"-style tags in all browsers
4337        elem = elem.replace(rxhtmlTag, fcloseTag);
4338
4339        // Trim whitespace, otherwise indexOf won't work as expected
4340        var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
4341          wrap = wrapMap[ tag ] || wrapMap._default,
4342          depth = wrap[0],
4343          div = context.createElement("div");
4344
4345        // Go to html and back, then peel off extra wrappers
4346        div.innerHTML = wrap[1] + elem + wrap[2];
4347
4348        // Move to the right depth
4349        while ( depth-- ) {
4350          div = div.lastChild;
4351        }
4352
4353        // Remove IE's autoinserted <tbody> from table fragments
4354        if ( !jQuery.support.tbody ) {
4355
4356          // String was a <table>, *may* have spurious <tbody>
4357          var hasBody = rtbody.test(elem),
4358            tbody = tag === "table" && !hasBody ?
4359              div.firstChild && div.firstChild.childNodes :
4360
4361              // String was a bare <thead> or <tfoot>
4362              wrap[1] === "<table>" && !hasBody ?
4363                div.childNodes :
4364                [];
4365
4366          for ( var j = tbody.length - 1; j >= 0 ; --j ) {
4367            if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
4368              tbody[ j ].parentNode.removeChild( tbody[ j ] );
4369            }
4370          }
4371
4372        }
4373
4374        // IE completely kills leading whitespace when innerHTML is used
4375        if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
4376          div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
4377        }
4378
4379        elem = jQuery.makeArray( div.childNodes );
4380      }
4381
4382      if ( elem.nodeType ) {
4383        ret.push( elem );
4384      } else {
4385        ret = jQuery.merge( ret, elem );
4386      }
4387
4388    });
4389
4390    if ( fragment ) {
4391      for ( var i = 0; ret[i]; i++ ) {
4392        if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
4393          scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
4394        } else {
4395          if ( ret[i].nodeType === 1 ) {
4396            ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
4397          }
4398          fragment.appendChild( ret[i] );
4399        }
4400      }
4401    }
4402
4403    return ret;
4404  },
4405 
4406  cleanData: function( elems ) {
4407    for ( var i = 0, elem, id; (elem = elems[i]) != null; i++ ) {
4408      jQuery.event.remove( elem );
4409      jQuery.removeData( elem );
4410    }
4411  }
4412});
4413// exclude the following css properties to add px
4414var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
4415  ralpha = /alpha\([^)]*\)/,
4416  ropacity = /opacity=([^)]*)/,
4417  rfloat = /float/i,
4418  rdashAlpha = /-([a-z])/ig,
4419  rupper = /([A-Z])/g,
4420  rnumpx = /^-?\d+(?:px)?$/i,
4421  rnum = /^-?\d/,
4422
4423  cssShow = { position: "absolute", visibility: "hidden", display:"block" },
4424  cssWidth = [ "Left", "Right" ],
4425  cssHeight = [ "Top", "Bottom" ],
4426
4427  // cache check for defaultView.getComputedStyle
4428  getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
4429  // normalize float css property
4430  styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
4431  fcamelCase = function( all, letter ) {
4432    return letter.toUpperCase();
4433  };
4434
4435jQuery.fn.css = function( name, value ) {
4436  return access( this, name, value, true, function( elem, name, value ) {
4437    if ( value === undefined ) {
4438      return jQuery.curCSS( elem, name );
4439    }
4440   
4441    if ( typeof value === "number" && !rexclude.test(name) ) {
4442      value += "px";
4443    }
4444
4445    jQuery.style( elem, name, value );
4446  });
4447};
4448
4449jQuery.extend({
4450  style: function( elem, name, value ) {
4451    // don't set styles on text and comment nodes
4452    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
4453      return undefined;
4454    }
4455
4456    // ignore negative width and height values #1599
4457    if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
4458      value = undefined;
4459    }
4460
4461    var style = elem.style || elem, set = value !== undefined;
4462
4463    // IE uses filters for opacity
4464    if ( !jQuery.support.opacity && name === "opacity" ) {
4465      if ( set ) {
4466        // IE has trouble with opacity if it does not have layout
4467        // Force it by setting the zoom level
4468        style.zoom = 1;
4469
4470        // Set the alpha filter to set the opacity
4471        var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
4472        var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
4473        style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
4474      }
4475
4476      return style.filter && style.filter.indexOf("opacity=") >= 0 ?
4477        (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
4478        "";
4479    }
4480
4481    // Make sure we're using the right name for getting the float value
4482    if ( rfloat.test( name ) ) {
4483      name = styleFloat;
4484    }
4485
4486    name = name.replace(rdashAlpha, fcamelCase);
4487
4488    if ( set ) {
4489      style[ name ] = value;
4490    }
4491
4492    return style[ name ];
4493  },
4494
4495  css: function( elem, name, force, extra ) {
4496    if ( name === "width" || name === "height" ) {
4497      var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
4498
4499      function getWH() {
4500        val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
4501
4502        if ( extra === "border" ) {
4503          return;
4504        }
4505
4506        jQuery.each( which, function() {
4507          if ( !extra ) {
4508            val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
4509          }
4510
4511          if ( extra === "margin" ) {
4512            val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
4513          } else {
4514            val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
4515          }
4516        });
4517      }
4518
4519      if ( elem.offsetWidth !== 0 ) {
4520        getWH();
4521      } else {
4522        jQuery.swap( elem, props, getWH );
4523      }
4524
4525      return Math.max(0, Math.round(val));
4526    }
4527
4528    return jQuery.curCSS( elem, name, force );
4529  },
4530
4531  curCSS: function( elem, name, force ) {
4532    var ret, style = elem.style, filter;
4533
4534    // IE uses filters for opacity
4535    if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
4536      ret = ropacity.test(elem.currentStyle.filter || "") ?
4537        (parseFloat(RegExp.$1) / 100) + "" :
4538        "";
4539
4540      return ret === "" ?
4541        "1" :
4542        ret;
4543    }
4544
4545    // Make sure we're using the right name for getting the float value
4546    if ( rfloat.test( name ) ) {
4547      name = styleFloat;
4548    }
4549
4550    if ( !force && style && style[ name ] ) {
4551      ret = style[ name ];
4552
4553    } else if ( getComputedStyle ) {
4554
4555      // Only "float" is needed here
4556      if ( rfloat.test( name ) ) {
4557        name = "float";
4558      }
4559
4560      name = name.replace( rupper, "-$1" ).toLowerCase();
4561
4562      var defaultView = elem.ownerDocument.defaultView;
4563
4564      if ( !defaultView ) {
4565        return null;
4566      }
4567
4568      var computedStyle = defaultView.getComputedStyle( elem, null );
4569
4570      if ( computedStyle ) {
4571        ret = computedStyle.getPropertyValue( name );
4572      }
4573
4574      // We should always get a number back from opacity
4575      if ( name === "opacity" && ret === "" ) {
4576        ret = "1";
4577      }
4578
4579    } else if ( elem.currentStyle ) {
4580      var camelCase = name.replace(rdashAlpha, fcamelCase);
4581
4582      ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
4583
4584      // From the awesome hack by Dean Edwards
4585      // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
4586
4587      // If we're not dealing with a regular pixel number
4588      // but a number that has a weird ending, we need to convert it to pixels
4589      if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
4590        // Remember the original values
4591        var left = style.left, rsLeft = elem.runtimeStyle.left;
4592
4593        // Put in the new values to get a computed value out
4594        elem.runtimeStyle.left = elem.currentStyle.left;
4595        style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
4596        ret = style.pixelLeft + "px";
4597
4598        // Revert the changed values
4599        style.left = left;
4600        elem.runtimeStyle.left = rsLeft;
4601      }
4602    }
4603
4604    return ret;
4605  },
4606
4607  // A method for quickly swapping in/out CSS properties to get correct calculations
4608  swap: function( elem, options, callback ) {
4609    var old = {};
4610
4611    // Remember the old values, and insert the new ones
4612    for ( var name in options ) {
4613      old[ name ] = elem.style[ name ];
4614      elem.style[ name ] = options[ name ];
4615    }
4616
4617    callback.call( elem );
4618
4619    // Revert the old values
4620    for ( var name in options ) {
4621      elem.style[ name ] = old[ name ];
4622    }
4623  }
4624});
4625
4626if ( jQuery.expr && jQuery.expr.filters ) {
4627  jQuery.expr.filters.hidden = function( elem ) {
4628    var width = elem.offsetWidth, height = elem.offsetHeight,
4629      skip = elem.nodeName.toLowerCase() === "tr";
4630
4631    return width === 0 && height === 0 && !skip ?
4632      true :
4633      width > 0 && height > 0 && !skip ?
4634        false :
4635        jQuery.curCSS(elem, "display") === "none";
4636  };
4637
4638  jQuery.expr.filters.visible = function( elem ) {
4639    return !jQuery.expr.filters.hidden( elem );
4640  };
4641}
4642var jsc = now(),
4643  rscript = /<script(.|\s)*?\/script>/gi,
4644  rselectTextarea = /select|textarea/i,
4645  rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
4646  jsre = /=\?(&|$)/,
4647  rquery = /\?/,
4648  rts = /(\?|&)_=.*?(&|$)/,
4649  rurl = /^(\w+:)?\/\/([^\/?#]+)/,
4650  r20 = /%20/g;
4651
4652jQuery.fn.extend({
4653  // Keep a copy of the old load
4654  _load: jQuery.fn.load,
4655
4656  load: function( url, params, callback ) {
4657    if ( typeof url !== "string" ) {
4658      return this._load( url );
4659
4660    // Don't do a request if no elements are being requested
4661    } else if ( !this.length ) {
4662      return this;
4663    }
4664
4665    var off = url.indexOf(" ");
4666    if ( off >= 0 ) {
4667      var selector = url.slice(off, url.length);
4668      url = url.slice(0, off);
4669    }
4670
4671    // Default to a GET request
4672    var type = "GET";
4673
4674    // If the second parameter was provided
4675    if ( params ) {
4676      // If it's a function
4677      if ( jQuery.isFunction( params ) ) {
4678        // We assume that it's the callback
4679        callback = params;
4680        params = null;
4681
4682      // Otherwise, build a param string
4683      } else if ( typeof params === "object" ) {
4684        params = jQuery.param( params, jQuery.ajaxSettings.traditional );
4685        type = "POST";
4686      }
4687    }
4688
4689    var self = this;
4690
4691    // Request the remote document
4692    jQuery.ajax({
4693      url: url,
4694      type: type,
4695      dataType: "html",
4696      data: params,
4697      complete: function( res, status ) {
4698        // If successful, inject the HTML into all the matched elements
4699        if ( status === "success" || status === "notmodified" ) {
4700          // See if a selector was specified
4701          self.html( selector ?
4702            // Create a dummy div to hold the results
4703            jQuery("<div />")
4704              // inject the contents of the document in, removing the scripts
4705              // to avoid any 'Permission Denied' errors in IE
4706              .append(res.responseText.replace(rscript, ""))
4707
4708              // Locate the specified elements
4709              .find(selector) :
4710
4711            // If not, just inject the full result
4712            res.responseText );
4713        }
4714
4715        if ( callback ) {
4716          self.each( callback, [res.responseText, status, res] );
4717        }
4718      }
4719    });
4720
4721    return this;
4722  },
4723
4724  serialize: function() {
4725    return jQuery.param(this.serializeArray());
4726  },
4727  serializeArray: function() {
4728    return this.map(function() {
4729      return this.elements ? jQuery.makeArray(this.elements) : this;
4730    })
4731    .filter(function() {
4732      return this.name && !this.disabled &&
4733        (this.checked || rselectTextarea.test(this.nodeName) ||
4734          rinput.test(this.type));
4735    })
4736    .map(function( i, elem ) {
4737      var val = jQuery(this).val();
4738
4739      return val == null ?
4740        null :
4741        jQuery.isArray(val) ?
4742          jQuery.map( val, function( val, i ) {
4743            return { name: elem.name, value: val };
4744          }) :
4745          { name: elem.name, value: val };
4746    }).get();
4747  }
4748});
4749
4750// Attach a bunch of functions for handling common AJAX events
4751jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
4752  jQuery.fn[o] = function( f ) {
4753    return this.bind(o, f);
4754  };
4755});
4756
4757jQuery.extend({
4758
4759  get: function( url, data, callback, type ) {
4760    // shift arguments if data argument was omited
4761    if ( jQuery.isFunction( data ) ) {
4762      type = type || callback;
4763      callback = data;
4764      data = null;
4765    }
4766
4767    return jQuery.ajax({
4768      type: "GET",
4769      url: url,
4770      data: data,
4771      success: callback,
4772      dataType: type
4773    });
4774  },
4775
4776  getScript: function( url, callback ) {
4777    return jQuery.get(url, null, callback, "script");
4778  },
4779
4780  getJSON: function( url, data, callback ) {
4781    return jQuery.get(url, data, callback, "json");
4782  },
4783
4784  post: function( url, data, callback, type ) {
4785    // shift arguments if data argument was omited
4786    if ( jQuery.isFunction( data ) ) {
4787      type = type || callback;
4788      callback = data;
4789      data = {};
4790    }
4791
4792    return jQuery.ajax({
4793      type: "POST",
4794      url: url,
4795      data: data,
4796      success: callback,
4797      dataType: type
4798    });
4799  },
4800
4801  ajaxSetup: function( settings ) {
4802    jQuery.extend( jQuery.ajaxSettings, settings );
4803  },
4804
4805  ajaxSettings: {
4806    url: location.href,
4807    global: true,
4808    type: "GET",
4809    contentType: "application/x-www-form-urlencoded",
4810    processData: true,
4811    async: true,
4812    /*
4813    timeout: 0,
4814    data: null,
4815    username: null,
4816    password: null,
4817    traditional: false,
4818    */
4819    // Create the request object; Microsoft failed to properly
4820    // implement the XMLHttpRequest in IE7 (can't request local files),
4821    // so we use the ActiveXObject when it is available
4822    // This function can be overriden by calling jQuery.ajaxSetup
4823    xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
4824      function() {
4825        return new window.XMLHttpRequest();
4826      } :
4827      function() {
4828        try {
4829          return new window.ActiveXObject("Microsoft.XMLHTTP");
4830        } catch(e) {}
4831      },
4832    accepts: {
4833      xml: "application/xml, text/xml",
4834      html: "text/html",
4835      script: "text/javascript, application/javascript",
4836      json: "application/json, text/javascript",
4837      text: "text/plain",
4838      _default: "*/*"
4839    }
4840  },
4841
4842  // Last-Modified header cache for next request
4843  lastModified: {},
4844  etag: {},
4845
4846  ajax: function( origSettings ) {
4847    var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
4848   
4849    var jsonp, status, data,
4850      callbackContext = origSettings && origSettings.context || s,
4851      type = s.type.toUpperCase();
4852
4853    // convert data if not already a string
4854    if ( s.data && s.processData && typeof s.data !== "string" ) {
4855      s.data = jQuery.param( s.data, s.traditional );
4856    }
4857
4858    // Handle JSONP Parameter Callbacks
4859    if ( s.dataType === "jsonp" ) {
4860      if ( type === "GET" ) {
4861        if ( !jsre.test( s.url ) ) {
4862          s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
4863        }
4864      } else if ( !s.data || !jsre.test(s.data) ) {
4865        s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
4866      }
4867      s.dataType = "json";
4868    }
4869
4870    // Build temporary JSONP function
4871    if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
4872      jsonp = s.jsonpCallback || ("jsonp" + jsc++);
4873
4874      // Replace the =? sequence both in the query string and the data
4875      if ( s.data ) {
4876        s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
4877      }
4878
4879      s.url = s.url.replace(jsre, "=" + jsonp + "$1");
4880
4881      // We need to make sure
4882      // that a JSONP style response is executed properly
4883      s.dataType = "script";
4884
4885      // Handle JSONP-style loading
4886      window[ jsonp ] = window[ jsonp ] || function( tmp ) {
4887        data = tmp;
4888        success();
4889        complete();
4890        // Garbage collect
4891        window[ jsonp ] = undefined;
4892
4893        try {
4894          delete window[ jsonp ];
4895        } catch(e) {}
4896
4897        if ( head ) {
4898          head.removeChild( script );
4899        }
4900      };
4901    }
4902
4903    if ( s.dataType === "script" && s.cache === null ) {
4904      s.cache = false;
4905    }
4906
4907    if ( s.cache === false && type === "GET" ) {
4908      var ts = now();
4909
4910      // try replacing _= if it is there
4911      var ret = s.url.replace(rts, "$1_=" + ts + "$2");
4912
4913      // if nothing was replaced, add timestamp to the end
4914      s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
4915    }
4916
4917    // If data is available, append data to url for get requests
4918    if ( s.data && type === "GET" ) {
4919      s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
4920    }
4921
4922    // Watch for a new set of requests
4923    if ( s.global && ! jQuery.active++ ) {
4924      jQuery.event.trigger( "ajaxStart" );
4925    }
4926
4927    // Matches an absolute URL, and saves the domain
4928    var parts = rurl.exec( s.url ),
4929      remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
4930
4931    // If we're requesting a remote document
4932    // and trying to load JSON or Script with a GET
4933    if ( s.dataType === "script" && type === "GET" && remote ) {
4934      var head = document.getElementsByTagName("head")[0] || document.documentElement;
4935      var script = document.createElement("script");
4936      script.src = s.url;
4937      if ( s.scriptCharset ) {
4938        script.charset = s.scriptCharset;
4939      }
4940
4941      // Handle Script loading
4942      if ( !jsonp ) {
4943        var done = false;
4944
4945        // Attach handlers for all browsers
4946        script.onload = script.onreadystatechange = function() {
4947          if ( !done && (!this.readyState ||
4948              this.readyState === "loaded" || this.readyState === "complete") ) {
4949            done = true;
4950            success();
4951            complete();
4952
4953            // Handle memory leak in IE
4954            script.onload = script.onreadystatechange = null;
4955            if ( head && script.parentNode ) {
4956              head.removeChild( script );
4957            }
4958          }
4959        };
4960      }
4961
4962      // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
4963      // This arises when a base node is used (#2709 and #4378).
4964      head.insertBefore( script, head.firstChild );
4965
4966      // We handle everything using the script element injection
4967      return undefined;
4968    }
4969
4970    var requestDone = false;
4971
4972    // Create the request object
4973    var xhr = s.xhr();
4974
4975    if ( !xhr ) {
4976      return;
4977    }
4978
4979    // Open the socket
4980    // Passing null username, generates a login popup on Opera (#2865)
4981    if ( s.username ) {
4982      xhr.open(type, s.url, s.async, s.username, s.password);
4983    } else {
4984      xhr.open(type, s.url, s.async);
4985    }
4986
4987    // Need an extra try/catch for cross domain requests in Firefox 3
4988    try {
4989      // Set the correct header, if data is being sent
4990      if ( s.data || origSettings && origSettings.contentType ) {
4991        xhr.setRequestHeader("Content-Type", s.contentType);
4992      }
4993
4994      // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
4995      if ( s.ifModified ) {
4996        if ( jQuery.lastModified[s.url] ) {
4997          xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
4998        }
4999
5000        if ( jQuery.etag[s.url] ) {
5001          xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
5002        }
5003      }
5004
5005      // Set header so the called script knows that it's an XMLHttpRequest
5006      // Only send the header if it's not a remote XHR
5007      if ( !remote ) {
5008        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
5009      }
5010
5011      // Set the Accepts header for the server, depending on the dataType
5012      xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
5013        s.accepts[ s.dataType ] + ", */*" :
5014        s.accepts._default );
5015    } catch(e) {}
5016
5017    // Allow custom headers/mimetypes and early abort
5018    if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
5019      // Handle the global AJAX counter
5020      if ( s.global && ! --jQuery.active ) {
5021        jQuery.event.trigger( "ajaxStop" );
5022      }
5023
5024      // close opended socket
5025      xhr.abort();
5026      return false;
5027    }
5028
5029    if ( s.global ) {
5030      trigger("ajaxSend", [xhr, s]);
5031    }
5032
5033    // Wait for a response to come back
5034    var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
5035      // The request was aborted
5036      if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
5037        // Opera doesn't call onreadystatechange before this point
5038        // so we simulate the call
5039        if ( !requestDone ) {
5040          complete();
5041        }
5042
5043        requestDone = true;
5044        if ( xhr ) {
5045          xhr.onreadystatechange = jQuery.noop;
5046        }
5047
5048      // The transfer is complete and the data is available, or the request timed out
5049      } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
5050        requestDone = true;
5051        xhr.onreadystatechange = jQuery.noop;
5052
5053        status = isTimeout === "timeout" ?
5054          "timeout" :
5055          !jQuery.httpSuccess( xhr ) ?
5056            "error" :
5057            s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
5058              "notmodified" :
5059              "success";
5060
5061        var errMsg;
5062
5063        if ( status === "success" ) {
5064          // Watch for, and catch, XML document parse errors
5065          try {
5066            // process the data (runs the xml through httpData regardless of callback)
5067            data = jQuery.httpData( xhr, s.dataType, s );
5068          } catch(err) {
5069            status = "parsererror";
5070            errMsg = err;
5071          }
5072        }
5073
5074        // Make sure that the request was successful or notmodified
5075        if ( status === "success" || status === "notmodified" ) {
5076          // JSONP handles its own success callback
5077          if ( !jsonp ) {
5078            success();
5079          }
5080        } else {
5081          jQuery.handleError(s, xhr, status, errMsg);
5082        }
5083
5084        // Fire the complete handlers
5085        complete();
5086
5087        if ( isTimeout === "timeout" ) {
5088          xhr.abort();
5089        }
5090
5091        // Stop memory leaks
5092        if ( s.async ) {
5093          xhr = null;
5094        }
5095      }
5096    };
5097
5098    // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
5099    // Opera doesn't fire onreadystatechange at all on abort
5100    try {
5101      var oldAbort = xhr.abort;
5102      xhr.abort = function() {
5103        if ( xhr ) {
5104          oldAbort.call( xhr );
5105        }
5106
5107        onreadystatechange( "abort" );
5108      };
5109    } catch(e) { }
5110
5111    // Timeout checker
5112    if ( s.async && s.timeout > 0 ) {
5113      setTimeout(function() {
5114        // Check to see if the request is still happening
5115        if ( xhr && !requestDone ) {
5116          onreadystatechange( "timeout" );
5117        }
5118      }, s.timeout);
5119    }
5120
5121    // Send the data
5122    try {
5123      xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
5124    } catch(e) {
5125      jQuery.handleError(s, xhr, null, e);
5126      // Fire the complete handlers
5127      complete();
5128    }
5129
5130    // firefox 1.5 doesn't fire statechange for sync requests
5131    if ( !s.async ) {
5132      onreadystatechange();
5133    }
5134
5135    function success() {
5136      // If a local callback was specified, fire it and pass it the data
5137      if ( s.success ) {
5138        s.success.call( callbackContext, data, status, xhr );
5139      }
5140
5141      // Fire the global callback
5142      if ( s.global ) {
5143        trigger( "ajaxSuccess", [xhr, s] );
5144      }
5145    }
5146
5147    function complete() {
5148      // Process result
5149      if ( s.complete ) {
5150        s.complete.call( callbackContext, xhr, status);
5151      }
5152
5153      // The request was completed
5154      if ( s.global ) {
5155        trigger( "ajaxComplete", [xhr, s] );
5156      }
5157
5158      // Handle the global AJAX counter
5159      if ( s.global && ! --jQuery.active ) {
5160        jQuery.event.trigger( "ajaxStop" );
5161      }
5162    }
5163   
5164    function trigger(type, args) {
5165      (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
5166    }
5167
5168    // return XMLHttpRequest to allow aborting the request etc.
5169    return xhr;
5170  },
5171
5172  handleError: function( s, xhr, status, e ) {
5173    // If a local callback was specified, fire it
5174    if ( s.error ) {
5175      s.error.call( s.context || s, xhr, status, e );
5176    }
5177
5178    // Fire the global callback
5179    if ( s.global ) {
5180      (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
5181    }
5182  },
5183
5184  // Counter for holding the number of active queries
5185  active: 0,
5186
5187  // Determines if an XMLHttpRequest was successful or not
5188  httpSuccess: function( xhr ) {
5189    try {
5190      // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
5191      return !xhr.status && location.protocol === "file:" ||
5192        // Opera returns 0 when status is 304
5193        ( xhr.status >= 200 && xhr.status < 300 ) ||
5194        xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
5195    } catch(e) {}
5196
5197    return false;
5198  },
5199
5200  // Determines if an XMLHttpRequest returns NotModified
5201  httpNotModified: function( xhr, url ) {
5202    var lastModified = xhr.getResponseHeader("Last-Modified"),
5203      etag = xhr.getResponseHeader("Etag");
5204
5205    if ( lastModified ) {
5206      jQuery.lastModified[url] = lastModified;
5207    }
5208
5209    if ( etag ) {
5210      jQuery.etag[url] = etag;
5211    }
5212
5213    // Opera returns 0 when status is 304
5214    return xhr.status === 304 || xhr.status === 0;
5215  },
5216
5217  httpData: function( xhr, type, s ) {
5218    var ct = xhr.getResponseHeader("content-type") || "",
5219      xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
5220      data = xml ? xhr.responseXML : xhr.responseText;
5221
5222    if ( xml && data.documentElement.nodeName === "parsererror" ) {
5223      jQuery.error( "parsererror" );
5224    }
5225
5226    // Allow a pre-filtering function to sanitize the response
5227    // s is checked to keep backwards compatibility
5228    if ( s && s.dataFilter ) {
5229      data = s.dataFilter( data, type );
5230    }
5231
5232    // The filter can actually parse the response
5233    if ( typeof data === "string" ) {
5234      // Get the JavaScript object, if JSON is used.
5235      if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
5236        data = jQuery.parseJSON( data );
5237
5238      // If the type is "script", eval it in global context
5239      } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
5240        jQuery.globalEval( data );
5241      }
5242    }
5243
5244    return data;
5245  },
5246
5247  // Serialize an array of form elements or a set of
5248  // key/values into a query string
5249  param: function( a, traditional ) {
5250    var s = [];
5251   
5252    // Set traditional to true for jQuery <= 1.3.2 behavior.
5253    if ( traditional === undefined ) {
5254      traditional = jQuery.ajaxSettings.traditional;
5255    }
5256   
5257    // If an array was passed in, assume that it is an array of form elements.
5258    if ( jQuery.isArray(a) || a.jquery ) {
5259      // Serialize the form elements
5260      jQuery.each( a, function() {
5261        add( this.name, this.value );
5262      });
5263     
5264    } else {
5265      // If traditional, encode the "old" way (the way 1.3.2 or older
5266      // did it), otherwise encode params recursively.
5267      for ( var prefix in a ) {
5268        buildParams( prefix, a[prefix] );
5269      }
5270    }
5271
5272    // Return the resulting serialization
5273    return s.join("&").replace(r20, "+");
5274
5275    function buildParams( prefix, obj ) {
5276      if ( jQuery.isArray(obj) ) {
5277        // Serialize array item.
5278        jQuery.each( obj, function( i, v ) {
5279          if ( traditional ) {
5280            // Treat each array item as a scalar.
5281            add( prefix, v );
5282          } else {
5283            // If array item is non-scalar (array or object), encode its
5284            // numeric index to resolve deserialization ambiguity issues.
5285            // Note that rack (as of 1.0.0) can't currently deserialize
5286            // nested arrays properly, and attempting to do so may cause
5287            // a server error. Possible fixes are to modify rack's
5288            // deserialization algorithm or to provide an option or flag
5289            // to force array serialization to be shallow.
5290            buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
5291          }
5292        });
5293         
5294      } else if ( !traditional && obj != null && typeof obj === "object" ) {
5295        // Serialize object item.
5296        jQuery.each( obj, function( k, v ) {
5297          buildParams( prefix + "[" + k + "]", v );
5298        });
5299         
5300      } else {
5301        // Serialize scalar item.
5302        add( prefix, obj );
5303      }
5304    }
5305
5306    function add( key, value ) {
5307      // If value is a function, invoke it and return its value
5308      value = jQuery.isFunction(value) ? value() : value;
5309      s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
5310    }
5311  }
5312});
5313var elemdisplay = {},
5314  rfxtypes = /toggle|show|hide/,
5315  rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
5316  timerId,
5317  fxAttrs = [
5318    // height animations
5319    [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
5320    // width animations
5321    [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
5322    // opacity animations
5323    [ "opacity" ]
5324  ];
5325
5326jQuery.fn.extend({
5327  show: function( speed, callback ) {
5328    if ( speed || speed === 0) {
5329      return this.animate( genFx("show", 3), speed, callback);
5330
5331    } else {
5332      for ( var i = 0, l = this.length; i < l; i++ ) {
5333        var old = jQuery.data(this[i], "olddisplay");
5334
5335        this[i].style.display = old || "";
5336
5337        if ( jQuery.css(this[i], "display") === "none" ) {
5338          var nodeName = this[i].nodeName, display;
5339
5340          if ( elemdisplay[ nodeName ] ) {
5341            display = elemdisplay[ nodeName ];
5342
5343          } else {
5344            var elem = jQuery("<" + nodeName + " />").appendTo("body");
5345
5346            display = elem.css("display");
5347
5348            if ( display === "none" ) {
5349              display = "block";
5350            }
5351
5352            elem.remove();
5353
5354            elemdisplay[ nodeName ] = display;
5355          }
5356
5357          jQuery.data(this[i], "olddisplay", display);
5358        }
5359      }
5360
5361      // Set the display of the elements in a second loop
5362      // to avoid the constant reflow
5363      for ( var j = 0, k = this.length; j < k; j++ ) {
5364        this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
5365      }
5366
5367      return this;
5368    }
5369  },
5370
5371  hide: function( speed, callback ) {
5372    if ( speed || speed === 0 ) {
5373      return this.animate( genFx("hide", 3), speed, callback);
5374
5375    } else {
5376      for ( var i = 0, l = this.length; i < l; i++ ) {
5377        var old = jQuery.data(this[i], "olddisplay");
5378        if ( !old && old !== "none" ) {
5379          jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
5380        }
5381      }
5382
5383      // Set the display of the elements in a second loop
5384      // to avoid the constant reflow
5385      for ( var j = 0, k = this.length; j < k; j++ ) {
5386        this[j].style.display = "none";
5387      }
5388
5389      return this;
5390    }
5391  },
5392
5393  // Save the old toggle function
5394  _toggle: jQuery.fn.toggle,
5395
5396  toggle: function( fn, fn2 ) {
5397    var bool = typeof fn === "boolean";
5398
5399    if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
5400      this._toggle.apply( this, arguments );
5401
5402    } else if ( fn == null || bool ) {
5403      this.each(function() {
5404        var state = bool ? fn : jQuery(this).is(":hidden");
5405        jQuery(this)[ state ? "show" : "hide" ]();
5406      });
5407
5408    } else {
5409      this.animate(genFx("toggle", 3), fn, fn2);
5410    }
5411
5412    return this;
5413  },
5414
5415  fadeTo: function( speed, to, callback ) {
5416    return this.filter(":hidden").css("opacity", 0).show().end()
5417          .animate({opacity: to}, speed, callback);
5418  },
5419
5420  animate: function( prop, speed, easing, callback ) {
5421    var optall = jQuery.speed(speed, easing, callback);
5422
5423    if ( jQuery.isEmptyObject( prop ) ) {
5424      return this.each( optall.complete );
5425    }
5426
5427    return this[ optall.queue === false ? "each" : "queue" ](function() {
5428      var opt = jQuery.extend({}, optall), p,
5429        hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
5430        self = this;
5431
5432      for ( p in prop ) {
5433        var name = p.replace(rdashAlpha, fcamelCase);
5434
5435        if ( p !== name ) {
5436          prop[ name ] = prop[ p ];
5437          delete prop[ p ];
5438          p = name;
5439        }
5440
5441        if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
5442          return opt.complete.call(this);
5443        }
5444
5445        if ( ( p === "height" || p === "width" ) && this.style ) {
5446          // Store display property
5447          opt.display = jQuery.css(this, "display");
5448
5449          // Make sure that nothing sneaks out
5450          opt.overflow = this.style.overflow;
5451        }
5452
5453        if ( jQuery.isArray( prop[p] ) ) {
5454          // Create (if needed) and add to specialEasing
5455          (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
5456          prop[p] = prop[p][0];
5457        }
5458      }
5459
5460      if ( opt.overflow != null ) {
5461        this.style.overflow = "hidden";
5462      }
5463
5464      opt.curAnim = jQuery.extend({}, prop);
5465
5466      jQuery.each( prop, function( name, val ) {
5467        var e = new jQuery.fx( self, opt, name );
5468
5469        if ( rfxtypes.test(val) ) {
5470          e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
5471
5472        } else {
5473          var parts = rfxnum.exec(val),
5474            start = e.cur(true) || 0;
5475
5476          if ( parts ) {
5477            var end = parseFloat( parts[2] ),
5478              unit = parts[3] || "px";
5479
5480            // We need to compute starting value
5481            if ( unit !== "px" ) {
5482              self.style[ name ] = (end || 1) + unit;
5483              start = ((end || 1) / e.cur(true)) * start;
5484              self.style[ name ] = start + unit;
5485            }
5486
5487            // If a +=/-= token was provided, we're doing a relative animation
5488            if ( parts[1] ) {
5489              end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
5490            }
5491
5492            e.custom( start, end, unit );
5493
5494          } else {
5495            e.custom( start, val, "" );
5496          }
5497        }
5498      });
5499
5500      // For JS strict compliance
5501      return true;
5502    });
5503  },
5504
5505  stop: function( clearQueue, gotoEnd ) {
5506    var timers = jQuery.timers;
5507
5508    if ( clearQueue ) {
5509      this.queue([]);
5510    }
5511
5512    this.each(function() {
5513      // go in reverse order so anything added to the queue during the loop is ignored
5514      for ( var i = timers.length - 1; i >= 0; i-- ) {
5515        if ( timers[i].elem === this ) {
5516          if (gotoEnd) {
5517            // force the next step to be the last
5518            timers[i](true);
5519          }
5520
5521          timers.splice(i, 1);
5522        }
5523      }
5524    });
5525
5526    // start the next in the queue if the last step wasn't forced
5527    if ( !gotoEnd ) {
5528      this.dequeue();
5529    }
5530
5531    return this;
5532  }
5533
5534});
5535
5536// Generate shortcuts for custom animations
5537jQuery.each({
5538  slideDown: genFx("show", 1),
5539  slideUp: genFx("hide", 1),
5540  slideToggle: genFx("toggle", 1),
5541  fadeIn: { opacity: "show" },
5542  fadeOut: { opacity: "hide" }
5543}, function( name, props ) {
5544  jQuery.fn[ name ] = function( speed, callback ) {
5545    return this.animate( props, speed, callback );
5546  };
5547});
5548
5549jQuery.extend({
5550  speed: function( speed, easing, fn ) {
5551    var opt = speed && typeof speed === "object" ? speed : {
5552      complete: fn || !fn && easing ||
5553        jQuery.isFunction( speed ) && speed,
5554      duration: speed,
5555      easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
5556    };
5557
5558    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
5559      jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
5560
5561    // Queueing
5562    opt.old = opt.complete;
5563    opt.complete = function() {
5564      if ( opt.queue !== false ) {
5565        jQuery(this).dequeue();
5566      }
5567      if ( jQuery.isFunction( opt.old ) ) {
5568        opt.old.call( this );
5569      }
5570    };
5571
5572    return opt;
5573  },
5574
5575  easing: {
5576    linear: function( p, n, firstNum, diff ) {
5577      return firstNum + diff * p;
5578    },
5579    swing: function( p, n, firstNum, diff ) {
5580      return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
5581    }
5582  },
5583
5584  timers: [],
5585
5586  fx: function( elem, options, prop ) {
5587    this.options = options;
5588    this.elem = elem;
5589    this.prop = prop;
5590
5591    if ( !options.orig ) {
5592      options.orig = {};
5593    }
5594  }
5595
5596});
5597
5598jQuery.fx.prototype = {
5599  // Simple function for setting a style value
5600  update: function() {
5601    if ( this.options.step ) {
5602      this.options.step.call( this.elem, this.now, this );
5603    }
5604
5605    (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
5606
5607    // Set display property to block for height/width animations
5608    if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
5609      this.elem.style.display = "block";
5610    }
5611  },
5612
5613  // Get the current size
5614  cur: function( force ) {
5615    if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
5616      return this.elem[ this.prop ];
5617    }
5618
5619    var r = parseFloat(jQuery.css(this.elem, this.prop, force));
5620    return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
5621  },
5622
5623  // Start an animation from one number to another
5624  custom: function( from, to, unit ) {
5625    this.startTime = now();
5626    this.start = from;
5627    this.end = to;
5628    this.unit = unit || this.unit || "px";
5629    this.now = this.start;
5630    this.pos = this.state = 0;
5631
5632    var self = this;
5633    function t( gotoEnd ) {
5634      return self.step(gotoEnd);
5635    }
5636
5637    t.elem = this.elem;
5638
5639    if ( t() && jQuery.timers.push(t) && !timerId ) {
5640      timerId = setInterval(jQuery.fx.tick, 13);
5641    }
5642  },
5643
5644  // Simple 'show' function
5645  show: function() {
5646    // Remember where we started, so that we can go back to it later
5647    this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5648    this.options.show = true;
5649
5650    // Begin the animation
5651    // Make sure that we start at a small width/height to avoid any
5652    // flash of content
5653    this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
5654
5655    // Start by showing the element
5656    jQuery( this.elem ).show();
5657  },
5658
5659  // Simple 'hide' function
5660  hide: function() {
5661    // Remember where we started, so that we can go back to it later
5662    this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5663    this.options.hide = true;
5664
5665    // Begin the animation
5666    this.custom(this.cur(), 0);
5667  },
5668
5669  // Each step of an animation
5670  step: function( gotoEnd ) {
5671    var t = now(), done = true;
5672
5673    if ( gotoEnd || t >= this.options.duration + this.startTime ) {
5674      this.now = this.end;
5675      this.pos = this.state = 1;
5676      this.update();
5677
5678      this.options.curAnim[ this.prop ] = true;
5679
5680      for ( var i in this.options.curAnim ) {
5681        if ( this.options.curAnim[i] !== true ) {
5682          done = false;
5683        }
5684      }
5685
5686      if ( done ) {
5687        if ( this.options.display != null ) {
5688          // Reset the overflow
5689          this.elem.style.overflow = this.options.overflow;
5690
5691          // Reset the display
5692          var old = jQuery.data(this.elem, "olddisplay");
5693          this.elem.style.display = old ? old : this.options.display;
5694
5695          if ( jQuery.css(this.elem, "display") === "none" ) {
5696            this.elem.style.display = "block";
5697          }
5698        }
5699
5700        // Hide the element if the "hide" operation was done
5701        if ( this.options.hide ) {
5702          jQuery(this.elem).hide();
5703        }
5704
5705        // Reset the properties, if the item has been hidden or shown
5706        if ( this.options.hide || this.options.show ) {
5707          for ( var p in this.options.curAnim ) {
5708            jQuery.style(this.elem, p, this.options.orig[p]);
5709          }
5710        }
5711
5712        // Execute the complete function
5713        this.options.complete.call( this.elem );
5714      }
5715
5716      return false;
5717
5718    } else {
5719      var n = t - this.startTime;
5720      this.state = n / this.options.duration;
5721
5722      // Perform the easing function, defaults to swing
5723      var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
5724      var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
5725      this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
5726      this.now = this.start + ((this.end - this.start) * this.pos);
5727
5728      // Perform the next step of the animation
5729      this.update();
5730    }
5731
5732    return true;
5733  }
5734};
5735
5736jQuery.extend( jQuery.fx, {
5737  tick: function() {
5738    var timers = jQuery.timers;
5739
5740    for ( var i = 0; i < timers.length; i++ ) {
5741      if ( !timers[i]() ) {
5742        timers.splice(i--, 1);
5743      }
5744    }
5745
5746    if ( !timers.length ) {
5747      jQuery.fx.stop();
5748    }
5749  },
5750   
5751  stop: function() {
5752    clearInterval( timerId );
5753    timerId = null;
5754  },
5755 
5756  speeds: {
5757    slow: 600,
5758    fast: 200,
5759    // Default speed
5760    _default: 400
5761  },
5762
5763  step: {
5764    opacity: function( fx ) {
5765      jQuery.style(fx.elem, "opacity", fx.now);
5766    },
5767
5768    _default: function( fx ) {
5769      if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
5770        fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
5771      } else {
5772        fx.elem[ fx.prop ] = fx.now;
5773      }
5774    }
5775  }
5776});
5777
5778if ( jQuery.expr && jQuery.expr.filters ) {
5779  jQuery.expr.filters.animated = function( elem ) {
5780    return jQuery.grep(jQuery.timers, function( fn ) {
5781      return elem === fn.elem;
5782    }).length;
5783  };
5784}
5785
5786function genFx( type, num ) {
5787  var obj = {};
5788
5789  jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
5790    obj[ this ] = type;
5791  });
5792
5793  return obj;
5794}
5795if ( "getBoundingClientRect" in document.documentElement ) {
5796  jQuery.fn.offset = function( options ) {
5797    var elem = this[0];
5798
5799    if ( options ) {
5800      return this.each(function( i ) {
5801        jQuery.offset.setOffset( this, options, i );
5802      });
5803    }
5804
5805    if ( !elem || !elem.ownerDocument ) {
5806      return null;
5807    }
5808
5809    if ( elem === elem.ownerDocument.body ) {
5810      return jQuery.offset.bodyOffset( elem );
5811    }
5812
5813    var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
5814      clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
5815      top  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
5816      left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
5817
5818    return { top: top, left: left };
5819  };
5820
5821} else {
5822  jQuery.fn.offset = function( options ) {
5823    var elem = this[0];
5824
5825    if ( options ) {
5826      return this.each(function( i ) {
5827        jQuery.offset.setOffset( this, options, i );
5828      });
5829    }
5830
5831    if ( !elem || !elem.ownerDocument ) {
5832      return null;
5833    }
5834
5835    if ( elem === elem.ownerDocument.body ) {
5836      return jQuery.offset.bodyOffset( elem );
5837    }
5838
5839    jQuery.offset.initialize();
5840
5841    var offsetParent = elem.offsetParent, prevOffsetParent = elem,
5842      doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
5843      body = doc.body, defaultView = doc.defaultView,
5844      prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
5845      top = elem.offsetTop, left = elem.offsetLeft;
5846
5847    while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
5848      if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
5849        break;
5850      }
5851
5852      computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
5853      top  -= elem.scrollTop;
5854      left -= elem.scrollLeft;
5855
5856      if ( elem === offsetParent ) {
5857        top  += elem.offsetTop;
5858        left += elem.offsetLeft;
5859
5860        if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
5861          top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
5862          left += parseFloat( computedStyle.borderLeftWidth ) || 0;
5863        }
5864
5865        prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
5866      }
5867
5868      if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
5869        top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
5870        left += parseFloat( computedStyle.borderLeftWidth ) || 0;
5871      }
5872
5873      prevComputedStyle = computedStyle;
5874    }
5875
5876    if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
5877      top  += body.offsetTop;
5878      left += body.offsetLeft;
5879    }
5880
5881    if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
5882      top  += Math.max( docElem.scrollTop, body.scrollTop );
5883      left += Math.max( docElem.scrollLeft, body.scrollLeft );
5884    }
5885
5886    return { top: top, left: left };
5887  };
5888}
5889
5890jQuery.offset = {
5891  initialize: function() {
5892    var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
5893      html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
5894
5895    jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
5896
5897    container.innerHTML = html;
5898    body.insertBefore( container, body.firstChild );
5899    innerDiv = container.firstChild;
5900    checkDiv = innerDiv.firstChild;
5901    td = innerDiv.nextSibling.firstChild.firstChild;
5902
5903    this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
5904    this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
5905
5906    checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
5907    // safari subtracts parent border width here which is 5px
5908    this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
5909    checkDiv.style.position = checkDiv.style.top = "";
5910
5911    innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
5912    this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
5913
5914    this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
5915
5916    body.removeChild( container );
5917    body = container = innerDiv = checkDiv = table = td = null;
5918    jQuery.offset.initialize = jQuery.noop;
5919  },
5920
5921  bodyOffset: function( body ) {
5922    var top = body.offsetTop, left = body.offsetLeft;
5923
5924    jQuery.offset.initialize();
5925
5926    if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
5927      top  += parseFloat( jQuery.curCSS(body, "marginTop",  true) ) || 0;
5928      left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
5929    }
5930
5931    return { top: top, left: left };
5932  },
5933 
5934  setOffset: function( elem, options, i ) {
5935    // set position first, in-case top/left are set even on static elem
5936    if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
5937      elem.style.position = "relative";
5938    }
5939    var curElem   = jQuery( elem ),
5940      curOffset = curElem.offset(),
5941      curTop    = parseInt( jQuery.curCSS( elem, "top",  true ), 10 ) || 0,
5942      curLeft   = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
5943
5944    if ( jQuery.isFunction( options ) ) {
5945      options = options.call( elem, i, curOffset );
5946    }
5947
5948    var props = {
5949      top:  (options.top  - curOffset.top)  + curTop,
5950      left: (options.left - curOffset.left) + curLeft
5951    };
5952   
5953    if ( "using" in options ) {
5954      options.using.call( elem, props );
5955    } else {
5956      curElem.css( props );
5957    }
5958  }
5959};
5960
5961
5962jQuery.fn.extend({
5963  position: function() {
5964    if ( !this[0] ) {
5965      return null;
5966    }
5967
5968    var elem = this[0],
5969
5970    // Get *real* offsetParent
5971    offsetParent = this.offsetParent(),
5972
5973    // Get correct offsets
5974    offset       = this.offset(),
5975    parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
5976
5977    // Subtract element margins
5978    // note: when an element has margin: auto the offsetLeft and marginLeft
5979    // are the same in Safari causing offset.left to incorrectly be 0
5980    offset.top  -= parseFloat( jQuery.curCSS(elem, "marginTop",  true) ) || 0;
5981    offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
5982
5983    // Add offsetParent borders
5984    parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth",  true) ) || 0;
5985    parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
5986
5987    // Subtract the two offsets
5988    return {
5989      top:  offset.top  - parentOffset.top,
5990      left: offset.left - parentOffset.left
5991    };
5992  },
5993
5994  offsetParent: function() {
5995    return this.map(function() {
5996      var offsetParent = this.offsetParent || document.body;
5997      while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
5998        offsetParent = offsetParent.offsetParent;
5999      }
6000      return offsetParent;
6001    });
6002  }
6003});
6004
6005
6006// Create scrollLeft and scrollTop methods
6007jQuery.each( ["Left", "Top"], function( i, name ) {
6008  var method = "scroll" + name;
6009
6010  jQuery.fn[ method ] = function(val) {
6011    var elem = this[0], win;
6012   
6013    if ( !elem ) {
6014      return null;
6015    }
6016
6017    if ( val !== undefined ) {
6018      // Set the scroll offset
6019      return this.each(function() {
6020        win = getWindow( this );
6021
6022        if ( win ) {
6023          win.scrollTo(
6024            !i ? val : jQuery(win).scrollLeft(),
6025             i ? val : jQuery(win).scrollTop()
6026          );
6027
6028        } else {
6029          this[ method ] = val;
6030        }
6031      });
6032    } else {
6033      win = getWindow( elem );
6034
6035      // Return the scroll offset
6036      return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
6037        jQuery.support.boxModel && win.document.documentElement[ method ] ||
6038          win.document.body[ method ] :
6039        elem[ method ];
6040    }
6041  };
6042});
6043
6044function getWindow( elem ) {
6045  return ("scrollTo" in elem && elem.document) ?
6046    elem :
6047    elem.nodeType === 9 ?
6048      elem.defaultView || elem.parentWindow :
6049      false;
6050}
6051// Create innerHeight, innerWidth, outerHeight and outerWidth methods
6052jQuery.each([ "Height", "Width" ], function( i, name ) {
6053
6054  var type = name.toLowerCase();
6055
6056  // innerHeight and innerWidth
6057  jQuery.fn["inner" + name] = function() {
6058    return this[0] ?
6059      jQuery.css( this[0], type, false, "padding" ) :
6060      null;
6061  };
6062
6063  // outerHeight and outerWidth
6064  jQuery.fn["outer" + name] = function( margin ) {
6065    return this[0] ?
6066      jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
6067      null;
6068  };
6069
6070  jQuery.fn[ type ] = function( size ) {
6071    // Get window width or height
6072    var elem = this[0];
6073    if ( !elem ) {
6074      return size == null ? null : this;
6075    }
6076   
6077    if ( jQuery.isFunction( size ) ) {
6078      return this.each(function( i ) {
6079        var self = jQuery( this );
6080        self[ type ]( size.call( this, i, self[ type ]() ) );
6081      });
6082    }
6083
6084    return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
6085      // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
6086      elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
6087      elem.document.body[ "client" + name ] :
6088
6089      // Get document width or height
6090      (elem.nodeType === 9) ? // is it a document
6091        // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
6092        Math.max(
6093          elem.documentElement["client" + name],
6094          elem.body["scroll" + name], elem.documentElement["scroll" + name],
6095          elem.body["offset" + name], elem.documentElement["offset" + name]
6096        ) :
6097
6098        // Get or set width or height on the element
6099        size === undefined ?
6100          // Get width or height on the element
6101          jQuery.css( elem, type ) :
6102
6103          // Set the width or height on the element (default to pixels if value is unitless)
6104          this.css( type, typeof size === "string" ? size : size + "px" );
6105  };
6106
6107});
6108// Expose jQuery to the global object
6109window.jQuery = window.$ = jQuery;
6110
6111})(window);
Note: See TracBrowser for help on using the repository browser.