Follow up to r60277: Restore the uploadFormTextTop and uploadFormTextAfterSummary...
[mediawiki.git] / js2 / js2stopgap.js
blob0a72515ba332a29a5f285f0a206501f327b5fd34
1 /*!
2  * jQuery JavaScript Library v1.3.2
3  * http://jquery.com/
4  *
5  * Copyright (c) 2009 John Resig
6  * Dual licensed under the MIT and GPL licenses.
7  * http://docs.jquery.com/License
8  *
9  * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
10  * Revision: 6246
11  */
12 (function(){
14 var 
15         // Will speed up references to window, and allows munging its name.
16         window = this,
17         // Will speed up references to undefined, and allows munging its name.
18         undefined,
19         // Map over jQuery in case of overwrite
20         _jQuery = window.jQuery,
21         // Map over the $ in case of overwrite
22         _$ = window.$,
24         jQuery = window.jQuery = window.$ = function( selector, context ) {
25                 // The jQuery object is actually just the init constructor 'enhanced'
26                 return new jQuery.fn.init( selector, context );
27         },
29         // A simple way to check for HTML strings or ID strings
30         // (both of which we optimize for)
31         quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
32         // Is it a simple selector
33         isSimple = /^.[^:#\[\.,]*$/;
35 jQuery.fn = jQuery.prototype = {
36         init: function( selector, context ) {
37                 // Make sure that a selection was provided
38                 selector = selector || document;
40                 // Handle $(DOMElement)
41                 if ( selector.nodeType ) {
42                         this[0] = selector;
43                         this.length = 1;
44                         this.context = selector;
45                         return this;
46                 }
47                 // Handle HTML strings
48                 if ( typeof selector === "string" ) {
49                         // Are we dealing with HTML string or an ID?
50                         var match = quickExpr.exec( selector );
52                         // Verify a match, and that no context was specified for #id
53                         if ( match && (match[1] || !context) ) {
55                                 // HANDLE: $(html) -> $(array)
56                                 if ( match[1] )
57                                         selector = jQuery.clean( [ match[1] ], context );
59                                 // HANDLE: $("#id")
60                                 else {
61                                         var elem = document.getElementById( match[3] );
63                                         // Handle the case where IE and Opera return items
64                                         // by name instead of ID
65                                         if ( elem && elem.id != match[3] )
66                                                 return jQuery().find( selector );
68                                         // Otherwise, we inject the element directly into the jQuery object
69                                         var ret = jQuery( elem || [] );
70                                         ret.context = document;
71                                         ret.selector = selector;
72                                         return ret;
73                                 }
75                         // HANDLE: $(expr, [context])
76                         // (which is just equivalent to: $(content).find(expr)
77                         } else
78                                 return jQuery( context ).find( selector );
80                 // HANDLE: $(function)
81                 // Shortcut for document ready
82                 } else if ( jQuery.isFunction( selector ) )
83                         return jQuery( document ).ready( selector );
85                 // Make sure that old selector state is passed along
86                 if ( selector.selector && selector.context ) {
87                         this.selector = selector.selector;
88                         this.context = selector.context;
89                 }
91                 return this.setArray(jQuery.isArray( selector ) ?
92                         selector :
93                         jQuery.makeArray(selector));
94         },
96         // Start with an empty selector
97         selector: "",
99         // The current version of jQuery being used
100         jquery: "1.3.2",
102         // The number of elements contained in the matched element set
103         size: function() {
104                 return this.length;
105         },
107         // Get the Nth element in the matched element set OR
108         // Get the whole matched element set as a clean array
109         get: function( num ) {
110                 return num === undefined ?
112                         // Return a 'clean' array
113                         Array.prototype.slice.call( this ) :
115                         // Return just the object
116                         this[ num ];
117         },
119         // Take an array of elements and push it onto the stack
120         // (returning the new matched element set)
121         pushStack: function( elems, name, selector ) {
122                 // Build a new jQuery matched element set
123                 var ret = jQuery( elems );
125                 // Add the old object onto the stack (as a reference)
126                 ret.prevObject = this;
128                 ret.context = this.context;
130                 if ( name === "find" )
131                         ret.selector = this.selector + (this.selector ? " " : "") + selector;
132                 else if ( name )
133                         ret.selector = this.selector + "." + name + "(" + selector + ")";
135                 // Return the newly-formed element set
136                 return ret;
137         },
139         // Force the current matched set of elements to become
140         // the specified array of elements (destroying the stack in the process)
141         // You should use pushStack() in order to do this, but maintain the stack
142         setArray: function( elems ) {
143                 // Resetting the length to 0, then using the native Array push
144                 // is a super-fast way to populate an object with array-like properties
145                 this.length = 0;
146                 Array.prototype.push.apply( this, elems );
148                 return this;
149         },
151         // Execute a callback for every element in the matched set.
152         // (You can seed the arguments with an array of args, but this is
153         // only used internally.)
154         each: function( callback, args ) {
155                 return jQuery.each( this, callback, args );
156         },
158         // Determine the position of an element within
159         // the matched set of elements
160         index: function( elem ) {
161                 // Locate the position of the desired element
162                 return jQuery.inArray(
163                         // If it receives a jQuery object, the first element is used
164                         elem && elem.jquery ? elem[0] : elem
165                 , this );
166         },
168         attr: function( name, value, type ) {
169                 var options = name;
171                 // Look for the case where we're accessing a style value
172                 if ( typeof name === "string" )
173                         if ( value === undefined )
174                                 return this[0] && jQuery[ type || "attr" ]( this[0], name );
176                         else {
177                                 options = {};
178                                 options[ name ] = value;
179                         }
181                 // Check to see if we're setting style values
182                 return this.each(function(i){
183                         // Set all the styles
184                         for ( name in options )
185                                 jQuery.attr(
186                                         type ?
187                                                 this.style :
188                                                 this,
189                                         name, jQuery.prop( this, options[ name ], type, i, name )
190                                 );
191                 });
192         },
194         css: function( key, value ) {
195                 // ignore negative width and height values
196                 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
197                         value = undefined;
198                 return this.attr( key, value, "curCSS" );
199         },
201         text: function( text ) {
202                 if ( typeof text !== "object" && text != null )
203                         return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
205                 var ret = "";
207                 jQuery.each( text || this, function(){
208                         jQuery.each( this.childNodes, function(){
209                                 if ( this.nodeType != 8 )
210                                         ret += this.nodeType != 1 ?
211                                                 this.nodeValue :
212                                                 jQuery.fn.text( [ this ] );
213                         });
214                 });
216                 return ret;
217         },
219         wrapAll: function( html ) {
220                 if ( this[0] ) {
221                         // The elements to wrap the target around
222                         var wrap = jQuery( html, this[0].ownerDocument ).clone();
224                         if ( this[0].parentNode )
225                                 wrap.insertBefore( this[0] );
227                         wrap.map(function(){
228                                 var elem = this;
230                                 while ( elem.firstChild )
231                                         elem = elem.firstChild;
233                                 return elem;
234                         }).append(this);
235                 }
237                 return this;
238         },
240         wrapInner: function( html ) {
241                 return this.each(function(){
242                         jQuery( this ).contents().wrapAll( html );
243                 });
244         },
246         wrap: function( html ) {
247                 return this.each(function(){
248                         jQuery( this ).wrapAll( html );
249                 });
250         },
252         append: function() {
253                 return this.domManip(arguments, true, function(elem){
254                         if (this.nodeType == 1)
255                                 this.appendChild( elem );
256                 });
257         },
259         prepend: function() {
260                 return this.domManip(arguments, true, function(elem){
261                         if (this.nodeType == 1)
262                                 this.insertBefore( elem, this.firstChild );
263                 });
264         },
266         before: function() {
267                 return this.domManip(arguments, false, function(elem){
268                         this.parentNode.insertBefore( elem, this );
269                 });
270         },
272         after: function() {
273                 return this.domManip(arguments, false, function(elem){
274                         this.parentNode.insertBefore( elem, this.nextSibling );
275                 });
276         },
278         end: function() {
279                 return this.prevObject || jQuery( [] );
280         },
282         // For internal use only.
283         // Behaves like an Array's method, not like a jQuery method.
284         push: [].push,
285         sort: [].sort,
286         splice: [].splice,
288         find: function( selector ) {
289                 if ( this.length === 1 ) {
290                         var ret = this.pushStack( [], "find", selector );
291                         ret.length = 0;
292                         jQuery.find( selector, this[0], ret );
293                         return ret;
294                 } else {
295                         return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
296                                 return jQuery.find( selector, elem );
297                         })), "find", selector );
298                 }
299         },
301         clone: function( events ) {
302                 // Do the clone
303                 var ret = this.map(function(){
304                         if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
305                                 // IE copies events bound via attachEvent when
306                                 // using cloneNode. Calling detachEvent on the
307                                 // clone will also remove the events from the orignal
308                                 // In order to get around this, we use innerHTML.
309                                 // Unfortunately, this means some modifications to
310                                 // attributes in IE that are actually only stored
311                                 // as properties will not be copied (such as the
312                                 // the name attribute on an input).
313                                 var html = this.outerHTML;
314                                 if ( !html ) {
315                                         var div = this.ownerDocument.createElement("div");
316                                         div.appendChild( this.cloneNode(true) );
317                                         html = div.innerHTML;
318                                 }
320                                 return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
321                         } else
322                                 return this.cloneNode(true);
323                 });
325                 // Copy the events from the original to the clone
326                 if ( events === true ) {
327                         var orig = this.find("*").andSelf(), i = 0;
329                         ret.find("*").andSelf().each(function(){
330                                 if ( this.nodeName !== orig[i].nodeName )
331                                         return;
333                                 var events = jQuery.data( orig[i], "events" );
335                                 for ( var type in events ) {
336                                         for ( var handler in events[ type ] ) {
337                                                 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
338                                         }
339                                 }
341                                 i++;
342                         });
343                 }
345                 // Return the cloned set
346                 return ret;
347         },
349         filter: function( selector ) {
350                 return this.pushStack(
351                         jQuery.isFunction( selector ) &&
352                         jQuery.grep(this, function(elem, i){
353                                 return selector.call( elem, i );
354                         }) ||
356                         jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
357                                 return elem.nodeType === 1;
358                         }) ), "filter", selector );
359         },
361         closest: function( selector ) {
362                 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
363                         closer = 0;
365                 return this.map(function(){
366                         var cur = this;
367                         while ( cur && cur.ownerDocument ) {
368                                 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
369                                         jQuery.data(cur, "closest", closer);
370                                         return cur;
371                                 }
372                                 cur = cur.parentNode;
373                                 closer++;
374                         }
375                 });
376         },
378         not: function( selector ) {
379                 if ( typeof selector === "string" )
380                         // test special case where just one selector is passed in
381                         if ( isSimple.test( selector ) )
382                                 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
383                         else
384                                 selector = jQuery.multiFilter( selector, this );
386                 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
387                 return this.filter(function() {
388                         return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
389                 });
390         },
392         add: function( selector ) {
393                 return this.pushStack( jQuery.unique( jQuery.merge(
394                         this.get(),
395                         typeof selector === "string" ?
396                                 jQuery( selector ) :
397                                 jQuery.makeArray( selector )
398                 )));
399         },
401         is: function( selector ) {
402                 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
403         },
405         hasClass: function( selector ) {
406                 return !!selector && this.is( "." + selector );
407         },
409         val: function( value ) {
410                 if ( value === undefined ) {                    
411                         var elem = this[0];
413                         if ( elem ) {
414                                 if( jQuery.nodeName( elem, 'option' ) )
415                                         return (elem.attributes.value || {}).specified ? elem.value : elem.text;
416                                 
417                                 // We need to handle select boxes special
418                                 if ( jQuery.nodeName( elem, "select" ) ) {
419                                         var index = elem.selectedIndex,
420                                                 values = [],
421                                                 options = elem.options,
422                                                 one = elem.type == "select-one";
424                                         // Nothing was selected
425                                         if ( index < 0 )
426                                                 return null;
428                                         // Loop through all the selected options
429                                         for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
430                                                 var option = options[ i ];
432                                                 if ( option.selected ) {
433                                                         // Get the specifc value for the option
434                                                         value = jQuery(option).val();
436                                                         // We don't need an array for one selects
437                                                         if ( one )
438                                                                 return value;
440                                                         // Multi-Selects return an array
441                                                         values.push( value );
442                                                 }
443                                         }
445                                         return values;                          
446                                 }
448                                 // Everything else, we just grab the value
449                                 return (elem.value || "").replace(/\r/g, "");
451                         }
453                         return undefined;
454                 }
456                 if ( typeof value === "number" )
457                         value += '';
459                 return this.each(function(){
460                         if ( this.nodeType != 1 )
461                                 return;
463                         if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
464                                 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
465                                         jQuery.inArray(this.name, value) >= 0);
467                         else if ( jQuery.nodeName( this, "select" ) ) {
468                                 var values = jQuery.makeArray(value);
470                                 jQuery( "option", this ).each(function(){
471                                         this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
472                                                 jQuery.inArray( this.text, values ) >= 0);
473                                 });
475                                 if ( !values.length )
476                                         this.selectedIndex = -1;
478                         } else
479                                 this.value = value;
480                 });
481         },
483         html: function( value ) {
484                 return value === undefined ?
485                         (this[0] ?
486                                 this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
487                                 null) :
488                         this.empty().append( value );
489         },
491         replaceWith: function( value ) {
492                 return this.after( value ).remove();
493         },
495         eq: function( i ) {
496                 return this.slice( i, +i + 1 );
497         },
499         slice: function() {
500                 return this.pushStack( Array.prototype.slice.apply( this, arguments ),
501                         "slice", Array.prototype.slice.call(arguments).join(",") );
502         },
504         map: function( callback ) {
505                 return this.pushStack( jQuery.map(this, function(elem, i){
506                         return callback.call( elem, i, elem );
507                 }));
508         },
510         andSelf: function() {
511                 return this.add( this.prevObject );
512         },
514         domManip: function( args, table, callback ) {
515                 if ( this[0] ) {
516                         var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
517                                 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
518                                 first = fragment.firstChild;
520                         if ( first )
521                                 for ( var i = 0, l = this.length; i < l; i++ )
522                                         callback.call( root(this[i], first), this.length > 1 || i > 0 ?
523                                                         fragment.cloneNode(true) : fragment );
524                 
525                         if ( scripts )
526                                 jQuery.each( scripts, evalScript );
527                 }
529                 return this;
530                 
531                 function root( elem, cur ) {
532                         return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
533                                 (elem.getElementsByTagName("tbody")[0] ||
534                                 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
535                                 elem;
536                 }
537         }
540 // Give the init function the jQuery prototype for later instantiation
541 jQuery.fn.init.prototype = jQuery.fn;
543 function evalScript( i, elem ) {
544         if ( elem.src )
545                 jQuery.ajax({
546                         url: elem.src,
547                         async: false,
548                         dataType: "script"
549                 });
551         else
552                 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
554         if ( elem.parentNode )
555                 elem.parentNode.removeChild( elem );
558 function now(){
559         return +new Date;
562 jQuery.extend = jQuery.fn.extend = function() {
563         // copy reference to target object
564         var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
566         // Handle a deep copy situation
567         if ( typeof target === "boolean" ) {
568                 deep = target;
569                 target = arguments[1] || {};
570                 // skip the boolean and the target
571                 i = 2;
572         }
574         // Handle case when target is a string or something (possible in deep copy)
575         if ( typeof target !== "object" && !jQuery.isFunction(target) )
576                 target = {};
578         // extend jQuery itself if only one argument is passed
579         if ( length == i ) {
580                 target = this;
581                 --i;
582         }
584         for ( ; i < length; i++ )
585                 // Only deal with non-null/undefined values
586                 if ( (options = arguments[ i ]) != null )
587                         // Extend the base object
588                         for ( var name in options ) {
589                                 var src = target[ name ], copy = options[ name ];
591                                 // Prevent never-ending loop
592                                 if ( target === copy )
593                                         continue;
595                                 // Recurse if we're merging object values
596                                 if ( deep && copy && typeof copy === "object" && !copy.nodeType )
597                                         target[ name ] = jQuery.extend( deep, 
598                                                 // Never move original objects, clone them
599                                                 src || ( copy.length != null ? [ ] : { } )
600                                         , copy );
602                                 // Don't bring in undefined values
603                                 else if ( copy !== undefined )
604                                         target[ name ] = copy;
606                         }
608         // Return the modified object
609         return target;
612 // exclude the following css properties to add px
613 var     exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
614         // cache defaultView
615         defaultView = document.defaultView || {},
616         toString = Object.prototype.toString;
618 jQuery.extend({
619         noConflict: function( deep ) {
620                 window.$ = _$;
622                 if ( deep )
623                         window.jQuery = _jQuery;
625                 return jQuery;
626         },
628         // See test/unit/core.js for details concerning isFunction.
629         // Since version 1.3, DOM methods and functions like alert
630         // aren't supported. They return false on IE (#2968).
631         isFunction: function( obj ) {
632                 return toString.call(obj) === "[object Function]";
633         },
635         isArray: function( obj ) {
636                 return toString.call(obj) === "[object Array]";
637         },
639         // check if an element is in a (or is an) XML document
640         isXMLDoc: function( elem ) {
641                 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
642                         !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
643         },
645         // Evalulates a script in a global context
646         globalEval: function( data ) {
647                 if ( data && /\S/.test(data) ) {
648                         // Inspired by code by Andrea Giammarchi
649                         // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
650                         var head = document.getElementsByTagName("head")[0] || document.documentElement,
651                                 script = document.createElement("script");
653                         script.type = "text/javascript";
654                         if ( jQuery.support.scriptEval )
655                                 script.appendChild( document.createTextNode( data ) );
656                         else
657                                 script.text = data;
659                         // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
660                         // This arises when a base node is used (#2709).
661                         head.insertBefore( script, head.firstChild );
662                         head.removeChild( script );
663                 }
664         },
666         nodeName: function( elem, name ) {
667                 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
668         },
670         // args is for internal usage only
671         each: function( object, callback, args ) {
672                 var name, i = 0, length = object.length;
674                 if ( args ) {
675                         if ( length === undefined ) {
676                                 for ( name in object )
677                                         if ( callback.apply( object[ name ], args ) === false )
678                                                 break;
679                         } else
680                                 for ( ; i < length; )
681                                         if ( callback.apply( object[ i++ ], args ) === false )
682                                                 break;
684                 // A special, fast, case for the most common use of each
685                 } else {
686                         if ( length === undefined ) {
687                                 for ( name in object )
688                                         if ( callback.call( object[ name ], name, object[ name ] ) === false )
689                                                 break;
690                         } else
691                                 for ( var value = object[0];
692                                         i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
693                 }
695                 return object;
696         },
698         prop: function( elem, value, type, i, name ) {
699                 // Handle executable functions
700                 if ( jQuery.isFunction( value ) )
701                         value = value.call( elem, i );
703                 // Handle passing in a number to a CSS property
704                 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
705                         value + "px" :
706                         value;
707         },
709         className: {
710                 // internal only, use addClass("class")
711                 add: function( elem, classNames ) {
712                         jQuery.each((classNames || "").split(/\s+/), function(i, className){
713                                 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
714                                         elem.className += (elem.className ? " " : "") + className;
715                         });
716                 },
718                 // internal only, use removeClass("class")
719                 remove: function( elem, classNames ) {
720                         if (elem.nodeType == 1)
721                                 elem.className = classNames !== undefined ?
722                                         jQuery.grep(elem.className.split(/\s+/), function(className){
723                                                 return !jQuery.className.has( classNames, className );
724                                         }).join(" ") :
725                                         "";
726                 },
728                 // internal only, use hasClass("class")
729                 has: function( elem, className ) {
730                         return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
731                 }
732         },
734         // A method for quickly swapping in/out CSS properties to get correct calculations
735         swap: function( elem, options, callback ) {
736                 var old = {};
737                 // Remember the old values, and insert the new ones
738                 for ( var name in options ) {
739                         old[ name ] = elem.style[ name ];
740                         elem.style[ name ] = options[ name ];
741                 }
743                 callback.call( elem );
745                 // Revert the old values
746                 for ( var name in options )
747                         elem.style[ name ] = old[ name ];
748         },
750         css: function( elem, name, force, extra ) {
751                 if ( name == "width" || name == "height" ) {
752                         var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
754                         function getWH() {
755                                 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
757                                 if ( extra === "border" )
758                                         return;
760                                 jQuery.each( which, function() {
761                                         if ( !extra )
762                                                 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
763                                         if ( extra === "margin" )
764                                                 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
765                                         else
766                                                 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
767                                 });
768                         }
770                         if ( elem.offsetWidth !== 0 )
771                                 getWH();
772                         else
773                                 jQuery.swap( elem, props, getWH );
775                         return Math.max(0, Math.round(val));
776                 }
778                 return jQuery.curCSS( elem, name, force );
779         },
781         curCSS: function( elem, name, force ) {
782                 var ret, style = elem.style;
784                 // We need to handle opacity special in IE
785                 if ( name == "opacity" && !jQuery.support.opacity ) {
786                         ret = jQuery.attr( style, "opacity" );
788                         return ret == "" ?
789                                 "1" :
790                                 ret;
791                 }
793                 // Make sure we're using the right name for getting the float value
794                 if ( name.match( /float/i ) )
795                         name = styleFloat;
797                 if ( !force && style && style[ name ] )
798                         ret = style[ name ];
800                 else if ( defaultView.getComputedStyle ) {
802                         // Only "float" is needed here
803                         if ( name.match( /float/i ) )
804                                 name = "float";
806                         name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
808                         var computedStyle = defaultView.getComputedStyle( elem, null );
810                         if ( computedStyle )
811                                 ret = computedStyle.getPropertyValue( name );
813                         // We should always get a number back from opacity
814                         if ( name == "opacity" && ret == "" )
815                                 ret = "1";
817                 } else if ( elem.currentStyle ) {
818                         var camelCase = name.replace(/\-(\w)/g, function(all, letter){
819                                 return letter.toUpperCase();
820                         });
822                         ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
824                         // From the awesome hack by Dean Edwards
825                         // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
827                         // If we're not dealing with a regular pixel number
828                         // but a number that has a weird ending, we need to convert it to pixels
829                         if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
830                                 // Remember the original values
831                                 var left = style.left, rsLeft = elem.runtimeStyle.left;
833                                 // Put in the new values to get a computed value out
834                                 elem.runtimeStyle.left = elem.currentStyle.left;
835                                 style.left = ret || 0;
836                                 ret = style.pixelLeft + "px";
838                                 // Revert the changed values
839                                 style.left = left;
840                                 elem.runtimeStyle.left = rsLeft;
841                         }
842                 }
844                 return ret;
845         },
847         clean: function( elems, context, fragment ) {
848                 context = context || document;
850                 // !context.createElement fails in IE with an error but returns typeof 'object'
851                 if ( typeof context.createElement === "undefined" )
852                         context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
854                 // If a single string is passed in and it's a single tag
855                 // just do a createElement and skip the rest
856                 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
857                         var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
858                         if ( match )
859                                 return [ context.createElement( match[1] ) ];
860                 }
862                 var ret = [], scripts = [], div = context.createElement("div");
864                 jQuery.each(elems, function(i, elem){
865                         if ( typeof elem === "number" )
866                                 elem += '';
868                         if ( !elem )
869                                 return;
871                         // Convert html string into DOM nodes
872                         if ( typeof elem === "string" ) {
873                                 // Fix "XHTML"-style tags in all browsers
874                                 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
875                                         return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
876                                                 all :
877                                                 front + "></" + tag + ">";
878                                 });
880                                 // Trim whitespace, otherwise indexOf won't work as expected
881                                 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
883                                 var wrap =
884                                         // option or optgroup
885                                         !tags.indexOf("<opt") &&
886                                         [ 1, "<select multiple='multiple'>", "</select>" ] ||
888                                         !tags.indexOf("<leg") &&
889                                         [ 1, "<fieldset>", "</fieldset>" ] ||
891                                         tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
892                                         [ 1, "<table>", "</table>" ] ||
894                                         !tags.indexOf("<tr") &&
895                                         [ 2, "<table><tbody>", "</tbody></table>" ] ||
897                                         // <thead> matched above
898                                         (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
899                                         [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
901                                         !tags.indexOf("<col") &&
902                                         [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
904                                         // IE can't serialize <link> and <script> tags normally
905                                         !jQuery.support.htmlSerialize &&
906                                         [ 1, "div<div>", "</div>" ] ||
908                                         [ 0, "", "" ];
910                                 // Go to html and back, then peel off extra wrappers
911                                 div.innerHTML = wrap[1] + elem + wrap[2];
913                                 // Move to the right depth
914                                 while ( wrap[0]-- )
915                                         div = div.lastChild;
917                                 // Remove IE's autoinserted <tbody> from table fragments
918                                 if ( !jQuery.support.tbody ) {
920                                         // String was a <table>, *may* have spurious <tbody>
921                                         var hasBody = /<tbody/i.test(elem),
922                                                 tbody = !tags.indexOf("<table") && !hasBody ?
923                                                         div.firstChild && div.firstChild.childNodes :
925                                                 // String was a bare <thead> or <tfoot>
926                                                 wrap[1] == "<table>" && !hasBody ?
927                                                         div.childNodes :
928                                                         [];
930                                         for ( var j = tbody.length - 1; j >= 0 ; --j )
931                                                 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
932                                                         tbody[ j ].parentNode.removeChild( tbody[ j ] );
934                                         }
936                                 // IE completely kills leading whitespace when innerHTML is used
937                                 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
938                                         div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
939                                 
940                                 elem = jQuery.makeArray( div.childNodes );
941                         }
943                         if ( elem.nodeType )
944                                 ret.push( elem );
945                         else
946                                 ret = jQuery.merge( ret, elem );
948                 });
950                 if ( fragment ) {
951                         for ( var i = 0; ret[i]; i++ ) {
952                                 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
953                                         scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
954                                 } else {
955                                         if ( ret[i].nodeType === 1 )
956                                                 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
957                                         fragment.appendChild( ret[i] );
958                                 }
959                         }
960                         
961                         return scripts;
962                 }
964                 return ret;
965         },
967         attr: function( elem, name, value ) {
968                 // don't set attributes on text and comment nodes
969                 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
970                         return undefined;
972                 var notxml = !jQuery.isXMLDoc( elem ),
973                         // Whether we are setting (or getting)
974                         set = value !== undefined;
976                 // Try to normalize/fix the name
977                 name = notxml && jQuery.props[ name ] || name;
979                 // Only do all the following if this is a node (faster for style)
980                 // IE elem.getAttribute passes even for style
981                 if ( elem.tagName ) {
983                         // These attributes require special treatment
984                         var special = /href|src|style/.test( name );
986                         // Safari mis-reports the default selected property of a hidden option
987                         // Accessing the parent's selectedIndex property fixes it
988                         if ( name == "selected" && elem.parentNode )
989                                 elem.parentNode.selectedIndex;
991                         // If applicable, access the attribute via the DOM 0 way
992                         if ( name in elem && notxml && !special ) {
993                                 if ( set ){
994                                         // We can't allow the type property to be changed (since it causes problems in IE)
995                                         if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
996                                                 throw "type property can't be changed";
998                                         elem[ name ] = value;
999                                 }
1001                                 // browsers index elements by id/name on forms, give priority to attributes.
1002                                 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1003                                         return elem.getAttributeNode( name ).nodeValue;
1005                                 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1006                                 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1007                                 if ( name == "tabIndex" ) {
1008                                         var attributeNode = elem.getAttributeNode( "tabIndex" );
1009                                         return attributeNode && attributeNode.specified
1010                                                 ? attributeNode.value
1011                                                 : elem.nodeName.match(/(button|input|object|select|textarea)/i)
1012                                                         ? 0
1013                                                         : elem.nodeName.match(/^(a|area)$/i) && elem.href
1014                                                                 ? 0
1015                                                                 : undefined;
1016                                 }
1018                                 return elem[ name ];
1019                         }
1021                         if ( !jQuery.support.style && notxml &&  name == "style" )
1022                                 return jQuery.attr( elem.style, "cssText", value );
1024                         if ( set )
1025                                 // convert the value to a string (all browsers do this but IE) see #1070
1026                                 elem.setAttribute( name, "" + value );
1028                         var attr = !jQuery.support.hrefNormalized && notxml && special
1029                                         // Some attributes require a special call on IE
1030                                         ? elem.getAttribute( name, 2 )
1031                                         : elem.getAttribute( name );
1033                         // Non-existent attributes return null, we normalize to undefined
1034                         return attr === null ? undefined : attr;
1035                 }
1037                 // elem is actually elem.style ... set the style
1039                 // IE uses filters for opacity
1040                 if ( !jQuery.support.opacity && name == "opacity" ) {
1041                         if ( set ) {
1042                                 // IE has trouble with opacity if it does not have layout
1043                                 // Force it by setting the zoom level
1044                                 elem.zoom = 1;
1046                                 // Set the alpha filter to set the opacity
1047                                 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1048                                         (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1049                         }
1051                         return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1052                                 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1053                                 "";
1054                 }
1056                 name = name.replace(/-([a-z])/ig, function(all, letter){
1057                         return letter.toUpperCase();
1058                 });
1060                 if ( set )
1061                         elem[ name ] = value;
1063                 return elem[ name ];
1064         },
1066         trim: function( text ) {
1067                 return (text || "").replace( /^\s+|\s+$/g, "" );
1068         },
1070         makeArray: function( array ) {
1071                 var ret = [];
1073                 if( array != null ){
1074                         var i = array.length;
1075                         // The window, strings (and functions) also have 'length'
1076                         if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
1077                                 ret[0] = array;
1078                         else
1079                                 while( i )
1080                                         ret[--i] = array[i];
1081                 }
1083                 return ret;
1084         },
1086         inArray: function( elem, array ) {
1087                 for ( var i = 0, length = array.length; i < length; i++ )
1088                 // Use === because on IE, window == document
1089                         if ( array[ i ] === elem )
1090                                 return i;
1092                 return -1;
1093         },
1095         merge: function( first, second ) {
1096                 // We have to loop this way because IE & Opera overwrite the length
1097                 // expando of getElementsByTagName
1098                 var i = 0, elem, pos = first.length;
1099                 // Also, we need to make sure that the correct elements are being returned
1100                 // (IE returns comment nodes in a '*' query)
1101                 if ( !jQuery.support.getAll ) {
1102                         while ( (elem = second[ i++ ]) != null )
1103                                 if ( elem.nodeType != 8 )
1104                                         first[ pos++ ] = elem;
1106                 } else
1107                         while ( (elem = second[ i++ ]) != null )
1108                                 first[ pos++ ] = elem;
1110                 return first;
1111         },
1113         unique: function( array ) {
1114                 var ret = [], done = {};
1116                 try {
1118                         for ( var i = 0, length = array.length; i < length; i++ ) {
1119                                 var id = jQuery.data( array[ i ] );
1121                                 if ( !done[ id ] ) {
1122                                         done[ id ] = true;
1123                                         ret.push( array[ i ] );
1124                                 }
1125                         }
1127                 } catch( e ) {
1128                         ret = array;
1129                 }
1131                 return ret;
1132         },
1134         grep: function( elems, callback, inv ) {
1135                 var ret = [];
1137                 // Go through the array, only saving the items
1138                 // that pass the validator function
1139                 for ( var i = 0, length = elems.length; i < length; i++ )
1140                         if ( !inv != !callback( elems[ i ], i ) )
1141                                 ret.push( elems[ i ] );
1143                 return ret;
1144         },
1146         map: function( elems, callback ) {
1147                 var ret = [];
1149                 // Go through the array, translating each of the items to their
1150                 // new value (or values).
1151                 for ( var i = 0, length = elems.length; i < length; i++ ) {
1152                         var value = callback( elems[ i ], i );
1154                         if ( value != null )
1155                                 ret[ ret.length ] = value;
1156                 }
1158                 return ret.concat.apply( [], ret );
1159         }
1162 // Use of jQuery.browser is deprecated.
1163 // It's included for backwards compatibility and plugins,
1164 // although they should work to migrate away.
1166 var userAgent = navigator.userAgent.toLowerCase();
1168 // Figure out what browser is being used
1169 jQuery.browser = {
1170         version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
1171         safari: /webkit/.test( userAgent ),
1172         opera: /opera/.test( userAgent ),
1173         msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1174         mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1177 jQuery.each({
1178         parent: function(elem){return elem.parentNode;},
1179         parents: function(elem){return jQuery.dir(elem,"parentNode");},
1180         next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1181         prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1182         nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1183         prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1184         siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1185         children: function(elem){return jQuery.sibling(elem.firstChild);},
1186         contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1187 }, function(name, fn){
1188         jQuery.fn[ name ] = function( selector ) {
1189                 var ret = jQuery.map( this, fn );
1191                 if ( selector && typeof selector == "string" )
1192                         ret = jQuery.multiFilter( selector, ret );
1194                 return this.pushStack( jQuery.unique( ret ), name, selector );
1195         };
1198 jQuery.each({
1199         appendTo: "append",
1200         prependTo: "prepend",
1201         insertBefore: "before",
1202         insertAfter: "after",
1203         replaceAll: "replaceWith"
1204 }, function(name, original){
1205         jQuery.fn[ name ] = function( selector ) {
1206                 var ret = [], insert = jQuery( selector );
1208                 for ( var i = 0, l = insert.length; i < l; i++ ) {
1209                         var elems = (i > 0 ? this.clone(true) : this).get();
1210                         jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
1211                         ret = ret.concat( elems );
1212                 }
1214                 return this.pushStack( ret, name, selector );
1215         };
1218 jQuery.each({
1219         removeAttr: function( name ) {
1220                 jQuery.attr( this, name, "" );
1221                 if (this.nodeType == 1)
1222                         this.removeAttribute( name );
1223         },
1225         addClass: function( classNames ) {
1226                 jQuery.className.add( this, classNames );
1227         },
1229         removeClass: function( classNames ) {
1230                 jQuery.className.remove( this, classNames );
1231         },
1233         toggleClass: function( classNames, state ) {
1234                 if( typeof state !== "boolean" )
1235                         state = !jQuery.className.has( this, classNames );
1236                 jQuery.className[ state ? "add" : "remove" ]( this, classNames );
1237         },
1239         remove: function( selector ) {
1240                 if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
1241                         // Prevent memory leaks
1242                         jQuery( "*", this ).add([this]).each(function(){
1243                                 jQuery.event.remove(this);
1244                                 jQuery.removeData(this);
1245                         });
1246                         if (this.parentNode)
1247                                 this.parentNode.removeChild( this );
1248                 }
1249         },
1251         empty: function() {
1252                 // Remove element nodes and prevent memory leaks
1253                 jQuery(this).children().remove();
1255                 // Remove any remaining nodes
1256                 while ( this.firstChild )
1257                         this.removeChild( this.firstChild );
1258         }
1259 }, function(name, fn){
1260         jQuery.fn[ name ] = function(){
1261                 return this.each( fn, arguments );
1262         };
1265 // Helper function used by the dimensions and offset modules
1266 function num(elem, prop) {
1267         return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1269 var expando = "jQuery" + now(), uuid = 0, windowData = {};
1271 jQuery.extend({
1272         cache: {},
1274         data: function( elem, name, data ) {
1275                 elem = elem == window ?
1276                         windowData :
1277                         elem;
1279                 var id = elem[ expando ];
1281                 // Compute a unique ID for the element
1282                 if ( !id )
1283                         id = elem[ expando ] = ++uuid;
1285                 // Only generate the data cache if we're
1286                 // trying to access or manipulate it
1287                 if ( name && !jQuery.cache[ id ] )
1288                         jQuery.cache[ id ] = {};
1290                 // Prevent overriding the named cache with undefined values
1291                 if ( data !== undefined )
1292                         jQuery.cache[ id ][ name ] = data;
1294                 // Return the named cache data, or the ID for the element
1295                 return name ?
1296                         jQuery.cache[ id ][ name ] :
1297                         id;
1298         },
1300         removeData: function( elem, name ) {
1301                 elem = elem == window ?
1302                         windowData :
1303                         elem;
1305                 var id = elem[ expando ];
1307                 // If we want to remove a specific section of the element's data
1308                 if ( name ) {
1309                         if ( jQuery.cache[ id ] ) {
1310                                 // Remove the section of cache data
1311                                 delete jQuery.cache[ id ][ name ];
1313                                 // If we've removed all the data, remove the element's cache
1314                                 name = "";
1316                                 for ( name in jQuery.cache[ id ] )
1317                                         break;
1319                                 if ( !name )
1320                                         jQuery.removeData( elem );
1321                         }
1323                 // Otherwise, we want to remove all of the element's data
1324                 } else {
1325                         // Clean up the element expando
1326                         try {
1327                                 delete elem[ expando ];
1328                         } catch(e){
1329                                 // IE has trouble directly removing the expando
1330                                 // but it's ok with using removeAttribute
1331                                 if ( elem.removeAttribute )
1332                                         elem.removeAttribute( expando );
1333                         }
1335                         // Completely remove the data cache
1336                         delete jQuery.cache[ id ];
1337                 }
1338         },
1339         queue: function( elem, type, data ) {
1340                 if ( elem ){
1341         
1342                         type = (type || "fx") + "queue";
1343         
1344                         var q = jQuery.data( elem, type );
1345         
1346                         if ( !q || jQuery.isArray(data) )
1347                                 q = jQuery.data( elem, type, jQuery.makeArray(data) );
1348                         else if( data )
1349                                 q.push( data );
1350         
1351                 }
1352                 return q;
1353         },
1355         dequeue: function( elem, type ){
1356                 var queue = jQuery.queue( elem, type ),
1357                         fn = queue.shift();
1358                 
1359                 if( !type || type === "fx" )
1360                         fn = queue[0];
1361                         
1362                 if( fn !== undefined )
1363                         fn.call(elem);
1364         }
1367 jQuery.fn.extend({
1368         data: function( key, value ){
1369                 var parts = key.split(".");
1370                 parts[1] = parts[1] ? "." + parts[1] : "";
1372                 if ( value === undefined ) {
1373                         var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1375                         if ( data === undefined && this.length )
1376                                 data = jQuery.data( this[0], key );
1378                         return data === undefined && parts[1] ?
1379                                 this.data( parts[0] ) :
1380                                 data;
1381                 } else
1382                         return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
1383                                 jQuery.data( this, key, value );
1384                         });
1385         },
1387         removeData: function( key ){
1388                 return this.each(function(){
1389                         jQuery.removeData( this, key );
1390                 });
1391         },
1392         queue: function(type, data){
1393                 if ( typeof type !== "string" ) {
1394                         data = type;
1395                         type = "fx";
1396                 }
1398                 if ( data === undefined )
1399                         return jQuery.queue( this[0], type );
1401                 return this.each(function(){
1402                         var queue = jQuery.queue( this, type, data );
1403                         
1404                          if( type == "fx" && queue.length == 1 )
1405                                 queue[0].call(this);
1406                 });
1407         },
1408         dequeue: function(type){
1409                 return this.each(function(){
1410                         jQuery.dequeue( this, type );
1411                 });
1412         }
1413 });/*!
1414  * Sizzle CSS Selector Engine - v0.9.3
1415  *  Copyright 2009, The Dojo Foundation
1416  *  Released under the MIT, BSD, and GPL Licenses.
1417  *  More information: http://sizzlejs.com/
1418  */
1419 (function(){
1421 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
1422         done = 0,
1423         toString = Object.prototype.toString;
1425 var Sizzle = function(selector, context, results, seed) {
1426         results = results || [];
1427         context = context || document;
1429         if ( context.nodeType !== 1 && context.nodeType !== 9 )
1430                 return [];
1431         
1432         if ( !selector || typeof selector !== "string" ) {
1433                 return results;
1434         }
1436         var parts = [], m, set, checkSet, check, mode, extra, prune = true;
1437         
1438         // Reset the position of the chunker regexp (start from head)
1439         chunker.lastIndex = 0;
1440         
1441         while ( (m = chunker.exec(selector)) !== null ) {
1442                 parts.push( m[1] );
1443                 
1444                 if ( m[2] ) {
1445                         extra = RegExp.rightContext;
1446                         break;
1447                 }
1448         }
1450         if ( parts.length > 1 && origPOS.exec( selector ) ) {
1451                 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
1452                         set = posProcess( parts[0] + parts[1], context );
1453                 } else {
1454                         set = Expr.relative[ parts[0] ] ?
1455                                 [ context ] :
1456                                 Sizzle( parts.shift(), context );
1458                         while ( parts.length ) {
1459                                 selector = parts.shift();
1461                                 if ( Expr.relative[ selector ] )
1462                                         selector += parts.shift();
1464                                 set = posProcess( selector, set );
1465                         }
1466                 }
1467         } else {
1468                 var ret = seed ?
1469                         { expr: parts.pop(), set: makeArray(seed) } :
1470                         Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
1471                 set = Sizzle.filter( ret.expr, ret.set );
1473                 if ( parts.length > 0 ) {
1474                         checkSet = makeArray(set);
1475                 } else {
1476                         prune = false;
1477                 }
1479                 while ( parts.length ) {
1480                         var cur = parts.pop(), pop = cur;
1482                         if ( !Expr.relative[ cur ] ) {
1483                                 cur = "";
1484                         } else {
1485                                 pop = parts.pop();
1486                         }
1488                         if ( pop == null ) {
1489                                 pop = context;
1490                         }
1492                         Expr.relative[ cur ]( checkSet, pop, isXML(context) );
1493                 }
1494         }
1496         if ( !checkSet ) {
1497                 checkSet = set;
1498         }
1500         if ( !checkSet ) {
1501                 throw "Syntax error, unrecognized expression: " + (cur || selector);
1502         }
1504         if ( toString.call(checkSet) === "[object Array]" ) {
1505                 if ( !prune ) {
1506                         results.push.apply( results, checkSet );
1507                 } else if ( context.nodeType === 1 ) {
1508                         for ( var i = 0; checkSet[i] != null; i++ ) {
1509                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
1510                                         results.push( set[i] );
1511                                 }
1512                         }
1513                 } else {
1514                         for ( var i = 0; checkSet[i] != null; i++ ) {
1515                                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
1516                                         results.push( set[i] );
1517                                 }
1518                         }
1519                 }
1520         } else {
1521                 makeArray( checkSet, results );
1522         }
1524         if ( extra ) {
1525                 Sizzle( extra, context, results, seed );
1527                 if ( sortOrder ) {
1528                         hasDuplicate = false;
1529                         results.sort(sortOrder);
1531                         if ( hasDuplicate ) {
1532                                 for ( var i = 1; i < results.length; i++ ) {
1533                                         if ( results[i] === results[i-1] ) {
1534                                                 results.splice(i--, 1);
1535                                         }
1536                                 }
1537                         }
1538                 }
1539         }
1541         return results;
1544 Sizzle.matches = function(expr, set){
1545         return Sizzle(expr, null, null, set);
1548 Sizzle.find = function(expr, context, isXML){
1549         var set, match;
1551         if ( !expr ) {
1552                 return [];
1553         }
1555         for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
1556                 var type = Expr.order[i], match;
1557                 
1558                 if ( (match = Expr.match[ type ].exec( expr )) ) {
1559                         var left = RegExp.leftContext;
1561                         if ( left.substr( left.length - 1 ) !== "\\" ) {
1562                                 match[1] = (match[1] || "").replace(/\\/g, "");
1563                                 set = Expr.find[ type ]( match, context, isXML );
1564                                 if ( set != null ) {
1565                                         expr = expr.replace( Expr.match[ type ], "" );
1566                                         break;
1567                                 }
1568                         }
1569                 }
1570         }
1572         if ( !set ) {
1573                 set = context.getElementsByTagName("*");
1574         }
1576         return {set: set, expr: expr};
1579 Sizzle.filter = function(expr, set, inplace, not){
1580         var old = expr, result = [], curLoop = set, match, anyFound,
1581                 isXMLFilter = set && set[0] && isXML(set[0]);
1583         while ( expr && set.length ) {
1584                 for ( var type in Expr.filter ) {
1585                         if ( (match = Expr.match[ type ].exec( expr )) != null ) {
1586                                 var filter = Expr.filter[ type ], found, item;
1587                                 anyFound = false;
1589                                 if ( curLoop == result ) {
1590                                         result = [];
1591                                 }
1593                                 if ( Expr.preFilter[ type ] ) {
1594                                         match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
1596                                         if ( !match ) {
1597                                                 anyFound = found = true;
1598                                         } else if ( match === true ) {
1599                                                 continue;
1600                                         }
1601                                 }
1603                                 if ( match ) {
1604                                         for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
1605                                                 if ( item ) {
1606                                                         found = filter( item, match, i, curLoop );
1607                                                         var pass = not ^ !!found;
1609                                                         if ( inplace && found != null ) {
1610                                                                 if ( pass ) {
1611                                                                         anyFound = true;
1612                                                                 } else {
1613                                                                         curLoop[i] = false;
1614                                                                 }
1615                                                         } else if ( pass ) {
1616                                                                 result.push( item );
1617                                                                 anyFound = true;
1618                                                         }
1619                                                 }
1620                                         }
1621                                 }
1623                                 if ( found !== undefined ) {
1624                                         if ( !inplace ) {
1625                                                 curLoop = result;
1626                                         }
1628                                         expr = expr.replace( Expr.match[ type ], "" );
1630                                         if ( !anyFound ) {
1631                                                 return [];
1632                                         }
1634                                         break;
1635                                 }
1636                         }
1637                 }
1639                 // Improper expression
1640                 if ( expr == old ) {
1641                         if ( anyFound == null ) {
1642                                 throw "Syntax error, unrecognized expression: " + expr;
1643                         } else {
1644                                 break;
1645                         }
1646                 }
1648                 old = expr;
1649         }
1651         return curLoop;
1654 var Expr = Sizzle.selectors = {
1655         order: [ "ID", "NAME", "TAG" ],
1656         match: {
1657                 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1658                 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1659                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
1660                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
1661                 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
1662                 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
1663                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
1664                 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
1665         },
1666         attrMap: {
1667                 "class": "className",
1668                 "for": "htmlFor"
1669         },
1670         attrHandle: {
1671                 href: function(elem){
1672                         return elem.getAttribute("href");
1673                 }
1674         },
1675         relative: {
1676                 "+": function(checkSet, part, isXML){
1677                         var isPartStr = typeof part === "string",
1678                                 isTag = isPartStr && !/\W/.test(part),
1679                                 isPartStrNotTag = isPartStr && !isTag;
1681                         if ( isTag && !isXML ) {
1682                                 part = part.toUpperCase();
1683                         }
1685                         for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
1686                                 if ( (elem = checkSet[i]) ) {
1687                                         while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
1689                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
1690                                                 elem || false :
1691                                                 elem === part;
1692                                 }
1693                         }
1695                         if ( isPartStrNotTag ) {
1696                                 Sizzle.filter( part, checkSet, true );
1697                         }
1698                 },
1699                 ">": function(checkSet, part, isXML){
1700                         var isPartStr = typeof part === "string";
1702                         if ( isPartStr && !/\W/.test(part) ) {
1703                                 part = isXML ? part : part.toUpperCase();
1705                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1706                                         var elem = checkSet[i];
1707                                         if ( elem ) {
1708                                                 var parent = elem.parentNode;
1709                                                 checkSet[i] = parent.nodeName === part ? parent : false;
1710                                         }
1711                                 }
1712                         } else {
1713                                 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1714                                         var elem = checkSet[i];
1715                                         if ( elem ) {
1716                                                 checkSet[i] = isPartStr ?
1717                                                         elem.parentNode :
1718                                                         elem.parentNode === part;
1719                                         }
1720                                 }
1722                                 if ( isPartStr ) {
1723                                         Sizzle.filter( part, checkSet, true );
1724                                 }
1725                         }
1726                 },
1727                 "": function(checkSet, part, isXML){
1728                         var doneName = done++, checkFn = dirCheck;
1730                         if ( !part.match(/\W/) ) {
1731                                 var nodeCheck = part = isXML ? part : part.toUpperCase();
1732                                 checkFn = dirNodeCheck;
1733                         }
1735                         checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
1736                 },
1737                 "~": function(checkSet, part, isXML){
1738                         var doneName = done++, checkFn = dirCheck;
1740                         if ( typeof part === "string" && !part.match(/\W/) ) {
1741                                 var nodeCheck = part = isXML ? part : part.toUpperCase();
1742                                 checkFn = dirNodeCheck;
1743                         }
1745                         checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
1746                 }
1747         },
1748         find: {
1749                 ID: function(match, context, isXML){
1750                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
1751                                 var m = context.getElementById(match[1]);
1752                                 return m ? [m] : [];
1753                         }
1754                 },
1755                 NAME: function(match, context, isXML){
1756                         if ( typeof context.getElementsByName !== "undefined" ) {
1757                                 var ret = [], results = context.getElementsByName(match[1]);
1759                                 for ( var i = 0, l = results.length; i < l; i++ ) {
1760                                         if ( results[i].getAttribute("name") === match[1] ) {
1761                                                 ret.push( results[i] );
1762                                         }
1763                                 }
1765                                 return ret.length === 0 ? null : ret;
1766                         }
1767                 },
1768                 TAG: function(match, context){
1769                         return context.getElementsByTagName(match[1]);
1770                 }
1771         },
1772         preFilter: {
1773                 CLASS: function(match, curLoop, inplace, result, not, isXML){
1774                         match = " " + match[1].replace(/\\/g, "") + " ";
1776                         if ( isXML ) {
1777                                 return match;
1778                         }
1780                         for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
1781                                 if ( elem ) {
1782                                         if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
1783                                                 if ( !inplace )
1784                                                         result.push( elem );
1785                                         } else if ( inplace ) {
1786                                                 curLoop[i] = false;
1787                                         }
1788                                 }
1789                         }
1791                         return false;
1792                 },
1793                 ID: function(match){
1794                         return match[1].replace(/\\/g, "");
1795                 },
1796                 TAG: function(match, curLoop){
1797                         for ( var i = 0; curLoop[i] === false; i++ ){}
1798                         return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
1799                 },
1800                 CHILD: function(match){
1801                         if ( match[1] == "nth" ) {
1802                                 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1803                                 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1804                                         match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
1805                                         !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
1807                                 // calculate the numbers (first)n+(last) including if they are negative
1808                                 match[2] = (test[1] + (test[2] || 1)) - 0;
1809                                 match[3] = test[3] - 0;
1810                         }
1812                         // TODO: Move to normal caching system
1813                         match[0] = done++;
1815                         return match;
1816                 },
1817                 ATTR: function(match, curLoop, inplace, result, not, isXML){
1818                         var name = match[1].replace(/\\/g, "");
1819                         
1820                         if ( !isXML && Expr.attrMap[name] ) {
1821                                 match[1] = Expr.attrMap[name];
1822                         }
1824                         if ( match[2] === "~=" ) {
1825                                 match[4] = " " + match[4] + " ";
1826                         }
1828                         return match;
1829                 },
1830                 PSEUDO: function(match, curLoop, inplace, result, not){
1831                         if ( match[1] === "not" ) {
1832                                 // If we're dealing with a complex expression, or a simple one
1833                                 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
1834                                         match[3] = Sizzle(match[3], null, null, curLoop);
1835                                 } else {
1836                                         var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
1837                                         if ( !inplace ) {
1838                                                 result.push.apply( result, ret );
1839                                         }
1840                                         return false;
1841                                 }
1842                         } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
1843                                 return true;
1844                         }
1845                         
1846                         return match;
1847                 },
1848                 POS: function(match){
1849                         match.unshift( true );
1850                         return match;
1851                 }
1852         },
1853         filters: {
1854                 enabled: function(elem){
1855                         return elem.disabled === false && elem.type !== "hidden";
1856                 },
1857                 disabled: function(elem){
1858                         return elem.disabled === true;
1859                 },
1860                 checked: function(elem){
1861                         return elem.checked === true;
1862                 },
1863                 selected: function(elem){
1864                         // Accessing this property makes selected-by-default
1865                         // options in Safari work properly
1866                         elem.parentNode.selectedIndex;
1867                         return elem.selected === true;
1868                 },
1869                 parent: function(elem){
1870                         return !!elem.firstChild;
1871                 },
1872                 empty: function(elem){
1873                         return !elem.firstChild;
1874                 },
1875                 has: function(elem, i, match){
1876                         return !!Sizzle( match[3], elem ).length;
1877                 },
1878                 header: function(elem){
1879                         return /h\d/i.test( elem.nodeName );
1880                 },
1881                 text: function(elem){
1882                         return "text" === elem.type;
1883                 },
1884                 radio: function(elem){
1885                         return "radio" === elem.type;
1886                 },
1887                 checkbox: function(elem){
1888                         return "checkbox" === elem.type;
1889                 },
1890                 file: function(elem){
1891                         return "file" === elem.type;
1892                 },
1893                 password: function(elem){
1894                         return "password" === elem.type;
1895                 },
1896                 submit: function(elem){
1897                         return "submit" === elem.type;
1898                 },
1899                 image: function(elem){
1900                         return "image" === elem.type;
1901                 },
1902                 reset: function(elem){
1903                         return "reset" === elem.type;
1904                 },
1905                 button: function(elem){
1906                         return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
1907                 },
1908                 input: function(elem){
1909                         return /input|select|textarea|button/i.test(elem.nodeName);
1910                 }
1911         },
1912         setFilters: {
1913                 first: function(elem, i){
1914                         return i === 0;
1915                 },
1916                 last: function(elem, i, match, array){
1917                         return i === array.length - 1;
1918                 },
1919                 even: function(elem, i){
1920                         return i % 2 === 0;
1921                 },
1922                 odd: function(elem, i){
1923                         return i % 2 === 1;
1924                 },
1925                 lt: function(elem, i, match){
1926                         return i < match[3] - 0;
1927                 },
1928                 gt: function(elem, i, match){
1929                         return i > match[3] - 0;
1930                 },
1931                 nth: function(elem, i, match){
1932                         return match[3] - 0 == i;
1933                 },
1934                 eq: function(elem, i, match){
1935                         return match[3] - 0 == i;
1936                 }
1937         },
1938         filter: {
1939                 PSEUDO: function(elem, match, i, array){
1940                         var name = match[1], filter = Expr.filters[ name ];
1942                         if ( filter ) {
1943                                 return filter( elem, i, match, array );
1944                         } else if ( name === "contains" ) {
1945                                 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
1946                         } else if ( name === "not" ) {
1947                                 var not = match[3];
1949                                 for ( var i = 0, l = not.length; i < l; i++ ) {
1950                                         if ( not[i] === elem ) {
1951                                                 return false;
1952                                         }
1953                                 }
1955                                 return true;
1956                         }
1957                 },
1958                 CHILD: function(elem, match){
1959                         var type = match[1], node = elem;
1960                         switch (type) {
1961                                 case 'only':
1962                                 case 'first':
1963                                         while (node = node.previousSibling)  {
1964                                                 if ( node.nodeType === 1 ) return false;
1965                                         }
1966                                         if ( type == 'first') return true;
1967                                         node = elem;
1968                                 case 'last':
1969                                         while (node = node.nextSibling)  {
1970                                                 if ( node.nodeType === 1 ) return false;
1971                                         }
1972                                         return true;
1973                                 case 'nth':
1974                                         var first = match[2], last = match[3];
1976                                         if ( first == 1 && last == 0 ) {
1977                                                 return true;
1978                                         }
1979                                         
1980                                         var doneName = match[0],
1981                                                 parent = elem.parentNode;
1982         
1983                                         if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
1984                                                 var count = 0;
1985                                                 for ( node = parent.firstChild; node; node = node.nextSibling ) {
1986                                                         if ( node.nodeType === 1 ) {
1987                                                                 node.nodeIndex = ++count;
1988                                                         }
1989                                                 } 
1990                                                 parent.sizcache = doneName;
1991                                         }
1992                                         
1993                                         var diff = elem.nodeIndex - last;
1994                                         if ( first == 0 ) {
1995                                                 return diff == 0;
1996                                         } else {
1997                                                 return ( diff % first == 0 && diff / first >= 0 );
1998                                         }
1999                         }
2000                 },
2001                 ID: function(elem, match){
2002                         return elem.nodeType === 1 && elem.getAttribute("id") === match;
2003                 },
2004                 TAG: function(elem, match){
2005                         return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
2006                 },
2007                 CLASS: function(elem, match){
2008                         return (" " + (elem.className || elem.getAttribute("class")) + " ")
2009                                 .indexOf( match ) > -1;
2010                 },
2011                 ATTR: function(elem, match){
2012                         var name = match[1],
2013                                 result = Expr.attrHandle[ name ] ?
2014                                         Expr.attrHandle[ name ]( elem ) :
2015                                         elem[ name ] != null ?
2016                                                 elem[ name ] :
2017                                                 elem.getAttribute( name ),
2018                                 value = result + "",
2019                                 type = match[2],
2020                                 check = match[4];
2022                         return result == null ?
2023                                 type === "!=" :
2024                                 type === "=" ?
2025                                 value === check :
2026                                 type === "*=" ?
2027                                 value.indexOf(check) >= 0 :
2028                                 type === "~=" ?
2029                                 (" " + value + " ").indexOf(check) >= 0 :
2030                                 !check ?
2031                                 value && result !== false :
2032                                 type === "!=" ?
2033                                 value != check :
2034                                 type === "^=" ?
2035                                 value.indexOf(check) === 0 :
2036                                 type === "$=" ?
2037                                 value.substr(value.length - check.length) === check :
2038                                 type === "|=" ?
2039                                 value === check || value.substr(0, check.length + 1) === check + "-" :
2040                                 false;
2041                 },
2042                 POS: function(elem, match, i, array){
2043                         var name = match[2], filter = Expr.setFilters[ name ];
2045                         if ( filter ) {
2046                                 return filter( elem, i, match, array );
2047                         }
2048                 }
2049         }
2052 var origPOS = Expr.match.POS;
2054 for ( var type in Expr.match ) {
2055         Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
2058 var makeArray = function(array, results) {
2059         array = Array.prototype.slice.call( array );
2061         if ( results ) {
2062                 results.push.apply( results, array );
2063                 return results;
2064         }
2065         
2066         return array;
2069 // Perform a simple check to determine if the browser is capable of
2070 // converting a NodeList to an array using builtin methods.
2071 try {
2072         Array.prototype.slice.call( document.documentElement.childNodes );
2074 // Provide a fallback method if it does not work
2075 } catch(e){
2076         makeArray = function(array, results) {
2077                 var ret = results || [];
2079                 if ( toString.call(array) === "[object Array]" ) {
2080                         Array.prototype.push.apply( ret, array );
2081                 } else {
2082                         if ( typeof array.length === "number" ) {
2083                                 for ( var i = 0, l = array.length; i < l; i++ ) {
2084                                         ret.push( array[i] );
2085                                 }
2086                         } else {
2087                                 for ( var i = 0; array[i]; i++ ) {
2088                                         ret.push( array[i] );
2089                                 }
2090                         }
2091                 }
2093                 return ret;
2094         };
2097 var sortOrder;
2099 if ( document.documentElement.compareDocumentPosition ) {
2100         sortOrder = function( a, b ) {
2101                 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
2102                 if ( ret === 0 ) {
2103                         hasDuplicate = true;
2104                 }
2105                 return ret;
2106         };
2107 } else if ( "sourceIndex" in document.documentElement ) {
2108         sortOrder = function( a, b ) {
2109                 var ret = a.sourceIndex - b.sourceIndex;
2110                 if ( ret === 0 ) {
2111                         hasDuplicate = true;
2112                 }
2113                 return ret;
2114         };
2115 } else if ( document.createRange ) {
2116         sortOrder = function( a, b ) {
2117                 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
2118                 aRange.selectNode(a);
2119                 aRange.collapse(true);
2120                 bRange.selectNode(b);
2121                 bRange.collapse(true);
2122                 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
2123                 if ( ret === 0 ) {
2124                         hasDuplicate = true;
2125                 }
2126                 return ret;
2127         };
2130 // Check to see if the browser returns elements by name when
2131 // querying by getElementById (and provide a workaround)
2132 (function(){
2133         // We're going to inject a fake input element with a specified name
2134         var form = document.createElement("form"),
2135                 id = "script" + (new Date).getTime();
2136         form.innerHTML = "<input name='" + id + "'/>";
2138         // Inject it into the root element, check its status, and remove it quickly
2139         var root = document.documentElement;
2140         root.insertBefore( form, root.firstChild );
2142         // The workaround has to do additional checks after a getElementById
2143         // Which slows things down for other browsers (hence the branching)
2144         if ( !!document.getElementById( id ) ) {
2145                 Expr.find.ID = function(match, context, isXML){
2146                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
2147                                 var m = context.getElementById(match[1]);
2148                                 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
2149                         }
2150                 };
2152                 Expr.filter.ID = function(elem, match){
2153                         var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
2154                         return elem.nodeType === 1 && node && node.nodeValue === match;
2155                 };
2156         }
2158         root.removeChild( form );
2159 })();
2161 (function(){
2162         // Check to see if the browser returns only elements
2163         // when doing getElementsByTagName("*")
2165         // Create a fake element
2166         var div = document.createElement("div");
2167         div.appendChild( document.createComment("") );
2169         // Make sure no comments are found
2170         if ( div.getElementsByTagName("*").length > 0 ) {
2171                 Expr.find.TAG = function(match, context){
2172                         var results = context.getElementsByTagName(match[1]);
2174                         // Filter out possible comments
2175                         if ( match[1] === "*" ) {
2176                                 var tmp = [];
2178                                 for ( var i = 0; results[i]; i++ ) {
2179                                         if ( results[i].nodeType === 1 ) {
2180                                                 tmp.push( results[i] );
2181                                         }
2182                                 }
2184                                 results = tmp;
2185                         }
2187                         return results;
2188                 };
2189         }
2191         // Check to see if an attribute returns normalized href attributes
2192         div.innerHTML = "<a href='#'></a>";
2193         if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
2194                         div.firstChild.getAttribute("href") !== "#" ) {
2195                 Expr.attrHandle.href = function(elem){
2196                         return elem.getAttribute("href", 2);
2197                 };
2198         }
2199 })();
2201 if ( document.querySelectorAll ) (function(){
2202         var oldSizzle = Sizzle, div = document.createElement("div");
2203         div.innerHTML = "<p class='TEST'></p>";
2205         // Safari can't handle uppercase or unicode characters when
2206         // in quirks mode.
2207         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
2208                 return;
2209         }
2210         
2211         Sizzle = function(query, context, extra, seed){
2212                 context = context || document;
2214                 // Only use querySelectorAll on non-XML documents
2215                 // (ID selectors don't work in non-HTML documents)
2216                 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
2217                         try {
2218                                 return makeArray( context.querySelectorAll(query), extra );
2219                         } catch(e){}
2220                 }
2221                 
2222                 return oldSizzle(query, context, extra, seed);
2223         };
2225         Sizzle.find = oldSizzle.find;
2226         Sizzle.filter = oldSizzle.filter;
2227         Sizzle.selectors = oldSizzle.selectors;
2228         Sizzle.matches = oldSizzle.matches;
2229 })();
2231 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
2232         var div = document.createElement("div");
2233         div.innerHTML = "<div class='test e'></div><div class='test'></div>";
2235         // Opera can't find a second classname (in 9.6)
2236         if ( div.getElementsByClassName("e").length === 0 )
2237                 return;
2239         // Safari caches class attributes, doesn't catch changes (in 3.2)
2240         div.lastChild.className = "e";
2242         if ( div.getElementsByClassName("e").length === 1 )
2243                 return;
2245         Expr.order.splice(1, 0, "CLASS");
2246         Expr.find.CLASS = function(match, context, isXML) {
2247                 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
2248                         return context.getElementsByClassName(match[1]);
2249                 }
2250         };
2251 })();
2253 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2254         var sibDir = dir == "previousSibling" && !isXML;
2255         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2256                 var elem = checkSet[i];
2257                 if ( elem ) {
2258                         if ( sibDir && elem.nodeType === 1 ){
2259                                 elem.sizcache = doneName;
2260                                 elem.sizset = i;
2261                         }
2262                         elem = elem[dir];
2263                         var match = false;
2265                         while ( elem ) {
2266                                 if ( elem.sizcache === doneName ) {
2267                                         match = checkSet[elem.sizset];
2268                                         break;
2269                                 }
2271                                 if ( elem.nodeType === 1 && !isXML ){
2272                                         elem.sizcache = doneName;
2273                                         elem.sizset = i;
2274                                 }
2276                                 if ( elem.nodeName === cur ) {
2277                                         match = elem;
2278                                         break;
2279                                 }
2281                                 elem = elem[dir];
2282                         }
2284                         checkSet[i] = match;
2285                 }
2286         }
2289 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2290         var sibDir = dir == "previousSibling" && !isXML;
2291         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2292                 var elem = checkSet[i];
2293                 if ( elem ) {
2294                         if ( sibDir && elem.nodeType === 1 ) {
2295                                 elem.sizcache = doneName;
2296                                 elem.sizset = i;
2297                         }
2298                         elem = elem[dir];
2299                         var match = false;
2301                         while ( elem ) {
2302                                 if ( elem.sizcache === doneName ) {
2303                                         match = checkSet[elem.sizset];
2304                                         break;
2305                                 }
2307                                 if ( elem.nodeType === 1 ) {
2308                                         if ( !isXML ) {
2309                                                 elem.sizcache = doneName;
2310                                                 elem.sizset = i;
2311                                         }
2312                                         if ( typeof cur !== "string" ) {
2313                                                 if ( elem === cur ) {
2314                                                         match = true;
2315                                                         break;
2316                                                 }
2318                                         } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
2319                                                 match = elem;
2320                                                 break;
2321                                         }
2322                                 }
2324                                 elem = elem[dir];
2325                         }
2327                         checkSet[i] = match;
2328                 }
2329         }
2332 var contains = document.compareDocumentPosition ?  function(a, b){
2333         return a.compareDocumentPosition(b) & 16;
2334 } : function(a, b){
2335         return a !== b && (a.contains ? a.contains(b) : true);
2338 var isXML = function(elem){
2339         return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
2340                 !!elem.ownerDocument && isXML( elem.ownerDocument );
2343 var posProcess = function(selector, context){
2344         var tmpSet = [], later = "", match,
2345                 root = context.nodeType ? [context] : context;
2347         // Position selectors must be done after the filter
2348         // And so must :not(positional) so we move all PSEUDOs to the end
2349         while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
2350                 later += match[0];
2351                 selector = selector.replace( Expr.match.PSEUDO, "" );
2352         }
2354         selector = Expr.relative[selector] ? selector + "*" : selector;
2356         for ( var i = 0, l = root.length; i < l; i++ ) {
2357                 Sizzle( selector, root[i], tmpSet );
2358         }
2360         return Sizzle.filter( later, tmpSet );
2363 // EXPOSE
2364 jQuery.find = Sizzle;
2365 jQuery.filter = Sizzle.filter;
2366 jQuery.expr = Sizzle.selectors;
2367 jQuery.expr[":"] = jQuery.expr.filters;
2369 Sizzle.selectors.filters.hidden = function(elem){
2370         return elem.offsetWidth === 0 || elem.offsetHeight === 0;
2373 Sizzle.selectors.filters.visible = function(elem){
2374         return elem.offsetWidth > 0 || elem.offsetHeight > 0;
2377 Sizzle.selectors.filters.animated = function(elem){
2378         return jQuery.grep(jQuery.timers, function(fn){
2379                 return elem === fn.elem;
2380         }).length;
2383 jQuery.multiFilter = function( expr, elems, not ) {
2384         if ( not ) {
2385                 expr = ":not(" + expr + ")";
2386         }
2388         return Sizzle.matches(expr, elems);
2391 jQuery.dir = function( elem, dir ){
2392         var matched = [], cur = elem[dir];
2393         while ( cur && cur != document ) {
2394                 if ( cur.nodeType == 1 )
2395                         matched.push( cur );
2396                 cur = cur[dir];
2397         }
2398         return matched;
2401 jQuery.nth = function(cur, result, dir, elem){
2402         result = result || 1;
2403         var num = 0;
2405         for ( ; cur; cur = cur[dir] )
2406                 if ( cur.nodeType == 1 && ++num == result )
2407                         break;
2409         return cur;
2412 jQuery.sibling = function(n, elem){
2413         var r = [];
2415         for ( ; n; n = n.nextSibling ) {
2416                 if ( n.nodeType == 1 && n != elem )
2417                         r.push( n );
2418         }
2420         return r;
2423 return;
2425 window.Sizzle = Sizzle;
2427 })();
2429  * A number of helper functions used for managing events.
2430  * Many of the ideas behind this code originated from
2431  * Dean Edwards' addEvent library.
2432  */
2433 jQuery.event = {
2435         // Bind an event to an element
2436         // Original by Dean Edwards
2437         add: function(elem, types, handler, data) {
2438                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2439                         return;
2441                 // For whatever reason, IE has trouble passing the window object
2442                 // around, causing it to be cloned in the process
2443                 if ( elem.setInterval && elem != window )
2444                         elem = window;
2446                 // Make sure that the function being executed has a unique ID
2447                 if ( !handler.guid )
2448                         handler.guid = this.guid++;
2450                 // if data is passed, bind to handler
2451                 if ( data !== undefined ) {
2452                         // Create temporary function pointer to original handler
2453                         var fn = handler;
2455                         // Create unique handler function, wrapped around original handler
2456                         handler = this.proxy( fn );
2458                         // Store data in unique handler
2459                         handler.data = data;
2460                 }
2462                 // Init the element's event structure
2463                 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
2464                         handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
2465                                 // Handle the second event of a trigger and when
2466                                 // an event is called after a page has unloaded
2467                                 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2468                                         jQuery.event.handle.apply(arguments.callee.elem, arguments) :
2469                                         undefined;
2470                         });
2471                 // Add elem as a property of the handle function
2472                 // This is to prevent a memory leak with non-native
2473                 // event in IE.
2474                 handle.elem = elem;
2476                 // Handle multiple events separated by a space
2477                 // jQuery(...).bind("mouseover mouseout", fn);
2478                 jQuery.each(types.split(/\s+/), function(index, type) {
2479                         // Namespaced event handlers
2480                         var namespaces = type.split(".");
2481                         type = namespaces.shift();
2482                         handler.type = namespaces.slice().sort().join(".");
2484                         // Get the current list of functions bound to this event
2485                         var handlers = events[type];
2486                         
2487                         if ( jQuery.event.specialAll[type] )
2488                                 jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
2490                         // Init the event handler queue
2491                         if (!handlers) {
2492                                 handlers = events[type] = {};
2494                                 // Check for a special event handler
2495                                 // Only use addEventListener/attachEvent if the special
2496                                 // events handler returns false
2497                                 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
2498                                         // Bind the global event handler to the element
2499                                         if (elem.addEventListener)
2500                                                 elem.addEventListener(type, handle, false);
2501                                         else if (elem.attachEvent)
2502                                                 elem.attachEvent("on" + type, handle);
2503                                 }
2504                         }
2506                         // Add the function to the element's handler list
2507                         handlers[handler.guid] = handler;
2509                         // Keep track of which events have been used, for global triggering
2510                         jQuery.event.global[type] = true;
2511                 });
2513                 // Nullify elem to prevent memory leaks in IE
2514                 elem = null;
2515         },
2517         guid: 1,
2518         global: {},
2520         // Detach an event or set of events from an element
2521         remove: function(elem, types, handler) {
2522                 // don't do events on text and comment nodes
2523                 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2524                         return;
2526                 var events = jQuery.data(elem, "events"), ret, index;
2528                 if ( events ) {
2529                         // Unbind all events for the element
2530                         if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
2531                                 for ( var type in events )
2532                                         this.remove( elem, type + (types || "") );
2533                         else {
2534                                 // types is actually an event object here
2535                                 if ( types.type ) {
2536                                         handler = types.handler;
2537                                         types = types.type;
2538                                 }
2540                                 // Handle multiple events seperated by a space
2541                                 // jQuery(...).unbind("mouseover mouseout", fn);
2542                                 jQuery.each(types.split(/\s+/), function(index, type){
2543                                         // Namespaced event handlers
2544                                         var namespaces = type.split(".");
2545                                         type = namespaces.shift();
2546                                         var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2548                                         if ( events[type] ) {
2549                                                 // remove the given handler for the given type
2550                                                 if ( handler )
2551                                                         delete events[type][handler.guid];
2553                                                 // remove all handlers for the given type
2554                                                 else
2555                                                         for ( var handle in events[type] )
2556                                                                 // Handle the removal of namespaced events
2557                                                                 if ( namespace.test(events[type][handle].type) )
2558                                                                         delete events[type][handle];
2559                                                                         
2560                                                 if ( jQuery.event.specialAll[type] )
2561                                                         jQuery.event.specialAll[type].teardown.call(elem, namespaces);
2563                                                 // remove generic event handler if no more handlers exist
2564                                                 for ( ret in events[type] ) break;
2565                                                 if ( !ret ) {
2566                                                         if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
2567                                                                 if (elem.removeEventListener)
2568                                                                         elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
2569                                                                 else if (elem.detachEvent)
2570                                                                         elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
2571                                                         }
2572                                                         ret = null;
2573                                                         delete events[type];
2574                                                 }
2575                                         }
2576                                 });
2577                         }
2579                         // Remove the expando if it's no longer used
2580                         for ( ret in events ) break;
2581                         if ( !ret ) {
2582                                 var handle = jQuery.data( elem, "handle" );
2583                                 if ( handle ) handle.elem = null;
2584                                 jQuery.removeData( elem, "events" );
2585                                 jQuery.removeData( elem, "handle" );
2586                         }
2587                 }
2588         },
2590         // bubbling is internal
2591         trigger: function( event, data, elem, bubbling ) {
2592                 // Event object or event type
2593                 var type = event.type || event;
2595                 if( !bubbling ){
2596                         event = typeof event === "object" ?
2597                                 // jQuery.Event object
2598                                 event[expando] ? event :
2599                                 // Object literal
2600                                 jQuery.extend( jQuery.Event(type), event ) :
2601                                 // Just the event type (string)
2602                                 jQuery.Event(type);
2604                         if ( type.indexOf("!") >= 0 ) {
2605                                 event.type = type = type.slice(0, -1);
2606                                 event.exclusive = true;
2607                         }
2609                         // Handle a global trigger
2610                         if ( !elem ) {
2611                                 // Don't bubble custom events when global (to avoid too much overhead)
2612                                 event.stopPropagation();
2613                                 // Only trigger if we've ever bound an event for it
2614                                 if ( this.global[type] )
2615                                         jQuery.each( jQuery.cache, function(){
2616                                                 if ( this.events && this.events[type] )
2617                                                         jQuery.event.trigger( event, data, this.handle.elem );
2618                                         });
2619                         }
2621                         // Handle triggering a single element
2623                         // don't do events on text and comment nodes
2624                         if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
2625                                 return undefined;
2626                         
2627                         // Clean up in case it is reused
2628                         event.result = undefined;
2629                         event.target = elem;
2630                         
2631                         // Clone the incoming data, if any
2632                         data = jQuery.makeArray(data);
2633                         data.unshift( event );
2634                 }
2636                 event.currentTarget = elem;
2638                 // Trigger the event, it is assumed that "handle" is a function
2639                 var handle = jQuery.data(elem, "handle");
2640                 if ( handle )
2641                         handle.apply( elem, data );
2643                 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2644                 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2645                         event.result = false;
2647                 // Trigger the native events (except for clicks on links)
2648                 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2649                         this.triggered = true;
2650                         try {
2651                                 elem[ type ]();
2652                         // prevent IE from throwing an error for some hidden elements
2653                         } catch (e) {}
2654                 }
2656                 this.triggered = false;
2658                 if ( !event.isPropagationStopped() ) {
2659                         var parent = elem.parentNode || elem.ownerDocument;
2660                         if ( parent )
2661                                 jQuery.event.trigger(event, data, parent, true);
2662                 }
2663         },
2665         handle: function(event) {
2666                 // returned undefined or false
2667                 var all, handlers;
2669                 event = arguments[0] = jQuery.event.fix( event || window.event );
2670                 event.currentTarget = this;
2671                 
2672                 // Namespaced event handlers
2673                 var namespaces = event.type.split(".");
2674                 event.type = namespaces.shift();
2676                 // Cache this now, all = true means, any handler
2677                 all = !namespaces.length && !event.exclusive;
2678                 
2679                 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2681                 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2683                 for ( var j in handlers ) {
2684                         var handler = handlers[j];
2686                         // Filter the functions by class
2687                         if ( all || namespace.test(handler.type) ) {
2688                                 // Pass in a reference to the handler function itself
2689                                 // So that we can later remove it
2690                                 event.handler = handler;
2691                                 event.data = handler.data;
2693                                 var ret = handler.apply(this, arguments);
2695                                 if( ret !== undefined ){
2696                                         event.result = ret;
2697                                         if ( ret === false ) {
2698                                                 event.preventDefault();
2699                                                 event.stopPropagation();
2700                                         }
2701                                 }
2703                                 if( event.isImmediatePropagationStopped() )
2704                                         break;
2706                         }
2707                 }
2708         },
2710         props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
2712         fix: function(event) {
2713                 if ( event[expando] )
2714                         return event;
2716                 // store a copy of the original event object
2717                 // and "clone" to set read-only properties
2718                 var originalEvent = event;
2719                 event = jQuery.Event( originalEvent );
2721                 for ( var i = this.props.length, prop; i; ){
2722                         prop = this.props[ --i ];
2723                         event[ prop ] = originalEvent[ prop ];
2724                 }
2726                 // Fix target property, if necessary
2727                 if ( !event.target )
2728                         event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2730                 // check if target is a textnode (safari)
2731                 if ( event.target.nodeType == 3 )
2732                         event.target = event.target.parentNode;
2734                 // Add relatedTarget, if necessary
2735                 if ( !event.relatedTarget && event.fromElement )
2736                         event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2738                 // Calculate pageX/Y if missing and clientX/Y available
2739                 if ( event.pageX == null && event.clientX != null ) {
2740                         var doc = document.documentElement, body = document.body;
2741                         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2742                         event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2743                 }
2745                 // Add which for key events
2746                 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2747                         event.which = event.charCode || event.keyCode;
2749                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2750                 if ( !event.metaKey && event.ctrlKey )
2751                         event.metaKey = event.ctrlKey;
2753                 // Add which for click: 1 == left; 2 == middle; 3 == right
2754                 // Note: button is not normalized, so don't use it
2755                 if ( !event.which && event.button )
2756                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2758                 return event;
2759         },
2761         proxy: function( fn, proxy ){
2762                 proxy = proxy || function(){ return fn.apply(this, arguments); };
2763                 // Set the guid of unique handler to the same of original handler, so it can be removed
2764                 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2765                 // So proxy can be declared as an argument
2766                 return proxy;
2767         },
2769         special: {
2770                 ready: {
2771                         // Make sure the ready event is setup
2772                         setup: bindReady,
2773                         teardown: function() {}
2774                 }
2775         },
2776         
2777         specialAll: {
2778                 live: {
2779                         setup: function( selector, namespaces ){
2780                                 jQuery.event.add( this, namespaces[0], liveHandler );
2781                         },
2782                         teardown:  function( namespaces ){
2783                                 if ( namespaces.length ) {
2784                                         var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2785                                         
2786                                         jQuery.each( (jQuery.data(this, "events").live || {}), function(){
2787                                                 if ( name.test(this.type) )
2788                                                         remove++;
2789                                         });
2790                                         
2791                                         if ( remove < 1 )
2792                                                 jQuery.event.remove( this, namespaces[0], liveHandler );
2793                                 }
2794                         }
2795                 }
2796         }
2799 jQuery.Event = function( src ){
2800         // Allow instantiation without the 'new' keyword
2801         if( !this.preventDefault )
2802                 return new jQuery.Event(src);
2803         
2804         // Event object
2805         if( src && src.type ){
2806                 this.originalEvent = src;
2807                 this.type = src.type;
2808         // Event type
2809         }else
2810                 this.type = src;
2812         // timeStamp is buggy for some events on Firefox(#3843)
2813         // So we won't rely on the native value
2814         this.timeStamp = now();
2815         
2816         // Mark it as fixed
2817         this[expando] = true;
2820 function returnFalse(){
2821         return false;
2823 function returnTrue(){
2824         return true;
2827 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2828 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2829 jQuery.Event.prototype = {
2830         preventDefault: function() {
2831                 this.isDefaultPrevented = returnTrue;
2833                 var e = this.originalEvent;
2834                 if( !e )
2835                         return;
2836                 // if preventDefault exists run it on the original event
2837                 if (e.preventDefault)
2838                         e.preventDefault();
2839                 // otherwise set the returnValue property of the original event to false (IE)
2840                 e.returnValue = false;
2841         },
2842         stopPropagation: function() {
2843                 this.isPropagationStopped = returnTrue;
2845                 var e = this.originalEvent;
2846                 if( !e )
2847                         return;
2848                 // if stopPropagation exists run it on the original event
2849                 if (e.stopPropagation)
2850                         e.stopPropagation();
2851                 // otherwise set the cancelBubble property of the original event to true (IE)
2852                 e.cancelBubble = true;
2853         },
2854         stopImmediatePropagation:function(){
2855                 this.isImmediatePropagationStopped = returnTrue;
2856                 this.stopPropagation();
2857         },
2858         isDefaultPrevented: returnFalse,
2859         isPropagationStopped: returnFalse,
2860         isImmediatePropagationStopped: returnFalse
2862 // Checks if an event happened on an element within another element
2863 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2864 var withinElement = function(event) {
2865         // Check if mouse(over|out) are still within the same parent element
2866         var parent = event.relatedTarget;
2867         // Traverse up the tree
2868         while ( parent && parent != this )
2869                 try { parent = parent.parentNode; }
2870                 catch(e) { parent = this; }
2871         
2872         if( parent != this ){
2873                 // set the correct event type
2874                 event.type = event.data;
2875                 // handle event if we actually just moused on to a non sub-element
2876                 jQuery.event.handle.apply( this, arguments );
2877         }
2879         
2880 jQuery.each({ 
2881         mouseover: 'mouseenter', 
2882         mouseout: 'mouseleave'
2883 }, function( orig, fix ){
2884         jQuery.event.special[ fix ] = {
2885                 setup: function(){
2886                         jQuery.event.add( this, orig, withinElement, fix );
2887                 },
2888                 teardown: function(){
2889                         jQuery.event.remove( this, orig, withinElement );
2890                 }
2891         };                         
2894 jQuery.fn.extend({
2895         bind: function( type, data, fn ) {
2896                 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2897                         jQuery.event.add( this, type, fn || data, fn && data );
2898                 });
2899         },
2901         one: function( type, data, fn ) {
2902                 var one = jQuery.event.proxy( fn || data, function(event) {
2903                         jQuery(this).unbind(event, one);
2904                         return (fn || data).apply( this, arguments );
2905                 });
2906                 return this.each(function(){
2907                         jQuery.event.add( this, type, one, fn && data);
2908                 });
2909         },
2911         unbind: function( type, fn ) {
2912                 return this.each(function(){
2913                         jQuery.event.remove( this, type, fn );
2914                 });
2915         },
2917         trigger: function( type, data ) {
2918                 return this.each(function(){
2919                         jQuery.event.trigger( type, data, this );
2920                 });
2921         },
2923         triggerHandler: function( type, data ) {
2924                 if( this[0] ){
2925                         var event = jQuery.Event(type);
2926                         event.preventDefault();
2927                         event.stopPropagation();
2928                         jQuery.event.trigger( event, data, this[0] );
2929                         return event.result;
2930                 }               
2931         },
2933         toggle: function( fn ) {
2934                 // Save reference to arguments for access in closure
2935                 var args = arguments, i = 1;
2937                 // link all the functions, so any of them can unbind this click handler
2938                 while( i < args.length )
2939                         jQuery.event.proxy( fn, args[i++] );
2941                 return this.click( jQuery.event.proxy( fn, function(event) {
2942                         // Figure out which function to execute
2943                         this.lastToggle = ( this.lastToggle || 0 ) % i;
2945                         // Make sure that clicks stop
2946                         event.preventDefault();
2948                         // and execute the function
2949                         return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2950                 }));
2951         },
2953         hover: function(fnOver, fnOut) {
2954                 return this.mouseenter(fnOver).mouseleave(fnOut);
2955         },
2957         ready: function(fn) {
2958                 // Attach the listeners
2959                 bindReady();
2961                 // If the DOM is already ready
2962                 if ( jQuery.isReady )
2963                         // Execute the function immediately
2964                         fn.call( document, jQuery );
2966                 // Otherwise, remember the function for later
2967                 else
2968                         // Add the function to the wait list
2969                         jQuery.readyList.push( fn );
2971                 return this;
2972         },
2973         
2974         live: function( type, fn ){
2975                 var proxy = jQuery.event.proxy( fn );
2976                 proxy.guid += this.selector + type;
2978                 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
2980                 return this;
2981         },
2982         
2983         die: function( type, fn ){
2984                 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
2985                 return this;
2986         }
2989 function liveHandler( event ){
2990         var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
2991                 stop = true,
2992                 elems = [];
2994         jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
2995                 if ( check.test(fn.type) ) {
2996                         var elem = jQuery(event.target).closest(fn.data)[0];
2997                         if ( elem )
2998                                 elems.push({ elem: elem, fn: fn });
2999                 }
3000         });
3002         elems.sort(function(a,b) {
3003                 return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
3004         });
3005         
3006         jQuery.each(elems, function(){
3007                 if ( this.fn.call(this.elem, event, this.fn.data) === false )
3008                         return (stop = false);
3009         });
3011         return stop;
3014 function liveConvert(type, selector){
3015         return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
3018 jQuery.extend({
3019         isReady: false,
3020         readyList: [],
3021         // Handle when the DOM is ready
3022         ready: function() {
3023                 // Make sure that the DOM is not already loaded
3024                 if ( !jQuery.isReady ) {
3025                         // Remember that the DOM is ready
3026                         jQuery.isReady = true;
3028                         // If there are functions bound, to execute
3029                         if ( jQuery.readyList ) {
3030                                 // Execute all of them
3031                                 jQuery.each( jQuery.readyList, function(){
3032                                         this.call( document, jQuery );
3033                                 });
3035                                 // Reset the list of functions
3036                                 jQuery.readyList = null;
3037                         }
3039                         // Trigger any bound ready events
3040                         jQuery(document).triggerHandler("ready");
3041                 }
3042         }
3045 var readyBound = false;
3047 function bindReady(){
3048         if ( readyBound ) return;
3049         readyBound = true;
3051         // Mozilla, Opera and webkit nightlies currently support this event
3052         if ( document.addEventListener ) {
3053                 // Use the handy event callback
3054                 document.addEventListener( "DOMContentLoaded", function(){
3055                         document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
3056                         jQuery.ready();
3057                 }, false );
3059         // If IE event model is used
3060         } else if ( document.attachEvent ) {
3061                 // ensure firing before onload,
3062                 // maybe late but safe also for iframes
3063                 document.attachEvent("onreadystatechange", function(){
3064                         if ( document.readyState === "complete" ) {
3065                                 document.detachEvent( "onreadystatechange", arguments.callee );
3066                                 jQuery.ready();
3067                         }
3068                 });
3070                 // If IE and not an iframe
3071                 // continually check to see if the document is ready
3072                 if ( document.documentElement.doScroll && window == window.top ) (function(){
3073                         if ( jQuery.isReady ) return;
3075                         try {
3076                                 // If IE is used, use the trick by Diego Perini
3077                                 // http://javascript.nwbox.com/IEContentLoaded/
3078                                 document.documentElement.doScroll("left");
3079                         } catch( error ) {
3080                                 setTimeout( arguments.callee, 0 );
3081                                 return;
3082                         }
3084                         // and execute any waiting functions
3085                         jQuery.ready();
3086                 })();
3087         }
3089         // A fallback to window.onload, that will always work
3090         jQuery.event.add( window, "load", jQuery.ready );
3093 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
3094         "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
3095         "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
3097         // Handle event binding
3098         jQuery.fn[name] = function(fn){
3099                 return fn ? this.bind(name, fn) : this.trigger(name);
3100         };
3103 // Prevent memory leaks in IE
3104 // And prevent errors on refresh with events like mouseover in other browsers
3105 // Window isn't included so as not to unbind existing unload events
3106 jQuery( window ).bind( 'unload', function(){ 
3107         for ( var id in jQuery.cache )
3108                 // Skip the window
3109                 if ( id != 1 && jQuery.cache[ id ].handle )
3110                         jQuery.event.remove( jQuery.cache[ id ].handle.elem );
3111 }); 
3112 (function(){
3114         jQuery.support = {};
3116         var root = document.documentElement,
3117                 script = document.createElement("script"),
3118                 div = document.createElement("div"),
3119                 id = "script" + (new Date).getTime();
3121         div.style.display = "none";
3122         div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
3124         var all = div.getElementsByTagName("*"),
3125                 a = div.getElementsByTagName("a")[0];
3127         // Can't get basic test support
3128         if ( !all || !all.length || !a ) {
3129                 return;
3130         }
3132         jQuery.support = {
3133                 // IE strips leading whitespace when .innerHTML is used
3134                 leadingWhitespace: div.firstChild.nodeType == 3,
3135                 
3136                 // Make sure that tbody elements aren't automatically inserted
3137                 // IE will insert them into empty tables
3138                 tbody: !div.getElementsByTagName("tbody").length,
3139                 
3140                 // Make sure that you can get all elements in an <object> element
3141                 // IE 7 always returns no results
3142                 objectAll: !!div.getElementsByTagName("object")[0]
3143                         .getElementsByTagName("*").length,
3144                 
3145                 // Make sure that link elements get serialized correctly by innerHTML
3146                 // This requires a wrapper element in IE
3147                 htmlSerialize: !!div.getElementsByTagName("link").length,
3148                 
3149                 // Get the style information from getAttribute
3150                 // (IE uses .cssText insted)
3151                 style: /red/.test( a.getAttribute("style") ),
3152                 
3153                 // Make sure that URLs aren't manipulated
3154                 // (IE normalizes it by default)
3155                 hrefNormalized: a.getAttribute("href") === "/a",
3156                 
3157                 // Make sure that element opacity exists
3158                 // (IE uses filter instead)
3159                 opacity: a.style.opacity === "0.5",
3160                 
3161                 // Verify style float existence
3162                 // (IE uses styleFloat instead of cssFloat)
3163                 cssFloat: !!a.style.cssFloat,
3165                 // Will be defined later
3166                 scriptEval: false,
3167                 noCloneEvent: true,
3168                 boxModel: null
3169         };
3170         
3171         script.type = "text/javascript";
3172         try {
3173                 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
3174         } catch(e){}
3176         root.insertBefore( script, root.firstChild );
3177         
3178         // Make sure that the execution of code works by injecting a script
3179         // tag with appendChild/createTextNode
3180         // (IE doesn't support this, fails, and uses .text instead)
3181         if ( window[ id ] ) {
3182                 jQuery.support.scriptEval = true;
3183                 delete window[ id ];
3184         }
3186         root.removeChild( script );
3188         if ( div.attachEvent && div.fireEvent ) {
3189                 div.attachEvent("onclick", function(){
3190                         // Cloning a node shouldn't copy over any
3191                         // bound event handlers (IE does this)
3192                         jQuery.support.noCloneEvent = false;
3193                         div.detachEvent("onclick", arguments.callee);
3194                 });
3195                 div.cloneNode(true).fireEvent("onclick");
3196         }
3198         // Figure out if the W3C box model works as expected
3199         // document.body must exist before we can do this
3200         jQuery(function(){
3201                 var div = document.createElement("div");
3202                 div.style.width = div.style.paddingLeft = "1px";
3204                 document.body.appendChild( div );
3205                 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
3206                 document.body.removeChild( div ).style.display = 'none';
3207         });
3208 })();
3210 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
3212 jQuery.props = {
3213         "for": "htmlFor",
3214         "class": "className",
3215         "float": styleFloat,
3216         cssFloat: styleFloat,
3217         styleFloat: styleFloat,
3218         readonly: "readOnly",
3219         maxlength: "maxLength",
3220         cellspacing: "cellSpacing",
3221         rowspan: "rowSpan",
3222         tabindex: "tabIndex"
3224 jQuery.fn.extend({
3225         // Keep a copy of the old load
3226         _load: jQuery.fn.load,
3228         load: function( url, params, callback ) {
3229                 if ( typeof url !== "string" )
3230                         return this._load( url );
3232                 var off = url.indexOf(" ");
3233                 if ( off >= 0 ) {
3234                         var selector = url.slice(off, url.length);
3235                         url = url.slice(0, off);
3236                 }
3238                 // Default to a GET request
3239                 var type = "GET";
3241                 // If the second parameter was provided
3242                 if ( params )
3243                         // If it's a function
3244                         if ( jQuery.isFunction( params ) ) {
3245                                 // We assume that it's the callback
3246                                 callback = params;
3247                                 params = null;
3249                         // Otherwise, build a param string
3250                         } else if( typeof params === "object" ) {
3251                                 params = jQuery.param( params );
3252                                 type = "POST";
3253                         }
3255                 var self = this;
3257                 // Request the remote document
3258                 jQuery.ajax({
3259                         url: url,
3260                         type: type,
3261                         dataType: "html",
3262                         data: params,
3263                         complete: function(res, status){
3264                                 // If successful, inject the HTML into all the matched elements
3265                                 if ( status == "success" || status == "notmodified" )
3266                                         // See if a selector was specified
3267                                         self.html( selector ?
3268                                                 // Create a dummy div to hold the results
3269                                                 jQuery("<div/>")
3270                                                         // inject the contents of the document in, removing the scripts
3271                                                         // to avoid any 'Permission Denied' errors in IE
3272                                                         .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
3274                                                         // Locate the specified elements
3275                                                         .find(selector) :
3277                                                 // If not, just inject the full result
3278                                                 res.responseText );
3280                                 if( callback )
3281                                         self.each( callback, [res.responseText, status, res] );
3282                         }
3283                 });
3284                 return this;
3285         },
3287         serialize: function() {
3288                 return jQuery.param(this.serializeArray());
3289         },
3290         serializeArray: function() {
3291                 return this.map(function(){
3292                         return this.elements ? jQuery.makeArray(this.elements) : this;
3293                 })
3294                 .filter(function(){
3295                         return this.name && !this.disabled &&
3296                                 (this.checked || /select|textarea/i.test(this.nodeName) ||
3297                                         /text|hidden|password|search/i.test(this.type));
3298                 })
3299                 .map(function(i, elem){
3300                         var val = jQuery(this).val();
3301                         return val == null ? null :
3302                                 jQuery.isArray(val) ?
3303                                         jQuery.map( val, function(val, i){
3304                                                 return {name: elem.name, value: val};
3305                                         }) :
3306                                         {name: elem.name, value: val};
3307                 }).get();
3308         }
3311 // Attach a bunch of functions for handling common AJAX events
3312 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
3313         jQuery.fn[o] = function(f){
3314                 return this.bind(o, f);
3315         };
3318 var jsc = now();
3320 jQuery.extend({
3321   
3322         get: function( url, data, callback, type ) {
3323                 // shift arguments if data argument was ommited
3324                 if ( jQuery.isFunction( data ) ) {
3325                         callback = data;
3326                         data = null;
3327                 }
3329                 return jQuery.ajax({
3330                         type: "GET",
3331                         url: url,
3332                         data: data,
3333                         success: callback,
3334                         dataType: type
3335                 });
3336         },
3338         getScript: function( url, callback ) {
3339                 return jQuery.get(url, null, callback, "script");
3340         },
3342         getJSON: function( url, data, callback ) {
3343                 return jQuery.get(url, data, callback, "json");
3344         },
3346         post: function( url, data, callback, type ) {
3347                 if ( jQuery.isFunction( data ) ) {
3348                         callback = data;
3349                         data = {};
3350                 }
3352                 return jQuery.ajax({
3353                         type: "POST",
3354                         url: url,
3355                         data: data,
3356                         success: callback,
3357                         dataType: type
3358                 });
3359         },
3361         ajaxSetup: function( settings ) {
3362                 jQuery.extend( jQuery.ajaxSettings, settings );
3363         },
3365         ajaxSettings: {
3366                 url: location.href,
3367                 global: true,
3368                 type: "GET",
3369                 contentType: "application/x-www-form-urlencoded",
3370                 processData: true,
3371                 async: true,
3372                 /*
3373                 timeout: 0,
3374                 data: null,
3375                 username: null,
3376                 password: null,
3377                 */
3378                 // Create the request object; Microsoft failed to properly
3379                 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
3380                 // This function can be overriden by calling jQuery.ajaxSetup
3381                 xhr:function(){
3382                         return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
3383                 },
3384                 accepts: {
3385                         xml: "application/xml, text/xml",
3386                         html: "text/html",
3387                         script: "text/javascript, application/javascript",
3388                         json: "application/json, text/javascript",
3389                         text: "text/plain",
3390                         _default: "*/*"
3391                 }
3392         },
3394         // Last-Modified header cache for next request
3395         lastModified: {},
3397         ajax: function( s ) {
3398                 // Extend the settings, but re-extend 's' so that it can be
3399                 // checked again later (in the test suite, specifically)
3400                 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
3402                 var jsonp, jsre = /=\?(&|$)/g, status, data,
3403                         type = s.type.toUpperCase();
3405                 // convert data if not already a string
3406                 if ( s.data && s.processData && typeof s.data !== "string" )
3407                         s.data = jQuery.param(s.data);
3409                 // Handle JSONP Parameter Callbacks
3410                 if ( s.dataType == "jsonp" ) {
3411                         if ( type == "GET" ) {
3412                                 if ( !s.url.match(jsre) )
3413                                         s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
3414                         } else if ( !s.data || !s.data.match(jsre) )
3415                                 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
3416                         s.dataType = "json";
3417                 }
3419                 // Build temporary JSONP function
3420                 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
3421                         jsonp = "jsonp" + jsc++;
3423                         // Replace the =? sequence both in the query string and the data
3424                         if ( s.data )
3425                                 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
3426                         s.url = s.url.replace(jsre, "=" + jsonp + "$1");
3428                         // We need to make sure
3429                         // that a JSONP style response is executed properly
3430                         s.dataType = "script";
3432                         // Handle JSONP-style loading
3433                         window[ jsonp ] = function(tmp){
3434                                 data = tmp;
3435                                 success();
3436                                 complete();
3437                                 // Garbage collect
3438                                 window[ jsonp ] = undefined;
3439                                 try{ delete window[ jsonp ]; } catch(e){}
3440                                 if ( head )
3441                                         head.removeChild( script );
3442                         };
3443                 }
3445                 if ( s.dataType == "script" && s.cache == null )
3446                         s.cache = false;
3448                 if ( s.cache === false && type == "GET" ) {
3449                         var ts = now();
3450                         // try replacing _= if it is there
3451                         var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
3452                         // if nothing was replaced, add timestamp to the end
3453                         s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
3454                 }
3456                 // If data is available, append data to url for get requests
3457                 if ( s.data && type == "GET" ) {
3458                         s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
3460                         // IE likes to send both get and post data, prevent this
3461                         s.data = null;
3462                 }
3464                 // Watch for a new set of requests
3465                 if ( s.global && ! jQuery.active++ )
3466                         jQuery.event.trigger( "ajaxStart" );
3468                 // Matches an absolute URL, and saves the domain
3469                 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
3471                 // If we're requesting a remote document
3472                 // and trying to load JSON or Script with a GET
3473                 if ( s.dataType == "script" && type == "GET" && parts
3474                         && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
3476                         var head = document.getElementsByTagName("head")[0];
3477                         var script = document.createElement("script");
3478                         script.src = s.url;
3479                         if (s.scriptCharset)
3480                                 script.charset = s.scriptCharset;
3482                         // Handle Script loading
3483                         if ( !jsonp ) {
3484                                 var done = false;
3486                                 // Attach handlers for all browsers
3487                                 script.onload = script.onreadystatechange = function(){
3488                                         if ( !done && (!this.readyState ||
3489                                                         this.readyState == "loaded" || this.readyState == "complete") ) {
3490                                                 done = true;
3491                                                 success();
3492                                                 complete();
3494                                                 // Handle memory leak in IE
3495                                                 script.onload = script.onreadystatechange = null;
3496                                                 head.removeChild( script );
3497                                         }
3498                                 };
3499                         }
3501                         head.appendChild(script);
3503                         // We handle everything using the script element injection
3504                         return undefined;
3505                 }
3507                 var requestDone = false;
3509                 // Create the request object
3510                 var xhr = s.xhr();
3512                 // Open the socket
3513                 // Passing null username, generates a login popup on Opera (#2865)
3514                 if( s.username )
3515                         xhr.open(type, s.url, s.async, s.username, s.password);
3516                 else
3517                         xhr.open(type, s.url, s.async);
3519                 // Need an extra try/catch for cross domain requests in Firefox 3
3520                 try {
3521                         // Set the correct header, if data is being sent
3522                         if ( s.data )
3523                                 xhr.setRequestHeader("Content-Type", s.contentType);
3525                         // Set the If-Modified-Since header, if ifModified mode.
3526                         if ( s.ifModified )
3527                                 xhr.setRequestHeader("If-Modified-Since",
3528                                         jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
3530                         // Set header so the called script knows that it's an XMLHttpRequest
3531                         xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
3533                         // Set the Accepts header for the server, depending on the dataType
3534                         xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
3535                                 s.accepts[ s.dataType ] + ", */*" :
3536                                 s.accepts._default );
3537                 } catch(e){}
3539                 // Allow custom headers/mimetypes and early abort
3540                 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
3541                         // Handle the global AJAX counter
3542                         if ( s.global && ! --jQuery.active )
3543                                 jQuery.event.trigger( "ajaxStop" );
3544                         // close opended socket
3545                         xhr.abort();
3546                         return false;
3547                 }
3549                 if ( s.global )
3550                         jQuery.event.trigger("ajaxSend", [xhr, s]);
3552                 // Wait for a response to come back
3553                 var onreadystatechange = function(isTimeout){
3554                         // The request was aborted, clear the interval and decrement jQuery.active
3555                         if (xhr.readyState == 0) {
3556                                 if (ival) {
3557                                         // clear poll interval
3558                                         clearInterval(ival);
3559                                         ival = null;
3560                                         // Handle the global AJAX counter
3561                                         if ( s.global && ! --jQuery.active )
3562                                                 jQuery.event.trigger( "ajaxStop" );
3563                                 }
3564                         // The transfer is complete and the data is available, or the request timed out
3565                         } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
3566                                 requestDone = true;
3568                                 // clear poll interval
3569                                 if (ival) {
3570                                         clearInterval(ival);
3571                                         ival = null;
3572                                 }
3574                                 status = isTimeout == "timeout" ? "timeout" :
3575                                         !jQuery.httpSuccess( xhr ) ? "error" :
3576                                         s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
3577                                         "success";
3579                                 if ( status == "success" ) {
3580                                         // Watch for, and catch, XML document parse errors
3581                                         try {
3582                                                 // process the data (runs the xml through httpData regardless of callback)
3583                                                 data = jQuery.httpData( xhr, s.dataType, s );
3584                                         } catch(e) {
3585                                                 status = "parsererror";
3586                                         }
3587                                 }
3589                                 // Make sure that the request was successful or notmodified
3590                                 if ( status == "success" ) {
3591                                         // Cache Last-Modified header, if ifModified mode.
3592                                         var modRes;
3593                                         try {
3594                                                 modRes = xhr.getResponseHeader("Last-Modified");
3595                                         } catch(e) {} // swallow exception thrown by FF if header is not available
3597                                         if ( s.ifModified && modRes )
3598                                                 jQuery.lastModified[s.url] = modRes;
3600                                         // JSONP handles its own success callback
3601                                         if ( !jsonp )
3602                                                 success();
3603                                 } else
3604                                         jQuery.handleError(s, xhr, status);
3606                                 // Fire the complete handlers
3607                                 complete();
3609                                 if ( isTimeout )
3610                                         xhr.abort();
3612                                 // Stop memory leaks
3613                                 if ( s.async )
3614                                         xhr = null;
3615                         }
3616                 };
3618                 if ( s.async ) {
3619                         // don't attach the handler to the request, just poll it instead
3620                         var ival = setInterval(onreadystatechange, 13);
3622                         // Timeout checker
3623                         if ( s.timeout > 0 )
3624                                 setTimeout(function(){
3625                                         // Check to see if the request is still happening
3626                                         if ( xhr && !requestDone )
3627                                                 onreadystatechange( "timeout" );
3628                                 }, s.timeout);
3629                 }
3631                 // Send the data
3632                 try {
3633                         xhr.send(s.data);
3634                 } catch(e) {
3635                         jQuery.handleError(s, xhr, null, e);
3636                 }
3638                 // firefox 1.5 doesn't fire statechange for sync requests
3639                 if ( !s.async )
3640                         onreadystatechange();
3642                 function success(){
3643                         // If a local callback was specified, fire it and pass it the data
3644                         if ( s.success )
3645                                 s.success( data, status );
3647                         // Fire the global callback
3648                         if ( s.global )
3649                                 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
3650                 }
3652                 function complete(){
3653                         // Process result
3654                         if ( s.complete )
3655                                 s.complete(xhr, status);
3657                         // The request was completed
3658                         if ( s.global )
3659                                 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
3661                         // Handle the global AJAX counter
3662                         if ( s.global && ! --jQuery.active )
3663                                 jQuery.event.trigger( "ajaxStop" );
3664                 }
3666                 // return XMLHttpRequest to allow aborting the request etc.
3667                 return xhr;
3668         },
3670         handleError: function( s, xhr, status, e ) {
3671                 // If a local callback was specified, fire it
3672                 if ( s.error ) s.error( xhr, status, e );
3674                 // Fire the global callback
3675                 if ( s.global )
3676                         jQuery.event.trigger( "ajaxError", [xhr, s, e] );
3677         },
3679         // Counter for holding the number of active queries
3680         active: 0,
3682         // Determines if an XMLHttpRequest was successful or not
3683         httpSuccess: function( xhr ) {
3684                 try {
3685                         // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
3686                         return !xhr.status && location.protocol == "file:" ||
3687                                 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
3688                 } catch(e){}
3689                 return false;
3690         },
3692         // Determines if an XMLHttpRequest returns NotModified
3693         httpNotModified: function( xhr, url ) {
3694                 try {
3695                         var xhrRes = xhr.getResponseHeader("Last-Modified");
3697                         // Firefox always returns 200. check Last-Modified date
3698                         return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
3699                 } catch(e){}
3700                 return false;
3701         },
3703         httpData: function( xhr, type, s ) {
3704                 var ct = xhr.getResponseHeader("content-type"),
3705                         xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
3706                         data = xml ? xhr.responseXML : xhr.responseText;
3708                 if ( xml && data.documentElement.tagName == "parsererror" )
3709                         throw "parsererror";
3710                         
3711                 // Allow a pre-filtering function to sanitize the response
3712                 // s != null is checked to keep backwards compatibility
3713                 if( s && s.dataFilter )
3714                         data = s.dataFilter( data, type );
3716                 // The filter can actually parse the response
3717                 if( typeof data === "string" ){
3719                         // If the type is "script", eval it in global context
3720                         if ( type == "script" )
3721                                 jQuery.globalEval( data );
3723                         // Get the JavaScript object, if JSON is used.
3724                         if ( type == "json" )
3725                                 data = window["eval"]("(" + data + ")");
3726                 }
3727                 
3728                 return data;
3729         },
3731         // Serialize an array of form elements or a set of
3732         // key/values into a query string
3733         param: function( a ) {
3734                 var s = [ ];
3736                 function add( key, value ){
3737                         s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
3738                 };
3740                 // If an array was passed in, assume that it is an array
3741                 // of form elements
3742                 if ( jQuery.isArray(a) || a.jquery )
3743                         // Serialize the form elements
3744                         jQuery.each( a, function(){
3745                                 add( this.name, this.value );
3746                         });
3748                 // Otherwise, assume that it's an object of key/value pairs
3749                 else
3750                         // Serialize the key/values
3751                         for ( var j in a )
3752                                 // If the value is an array then the key names need to be repeated
3753                                 if ( jQuery.isArray(a[j]) )
3754                                         jQuery.each( a[j], function(){
3755                                                 add( j, this );
3756                                         });
3757                                 else
3758                                         add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
3760                 // Return the resulting serialization
3761                 return s.join("&").replace(/%20/g, "+");
3762         }
3765 var elemdisplay = {},
3766         timerId,
3767         fxAttrs = [
3768                 // height animations
3769                 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3770                 // width animations
3771                 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3772                 // opacity animations
3773                 [ "opacity" ]
3774         ];
3776 function genFx( type, num ){
3777         var obj = {};
3778         jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3779                 obj[ this ] = type;
3780         });
3781         return obj;
3784 jQuery.fn.extend({
3785         show: function(speed,callback){
3786                 if ( speed ) {
3787                         return this.animate( genFx("show", 3), speed, callback);
3788                 } else {
3789                         for ( var i = 0, l = this.length; i < l; i++ ){
3790                                 var old = jQuery.data(this[i], "olddisplay");
3791                                 
3792                                 this[i].style.display = old || "";
3793                                 
3794                                 if ( jQuery.css(this[i], "display") === "none" ) {
3795                                         var tagName = this[i].tagName, display;
3796                                         
3797                                         if ( elemdisplay[ tagName ] ) {
3798                                                 display = elemdisplay[ tagName ];
3799                                         } else {
3800                                                 var elem = jQuery("<" + tagName + " />").appendTo("body");
3801                                                 
3802                                                 display = elem.css("display");
3803                                                 if ( display === "none" )
3804                                                         display = "block";
3805                                                 
3806                                                 elem.remove();
3807                                                 
3808                                                 elemdisplay[ tagName ] = display;
3809                                         }
3810                                         
3811                                         jQuery.data(this[i], "olddisplay", display);
3812                                 }
3813                         }
3815                         // Set the display of the elements in a second loop
3816                         // to avoid the constant reflow
3817                         for ( var i = 0, l = this.length; i < l; i++ ){
3818                                 this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
3819                         }
3820                         
3821                         return this;
3822                 }
3823         },
3825         hide: function(speed,callback){
3826                 if ( speed ) {
3827                         return this.animate( genFx("hide", 3), speed, callback);
3828                 } else {
3829                         for ( var i = 0, l = this.length; i < l; i++ ){
3830                                 var old = jQuery.data(this[i], "olddisplay");
3831                                 if ( !old && old !== "none" )
3832                                         jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3833                         }
3835                         // Set the display of the elements in a second loop
3836                         // to avoid the constant reflow
3837                         for ( var i = 0, l = this.length; i < l; i++ ){
3838                                 this[i].style.display = "none";
3839                         }
3841                         return this;
3842                 }
3843         },
3845         // Save the old toggle function
3846         _toggle: jQuery.fn.toggle,
3848         toggle: function( fn, fn2 ){
3849                 var bool = typeof fn === "boolean";
3851                 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3852                         this._toggle.apply( this, arguments ) :
3853                         fn == null || bool ?
3854                                 this.each(function(){
3855                                         var state = bool ? fn : jQuery(this).is(":hidden");
3856                                         jQuery(this)[ state ? "show" : "hide" ]();
3857                                 }) :
3858                                 this.animate(genFx("toggle", 3), fn, fn2);
3859         },
3861         fadeTo: function(speed,to,callback){
3862                 return this.animate({opacity: to}, speed, callback);
3863         },
3865         animate: function( prop, speed, easing, callback ) {
3866                 var optall = jQuery.speed(speed, easing, callback);
3868                 return this[ optall.queue === false ? "each" : "queue" ](function(){
3869                 
3870                         var opt = jQuery.extend({}, optall), p,
3871                                 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3872                                 self = this;
3873         
3874                         for ( p in prop ) {
3875                                 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3876                                         return opt.complete.call(this);
3878                                 if ( ( p == "height" || p == "width" ) && this.style ) {
3879                                         // Store display property
3880                                         opt.display = jQuery.css(this, "display");
3882                                         // Make sure that nothing sneaks out
3883                                         opt.overflow = this.style.overflow;
3884                                 }
3885                         }
3887                         if ( opt.overflow != null )
3888                                 this.style.overflow = "hidden";
3890                         opt.curAnim = jQuery.extend({}, prop);
3892                         jQuery.each( prop, function(name, val){
3893                                 var e = new jQuery.fx( self, opt, name );
3895                                 if ( /toggle|show|hide/.test(val) )
3896                                         e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3897                                 else {
3898                                         var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3899                                                 start = e.cur(true) || 0;
3901                                         if ( parts ) {
3902                                                 var end = parseFloat(parts[2]),
3903                                                         unit = parts[3] || "px";
3905                                                 // We need to compute starting value
3906                                                 if ( unit != "px" ) {
3907                                                         self.style[ name ] = (end || 1) + unit;
3908                                                         start = ((end || 1) / e.cur(true)) * start;
3909                                                         self.style[ name ] = start + unit;
3910                                                 }
3912                                                 // If a +=/-= token was provided, we're doing a relative animation
3913                                                 if ( parts[1] )
3914                                                         end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3916                                                 e.custom( start, end, unit );
3917                                         } else
3918                                                 e.custom( start, val, "" );
3919                                 }
3920                         });
3922                         // For JS strict compliance
3923                         return true;
3924                 });
3925         },
3927         stop: function(clearQueue, gotoEnd){
3928                 var timers = jQuery.timers;
3930                 if (clearQueue)
3931                         this.queue([]);
3933                 this.each(function(){
3934                         // go in reverse order so anything added to the queue during the loop is ignored
3935                         for ( var i = timers.length - 1; i >= 0; i-- )
3936                                 if ( timers[i].elem == this ) {
3937                                         if (gotoEnd)
3938                                                 // force the next step to be the last
3939                                                 timers[i](true);
3940                                         timers.splice(i, 1);
3941                                 }
3942                 });
3944                 // start the next in the queue if the last step wasn't forced
3945                 if (!gotoEnd)
3946                         this.dequeue();
3948                 return this;
3949         }
3953 // Generate shortcuts for custom animations
3954 jQuery.each({
3955         slideDown: genFx("show", 1),
3956         slideUp: genFx("hide", 1),
3957         slideToggle: genFx("toggle", 1),
3958         fadeIn: { opacity: "show" },
3959         fadeOut: { opacity: "hide" }
3960 }, function( name, props ){
3961         jQuery.fn[ name ] = function( speed, callback ){
3962                 return this.animate( props, speed, callback );
3963         };
3966 jQuery.extend({
3968         speed: function(speed, easing, fn) {
3969                 var opt = typeof speed === "object" ? speed : {
3970                         complete: fn || !fn && easing ||
3971                                 jQuery.isFunction( speed ) && speed,
3972                         duration: speed,
3973                         easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
3974                 };
3976                 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
3977                         jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
3979                 // Queueing
3980                 opt.old = opt.complete;
3981                 opt.complete = function(){
3982                         if ( opt.queue !== false )
3983                                 jQuery(this).dequeue();
3984                         if ( jQuery.isFunction( opt.old ) )
3985                                 opt.old.call( this );
3986                 };
3988                 return opt;
3989         },
3991         easing: {
3992                 linear: function( p, n, firstNum, diff ) {
3993                         return firstNum + diff * p;
3994                 },
3995                 swing: function( p, n, firstNum, diff ) {
3996                         return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3997                 }
3998         },
4000         timers: [],
4002         fx: function( elem, options, prop ){
4003                 this.options = options;
4004                 this.elem = elem;
4005                 this.prop = prop;
4007                 if ( !options.orig )
4008                         options.orig = {};
4009         }
4013 jQuery.fx.prototype = {
4015         // Simple function for setting a style value
4016         update: function(){
4017                 if ( this.options.step )
4018                         this.options.step.call( this.elem, this.now, this );
4020                 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
4022                 // Set display property to block for height/width animations
4023                 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
4024                         this.elem.style.display = "block";
4025         },
4027         // Get the current size
4028         cur: function(force){
4029                 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
4030                         return this.elem[ this.prop ];
4032                 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
4033                 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
4034         },
4036         // Start an animation from one number to another
4037         custom: function(from, to, unit){
4038                 this.startTime = now();
4039                 this.start = from;
4040                 this.end = to;
4041                 this.unit = unit || this.unit || "px";
4042                 this.now = this.start;
4043                 this.pos = this.state = 0;
4045                 var self = this;
4046                 function t(gotoEnd){
4047                         return self.step(gotoEnd);
4048                 }
4050                 t.elem = this.elem;
4052                 if ( t() && jQuery.timers.push(t) && !timerId ) {
4053                         timerId = setInterval(function(){
4054                                 var timers = jQuery.timers;
4056                                 for ( var i = 0; i < timers.length; i++ )
4057                                         if ( !timers[i]() )
4058                                                 timers.splice(i--, 1);
4060                                 if ( !timers.length ) {
4061                                         clearInterval( timerId );
4062                                         timerId = undefined;
4063                                 }
4064                         }, 13);
4065                 }
4066         },
4068         // Simple 'show' function
4069         show: function(){
4070                 // Remember where we started, so that we can go back to it later
4071                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
4072                 this.options.show = true;
4074                 // Begin the animation
4075                 // Make sure that we start at a small width/height to avoid any
4076                 // flash of content
4077                 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
4079                 // Start by showing the element
4080                 jQuery(this.elem).show();
4081         },
4083         // Simple 'hide' function
4084         hide: function(){
4085                 // Remember where we started, so that we can go back to it later
4086                 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
4087                 this.options.hide = true;
4089                 // Begin the animation
4090                 this.custom(this.cur(), 0);
4091         },
4093         // Each step of an animation
4094         step: function(gotoEnd){
4095                 var t = now();
4097                 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
4098                         this.now = this.end;
4099                         this.pos = this.state = 1;
4100                         this.update();
4102                         this.options.curAnim[ this.prop ] = true;
4104                         var done = true;
4105                         for ( var i in this.options.curAnim )
4106                                 if ( this.options.curAnim[i] !== true )
4107                                         done = false;
4109                         if ( done ) {
4110                                 if ( this.options.display != null ) {
4111                                         // Reset the overflow
4112                                         this.elem.style.overflow = this.options.overflow;
4114                                         // Reset the display
4115                                         this.elem.style.display = this.options.display;
4116                                         if ( jQuery.css(this.elem, "display") == "none" )
4117                                                 this.elem.style.display = "block";
4118                                 }
4120                                 // Hide the element if the "hide" operation was done
4121                                 if ( this.options.hide )
4122                                         jQuery(this.elem).hide();
4124                                 // Reset the properties, if the item has been hidden or shown
4125                                 if ( this.options.hide || this.options.show )
4126                                         for ( var p in this.options.curAnim )
4127                                                 jQuery.attr(this.elem.style, p, this.options.orig[p]);
4128                                         
4129                                 // Execute the complete function
4130                                 this.options.complete.call( this.elem );
4131                         }
4133                         return false;
4134                 } else {
4135                         var n = t - this.startTime;
4136                         this.state = n / this.options.duration;
4138                         // Perform the easing function, defaults to swing
4139                         this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
4140                         this.now = this.start + ((this.end - this.start) * this.pos);
4142                         // Perform the next step of the animation
4143                         this.update();
4144                 }
4146                 return true;
4147         }
4151 jQuery.extend( jQuery.fx, {
4152         speeds:{
4153                 slow: 600,
4154                 fast: 200,
4155                 // Default speed
4156                 _default: 400
4157         },
4158         step: {
4160                 opacity: function(fx){
4161                         jQuery.attr(fx.elem.style, "opacity", fx.now);
4162                 },
4164                 _default: function(fx){
4165                         if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
4166                                 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
4167                         else
4168                                 fx.elem[ fx.prop ] = fx.now;
4169                 }
4170         }
4172 if ( document.documentElement["getBoundingClientRect"] )
4173         jQuery.fn.offset = function() {
4174                 if ( !this[0] ) return { top: 0, left: 0 };
4175                 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4176                 var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
4177                         clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
4178                         top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
4179                         left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
4180                 return { top: top, left: left };
4181         };
4182 else 
4183         jQuery.fn.offset = function() {
4184                 if ( !this[0] ) return { top: 0, left: 0 };
4185                 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4186                 jQuery.offset.initialized || jQuery.offset.initialize();
4188                 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
4189                         doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
4190                         body = doc.body, defaultView = doc.defaultView,
4191                         prevComputedStyle = defaultView.getComputedStyle(elem, null),
4192                         top = elem.offsetTop, left = elem.offsetLeft;
4194                 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
4195                         computedStyle = defaultView.getComputedStyle(elem, null);
4196                         top -= elem.scrollTop, left -= elem.scrollLeft;
4197                         if ( elem === offsetParent ) {
4198                                 top += elem.offsetTop, left += elem.offsetLeft;
4199                                 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
4200                                         top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
4201                                         left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4202                                 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
4203                         }
4204                         if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
4205                                 top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
4206                                 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4207                         prevComputedStyle = computedStyle;
4208                 }
4210                 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
4211                         top  += body.offsetTop,
4212                         left += body.offsetLeft;
4214                 if ( prevComputedStyle.position === "fixed" )
4215                         top  += Math.max(docElem.scrollTop, body.scrollTop),
4216                         left += Math.max(docElem.scrollLeft, body.scrollLeft);
4218                 return { top: top, left: left };
4219         };
4221 jQuery.offset = {
4222         initialize: function() {
4223                 if ( this.initialized ) return;
4224                 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
4225                         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>';
4227                 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
4228                 for ( prop in rules ) container.style[prop] = rules[prop];
4230                 container.innerHTML = html;
4231                 body.insertBefore(container, body.firstChild);
4232                 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
4234                 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
4235                 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
4237                 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
4238                 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
4240                 body.style.marginTop = '1px';
4241                 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
4242                 body.style.marginTop = bodyMarginTop;
4244                 body.removeChild(container);
4245                 this.initialized = true;
4246         },
4248         bodyOffset: function(body) {
4249                 jQuery.offset.initialized || jQuery.offset.initialize();
4250                 var top = body.offsetTop, left = body.offsetLeft;
4251                 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
4252                         top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
4253                         left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
4254                 return { top: top, left: left };
4255         }
4259 jQuery.fn.extend({
4260         position: function() {
4261                 var left = 0, top = 0, results;
4263                 if ( this[0] ) {
4264                         // Get *real* offsetParent
4265                         var offsetParent = this.offsetParent(),
4267                         // Get correct offsets
4268                         offset       = this.offset(),
4269                         parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
4271                         // Subtract element margins
4272                         // note: when an element has margin: auto the offsetLeft and marginLeft 
4273                         // are the same in Safari causing offset.left to incorrectly be 0
4274                         offset.top  -= num( this, 'marginTop'  );
4275                         offset.left -= num( this, 'marginLeft' );
4277                         // Add offsetParent borders
4278                         parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
4279                         parentOffset.left += num( offsetParent, 'borderLeftWidth' );
4281                         // Subtract the two offsets
4282                         results = {
4283                                 top:  offset.top  - parentOffset.top,
4284                                 left: offset.left - parentOffset.left
4285                         };
4286                 }
4288                 return results;
4289         },
4291         offsetParent: function() {
4292                 var offsetParent = this[0].offsetParent || document.body;
4293                 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
4294                         offsetParent = offsetParent.offsetParent;
4295                 return jQuery(offsetParent);
4296         }
4300 // Create scrollLeft and scrollTop methods
4301 jQuery.each( ['Left', 'Top'], function(i, name) {
4302         var method = 'scroll' + name;
4303         
4304         jQuery.fn[ method ] = function(val) {
4305                 if (!this[0]) return null;
4307                 return val !== undefined ?
4309                         // Set the scroll offset
4310                         this.each(function() {
4311                                 this == window || this == document ?
4312                                         window.scrollTo(
4313                                                 !i ? val : jQuery(window).scrollLeft(),
4314                                                  i ? val : jQuery(window).scrollTop()
4315                                         ) :
4316                                         this[ method ] = val;
4317                         }) :
4319                         // Return the scroll offset
4320                         this[0] == window || this[0] == document ?
4321                                 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
4322                                         jQuery.boxModel && document.documentElement[ method ] ||
4323                                         document.body[ method ] :
4324                                 this[0][ method ];
4325         };
4327 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
4328 jQuery.each([ "Height", "Width" ], function(i, name){
4330         var tl = i ? "Left"  : "Top",  // top or left
4331                 br = i ? "Right" : "Bottom", // bottom or right
4332                 lower = name.toLowerCase();
4334         // innerHeight and innerWidth
4335         jQuery.fn["inner" + name] = function(){
4336                 return this[0] ?
4337                         jQuery.css( this[0], lower, false, "padding" ) :
4338                         null;
4339         };
4341         // outerHeight and outerWidth
4342         jQuery.fn["outer" + name] = function(margin) {
4343                 return this[0] ?
4344                         jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
4345                         null;
4346         };
4347         
4348         var type = name.toLowerCase();
4350         jQuery.fn[ type ] = function( size ) {
4351                 // Get window width or height
4352                 return this[0] == window ?
4353                         // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
4354                         document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
4355                         document.body[ "client" + name ] :
4357                         // Get document width or height
4358                         this[0] == document ?
4359                                 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
4360                                 Math.max(
4361                                         document.documentElement["client" + name],
4362                                         document.body["scroll" + name], document.documentElement["scroll" + name],
4363                                         document.body["offset" + name], document.documentElement["offset" + name]
4364                                 ) :
4366                                 // Get or set width or height on the element
4367                                 size === undefined ?
4368                                         // Get width or height on the element
4369                                         (this.length ? jQuery.css( this[0], type ) : null) :
4371                                         // Set the width or height on the element (default to pixels if value is unitless)
4372                                         this.css( type, typeof size === "string" ? size : size + "px" );
4373         };
4376 })();
4378  * jQuery UI 1.7.2
4380  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4381  * Dual licensed under the MIT (MIT-LICENSE.txt)
4382  * and GPL (GPL-LICENSE.txt) licenses.
4384  * http://docs.jquery.com/UI
4385  */
4386 ;jQuery.ui || (function($) {
4388 var _remove = $.fn.remove,
4389         isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
4391 //Helper functions and ui object
4392 $.ui = {
4393         version: "1.7.2",
4395         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
4396         plugin: {
4397                 add: function(module, option, set) {
4398                         var proto = $.ui[module].prototype;
4399                         for(var i in set) {
4400                                 proto.plugins[i] = proto.plugins[i] || [];
4401                                 proto.plugins[i].push([option, set[i]]);
4402                         }
4403                 },
4404                 call: function(instance, name, args) {
4405                         var set = instance.plugins[name];
4406                         if(!set || !instance.element[0].parentNode) { return; }
4408                         for (var i = 0; i < set.length; i++) {
4409                                 if (instance.options[set[i][0]]) {
4410                                         set[i][1].apply(instance.element, args);
4411                                 }
4412                         }
4413                 }
4414         },
4416         contains: function(a, b) {
4417                 return document.compareDocumentPosition
4418                         ? a.compareDocumentPosition(b) & 16
4419                         : a !== b && a.contains(b);
4420         },
4422         hasScroll: function(el, a) {
4424                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
4425                 if ($(el).css('overflow') == 'hidden') { return false; }
4427                 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
4428                         has = false;
4430                 if (el[scroll] > 0) { return true; }
4432                 // TODO: determine which cases actually cause this to happen
4433                 // if the element doesn't have the scroll set, see if it's possible to
4434                 // set the scroll
4435                 el[scroll] = 1;
4436                 has = (el[scroll] > 0);
4437                 el[scroll] = 0;
4438                 return has;
4439         },
4441         isOverAxis: function(x, reference, size) {
4442                 //Determines when x coordinate is over "b" element axis
4443                 return (x > reference) && (x < (reference + size));
4444         },
4446         isOver: function(y, x, top, left, height, width) {
4447                 //Determines when x, y coordinates is over "b" element
4448                 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
4449         },
4451         keyCode: {
4452                 BACKSPACE: 8,
4453                 CAPS_LOCK: 20,
4454                 COMMA: 188,
4455                 CONTROL: 17,
4456                 DELETE: 46,
4457                 DOWN: 40,
4458                 END: 35,
4459                 ENTER: 13,
4460                 ESCAPE: 27,
4461                 HOME: 36,
4462                 INSERT: 45,
4463                 LEFT: 37,
4464                 NUMPAD_ADD: 107,
4465                 NUMPAD_DECIMAL: 110,
4466                 NUMPAD_DIVIDE: 111,
4467                 NUMPAD_ENTER: 108,
4468                 NUMPAD_MULTIPLY: 106,
4469                 NUMPAD_SUBTRACT: 109,
4470                 PAGE_DOWN: 34,
4471                 PAGE_UP: 33,
4472                 PERIOD: 190,
4473                 RIGHT: 39,
4474                 SHIFT: 16,
4475                 SPACE: 32,
4476                 TAB: 9,
4477                 UP: 38
4478         }
4481 // WAI-ARIA normalization
4482 if (isFF2) {
4483         var attr = $.attr,
4484                 removeAttr = $.fn.removeAttr,
4485                 ariaNS = "http://www.w3.org/2005/07/aaa",
4486                 ariaState = /^aria-/,
4487                 ariaRole = /^wairole:/;
4489         $.attr = function(elem, name, value) {
4490                 var set = value !== undefined;
4492                 return (name == 'role'
4493                         ? (set
4494                                 ? attr.call(this, elem, name, "wairole:" + value)
4495                                 : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
4496                         : (ariaState.test(name)
4497                                 ? (set
4498                                         ? elem.setAttributeNS(ariaNS,
4499                                                 name.replace(ariaState, "aaa:"), value)
4500                                         : attr.call(this, elem, name.replace(ariaState, "aaa:")))
4501                                 : attr.apply(this, arguments)));
4502         };
4504         $.fn.removeAttr = function(name) {
4505                 return (ariaState.test(name)
4506                         ? this.each(function() {
4507                                 this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
4508                         }) : removeAttr.call(this, name));
4509         };
4512 //jQuery plugins
4513 $.fn.extend({
4514         remove: function() {
4515                 // Safari has a native remove event which actually removes DOM elements,
4516                 // so we have to use triggerHandler instead of trigger (#3037).
4517                 $("*", this).add(this).each(function() {
4518                         $(this).triggerHandler("remove");
4519                 });
4520                 return _remove.apply(this, arguments );
4521         },
4523         enableSelection: function() {
4524                 return this
4525                         .attr('unselectable', 'off')
4526                         .css('MozUserSelect', '')
4527                         .unbind('selectstart.ui');
4528         },
4530         disableSelection: function() {
4531                 return this
4532                         .attr('unselectable', 'on')
4533                         .css('MozUserSelect', 'none')
4534                         .bind('selectstart.ui', function() { return false; });
4535         },
4537         scrollParent: function() {
4538                 var scrollParent;
4539                 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
4540                         scrollParent = this.parents().filter(function() {
4541                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
4542                         }).eq(0);
4543                 } else {
4544                         scrollParent = this.parents().filter(function() {
4545                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
4546                         }).eq(0);
4547                 }
4549                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
4550         }
4554 //Additional selectors
4555 $.extend($.expr[':'], {
4556         data: function(elem, i, match) {
4557                 return !!$.data(elem, match[3]);
4558         },
4560         focusable: function(element) {
4561                 var nodeName = element.nodeName.toLowerCase(),
4562                         tabIndex = $.attr(element, 'tabindex');
4563                 return (/input|select|textarea|button|object/.test(nodeName)
4564                         ? !element.disabled
4565                         : 'a' == nodeName || 'area' == nodeName
4566                                 ? element.href || !isNaN(tabIndex)
4567                                 : !isNaN(tabIndex))
4568                         // the element and all of its ancestors must be visible
4569                         // the browser may report that the area is hidden
4570                         && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
4571         },
4573         tabbable: function(element) {
4574                 var tabIndex = $.attr(element, 'tabindex');
4575                 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
4576         }
4580 // $.widget is a factory to create jQuery plugins
4581 // taking some boilerplate code out of the plugin code
4582 function getter(namespace, plugin, method, args) {
4583         function getMethods(type) {
4584                 var methods = $[namespace][plugin][type] || [];
4585                 return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
4586         }
4588         var methods = getMethods('getter');
4589         if (args.length == 1 && typeof args[0] == 'string') {
4590                 methods = methods.concat(getMethods('getterSetter'));
4591         }
4592         return ($.inArray(method, methods) != -1);
4595 $.widget = function(name, prototype) {
4596         var namespace = name.split(".")[0];
4597         name = name.split(".")[1];
4599         // create plugin method
4600         $.fn[name] = function(options) {
4601                 var isMethodCall = (typeof options == 'string'),
4602                         args = Array.prototype.slice.call(arguments, 1);
4604                 // prevent calls to internal methods
4605                 if (isMethodCall && options.substring(0, 1) == '_') {
4606                         return this;
4607                 }
4609                 // handle getter methods
4610                 if (isMethodCall && getter(namespace, name, options, args)) {
4611                         var instance = $.data(this[0], name);
4612                         return (instance ? instance[options].apply(instance, args)
4613                                 : undefined);
4614                 }
4616                 // handle initialization and non-getter methods
4617                 return this.each(function() {
4618                         var instance = $.data(this, name);
4620                         // constructor
4621                         (!instance && !isMethodCall &&
4622                                 $.data(this, name, new $[namespace][name](this, options))._init());
4624                         // method call
4625                         (instance && isMethodCall && $.isFunction(instance[options]) &&
4626                                 instance[options].apply(instance, args));
4627                 });
4628         };
4630         // create widget constructor
4631         $[namespace] = $[namespace] || {};
4632         $[namespace][name] = function(element, options) {
4633                 var self = this;
4635                 this.namespace = namespace;
4636                 this.widgetName = name;
4637                 this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
4638                 this.widgetBaseClass = namespace + '-' + name;
4640                 this.options = $.extend({},
4641                         $.widget.defaults,
4642                         $[namespace][name].defaults,
4643                         $.metadata && $.metadata.get(element)[name],
4644                         options);
4646                 this.element = $(element)
4647                         .bind('setData.' + name, function(event, key, value) {
4648                                 if (event.target == element) {
4649                                         return self._setData(key, value);
4650                                 }
4651                         })
4652                         .bind('getData.' + name, function(event, key) {
4653                                 if (event.target == element) {
4654                                         return self._getData(key);
4655                                 }
4656                         })
4657                         .bind('remove', function() {
4658                                 return self.destroy();
4659                         });
4660         };
4662         // add widget prototype
4663         $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
4665         // TODO: merge getter and getterSetter properties from widget prototype
4666         // and plugin prototype
4667         $[namespace][name].getterSetter = 'option';
4670 $.widget.prototype = {
4671         _init: function() {},
4672         destroy: function() {
4673                 this.element.removeData(this.widgetName)
4674                         .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
4675                         .removeAttr('aria-disabled');
4676         },
4678         option: function(key, value) {
4679                 var options = key,
4680                         self = this;
4682                 if (typeof key == "string") {
4683                         if (value === undefined) {
4684                                 return this._getData(key);
4685                         }
4686                         options = {};
4687                         options[key] = value;
4688                 }
4690                 $.each(options, function(key, value) {
4691                         self._setData(key, value);
4692                 });
4693         },
4694         _getData: function(key) {
4695                 return this.options[key];
4696         },
4697         _setData: function(key, value) {
4698                 this.options[key] = value;
4700                 if (key == 'disabled') {
4701                         this.element
4702                                 [value ? 'addClass' : 'removeClass'](
4703                                         this.widgetBaseClass + '-disabled' + ' ' +
4704                                         this.namespace + '-state-disabled')
4705                                 .attr("aria-disabled", value);
4706                 }
4707         },
4709         enable: function() {
4710                 this._setData('disabled', false);
4711         },
4712         disable: function() {
4713                 this._setData('disabled', true);
4714         },
4716         _trigger: function(type, event, data) {
4717                 var callback = this.options[type],
4718                         eventName = (type == this.widgetEventPrefix
4719                                 ? type : this.widgetEventPrefix + type);
4721                 event = $.Event(event);
4722                 event.type = eventName;
4724                 // copy original event properties over to the new event
4725                 // this would happen if we could call $.event.fix instead of $.Event
4726                 // but we don't have a way to force an event to be fixed multiple times
4727                 if (event.originalEvent) {
4728                         for (var i = $.event.props.length, prop; i;) {
4729                                 prop = $.event.props[--i];
4730                                 event[prop] = event.originalEvent[prop];
4731                         }
4732                 }
4734                 this.element.trigger(event, data);
4736                 return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
4737                         || event.isDefaultPrevented());
4738         }
4741 $.widget.defaults = {
4742         disabled: false
4746 /** Mouse Interaction Plugin **/
4748 $.ui.mouse = {
4749         _mouseInit: function() {
4750                 var self = this;
4752                 this.element
4753                         .bind('mousedown.'+this.widgetName, function(event) {
4754                                 return self._mouseDown(event);
4755                         })
4756                         .bind('click.'+this.widgetName, function(event) {
4757                                 if(self._preventClickEvent) {
4758                                         self._preventClickEvent = false;
4759                                         event.stopImmediatePropagation();
4760                                         return false;
4761                                 }
4762                         });
4764                 // Prevent text selection in IE
4765                 if ($.browser.msie) {
4766                         this._mouseUnselectable = this.element.attr('unselectable');
4767                         this.element.attr('unselectable', 'on');
4768                 }
4770                 this.started = false;
4771         },
4773         // TODO: make sure destroying one instance of mouse doesn't mess with
4774         // other instances of mouse
4775         _mouseDestroy: function() {
4776                 this.element.unbind('.'+this.widgetName);
4778                 // Restore text selection in IE
4779                 ($.browser.msie
4780                         && this.element.attr('unselectable', this._mouseUnselectable));
4781         },
4783         _mouseDown: function(event) {
4784                 // don't let more than one widget handle mouseStart
4785                 // TODO: figure out why we have to use originalEvent
4786                 event.originalEvent = event.originalEvent || {};
4787                 if (event.originalEvent.mouseHandled) { return; }
4789                 // we may have missed mouseup (out of window)
4790                 (this._mouseStarted && this._mouseUp(event));
4792                 this._mouseDownEvent = event;
4794                 var self = this,
4795                         btnIsLeft = (event.which == 1),
4796                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
4797                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
4798                         return true;
4799                 }
4801                 this.mouseDelayMet = !this.options.delay;
4802                 if (!this.mouseDelayMet) {
4803                         this._mouseDelayTimer = setTimeout(function() {
4804                                 self.mouseDelayMet = true;
4805                         }, this.options.delay);
4806                 }
4808                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
4809                         this._mouseStarted = (this._mouseStart(event) !== false);
4810                         if (!this._mouseStarted) {
4811                                 event.preventDefault();
4812                                 return true;
4813                         }
4814                 }
4816                 // these delegates are required to keep context
4817                 this._mouseMoveDelegate = function(event) {
4818                         return self._mouseMove(event);
4819                 };
4820                 this._mouseUpDelegate = function(event) {
4821                         return self._mouseUp(event);
4822                 };
4823                 $(document)
4824                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
4825                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
4827                 // preventDefault() is used to prevent the selection of text here -
4828                 // however, in Safari, this causes select boxes not to be selectable
4829                 // anymore, so this fix is needed
4830                 ($.browser.safari || event.preventDefault());
4832                 event.originalEvent.mouseHandled = true;
4833                 return true;
4834         },
4836         _mouseMove: function(event) {
4837                 // IE mouseup check - mouseup happened when mouse was out of window
4838                 if ($.browser.msie && !event.button) {
4839                         return this._mouseUp(event);
4840                 }
4842                 if (this._mouseStarted) {
4843                         this._mouseDrag(event);
4844                         return event.preventDefault();
4845                 }
4847                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
4848                         this._mouseStarted =
4849                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
4850                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
4851                 }
4853                 return !this._mouseStarted;
4854         },
4856         _mouseUp: function(event) {
4857                 $(document)
4858                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
4859                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
4861                 if (this._mouseStarted) {
4862                         this._mouseStarted = false;
4863                         this._preventClickEvent = (event.target == this._mouseDownEvent.target);
4864                         this._mouseStop(event);
4865                 }
4867                 return false;
4868         },
4870         _mouseDistanceMet: function(event) {
4871                 return (Math.max(
4872                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
4873                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
4874                         ) >= this.options.distance
4875                 );
4876         },
4878         _mouseDelayMet: function(event) {
4879                 return this.mouseDelayMet;
4880         },
4882         // These are placeholder methods, to be overriden by extending plugin
4883         _mouseStart: function(event) {},
4884         _mouseDrag: function(event) {},
4885         _mouseStop: function(event) {},
4886         _mouseCapture: function(event) { return true; }
4889 $.ui.mouse.defaults = {
4890         cancel: null,
4891         distance: 1,
4892         delay: 0
4895 })(jQuery);
4897  * jQuery UI Draggable 1.7.2
4899  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
4900  * Dual licensed under the MIT (MIT-LICENSE.txt)
4901  * and GPL (GPL-LICENSE.txt) licenses.
4903  * http://docs.jquery.com/UI/Draggables
4905  * Depends:
4906  *      ui.core.js
4907  */
4908 (function($) {
4910 $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
4912         _init: function() {
4914                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
4915                         this.element[0].style.position = 'relative';
4917                 (this.options.addClasses && this.element.addClass("ui-draggable"));
4918                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
4920                 this._mouseInit();
4922         },
4924         destroy: function() {
4925                 if(!this.element.data('draggable')) return;
4926                 this.element
4927                         .removeData("draggable")
4928                         .unbind(".draggable")
4929                         .removeClass("ui-draggable"
4930                                 + " ui-draggable-dragging"
4931                                 + " ui-draggable-disabled");
4932                 this._mouseDestroy();
4933         },
4935         _mouseCapture: function(event) {
4937                 var o = this.options;
4939                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
4940                         return false;
4942                 //Quit if we're not on a valid handle
4943                 this.handle = this._getHandle(event);
4944                 if (!this.handle)
4945                         return false;
4947                 return true;
4949         },
4951         _mouseStart: function(event) {
4953                 var o = this.options;
4955                 //Create and append the visible helper
4956                 this.helper = this._createHelper(event);
4958                 //Cache the helper size
4959                 this._cacheHelperProportions();
4961                 //If ddmanager is used for droppables, set the global draggable
4962                 if($.ui.ddmanager)
4963                         $.ui.ddmanager.current = this;
4965                 /*
4966                  * - Position generation -
4967                  * This block generates everything position related - it's the core of draggables.
4968                  */
4970                 //Cache the margins of the original element
4971                 this._cacheMargins();
4973                 //Store the helper's css position
4974                 this.cssPosition = this.helper.css("position");
4975                 this.scrollParent = this.helper.scrollParent();
4977                 //The element's absolute position on the page minus margins
4978                 this.offset = this.element.offset();
4979                 this.offset = {
4980                         top: this.offset.top - this.margins.top,
4981                         left: this.offset.left - this.margins.left
4982                 };
4984                 $.extend(this.offset, {
4985                         click: { //Where the click happened, relative to the element
4986                                 left: event.pageX - this.offset.left,
4987                                 top: event.pageY - this.offset.top
4988                         },
4989                         parent: this._getParentOffset(),
4990                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
4991                 });
4993                 //Generate the original position
4994                 this.originalPosition = this._generatePosition(event);
4995                 this.originalPageX = event.pageX;
4996                 this.originalPageY = event.pageY;
4998                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
4999                 if(o.cursorAt)
5000                         this._adjustOffsetFromHelper(o.cursorAt);
5002                 //Set a containment if given in the options
5003                 if(o.containment)
5004                         this._setContainment();
5006                 //Call plugins and callbacks
5007                 this._trigger("start", event);
5009                 //Recache the helper size
5010                 this._cacheHelperProportions();
5012                 //Prepare the droppable offsets
5013                 if ($.ui.ddmanager && !o.dropBehaviour)
5014                         $.ui.ddmanager.prepareOffsets(this, event);
5016                 this.helper.addClass("ui-draggable-dragging");
5017                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
5018                 return true;
5019         },
5021         _mouseDrag: function(event, noPropagation) {
5023                 //Compute the helpers position
5024                 this.position = this._generatePosition(event);
5025                 this.positionAbs = this._convertPositionTo("absolute");
5027                 //Call plugins and callbacks and use the resulting position if something is returned
5028                 if (!noPropagation) {
5029                         var ui = this._uiHash();
5030                         this._trigger('drag', event, ui);
5031                         this.position = ui.position;
5032                 }
5034                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
5035                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
5036                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
5038                 return false;
5039         },
5041         _mouseStop: function(event) {
5043                 //If we are using droppables, inform the manager about the drop
5044                 var dropped = false;
5045                 if ($.ui.ddmanager && !this.options.dropBehaviour)
5046                         dropped = $.ui.ddmanager.drop(this, event);
5048                 //if a drop comes from outside (a sortable)
5049                 if(this.dropped) {
5050                         dropped = this.dropped;
5051                         this.dropped = false;
5052                 }
5054                 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
5055                         var self = this;
5056                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
5057                                 self._trigger("stop", event);
5058                                 self._clear();
5059                         });
5060                 } else {
5061                         this._trigger("stop", event);
5062                         this._clear();
5063                 }
5065                 return false;
5066         },
5068         _getHandle: function(event) {
5070                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
5071                 $(this.options.handle, this.element)
5072                         .find("*")
5073                         .andSelf()
5074                         .each(function() {
5075                                 if(this == event.target) handle = true;
5076                         });
5078                 return handle;
5080         },
5082         _createHelper: function(event) {
5084                 var o = this.options;
5085                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
5087                 if(!helper.parents('body').length)
5088                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
5090                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
5091                         helper.css("position", "absolute");
5093                 return helper;
5095         },
5097         _adjustOffsetFromHelper: function(obj) {
5098                 if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
5099                 if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
5100                 if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
5101                 if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
5102         },
5104         _getParentOffset: function() {
5106                 //Get the offsetParent and cache its position
5107                 this.offsetParent = this.helper.offsetParent();
5108                 var po = this.offsetParent.offset();
5110                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
5111                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
5112                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
5113                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
5114                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
5115                         po.left += this.scrollParent.scrollLeft();
5116                         po.top += this.scrollParent.scrollTop();
5117                 }
5119                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
5120                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
5121                         po = { top: 0, left: 0 };
5123                 return {
5124                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
5125                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
5126                 };
5128         },
5130         _getRelativeOffset: function() {
5132                 if(this.cssPosition == "relative") {
5133                         var p = this.element.position();
5134                         return {
5135                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
5136                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
5137                         };
5138                 } else {
5139                         return { top: 0, left: 0 };
5140                 }
5142         },
5144         _cacheMargins: function() {
5145                 this.margins = {
5146                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
5147                         top: (parseInt(this.element.css("marginTop"),10) || 0)
5148                 };
5149         },
5151         _cacheHelperProportions: function() {
5152                 this.helperProportions = {
5153                         width: this.helper.outerWidth(),
5154                         height: this.helper.outerHeight()
5155                 };
5156         },
5158         _setContainment: function() {
5160                 var o = this.options;
5161                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
5162                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
5163                         0 - this.offset.relative.left - this.offset.parent.left,
5164                         0 - this.offset.relative.top - this.offset.parent.top,
5165                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
5166                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
5167                 ];
5169                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
5170                         var ce = $(o.containment)[0]; if(!ce) return;
5171                         var co = $(o.containment).offset();
5172                         var over = ($(ce).css("overflow") != 'hidden');
5174                         this.containment = [
5175                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
5176                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
5177                                 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
5178                                 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
5179                         ];
5180                 } else if(o.containment.constructor == Array) {
5181                         this.containment = o.containment;
5182                 }
5184         },
5186         _convertPositionTo: function(d, pos) {
5188                 if(!pos) pos = this.position;
5189                 var mod = d == "absolute" ? 1 : -1;
5190                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5192                 return {
5193                         top: (
5194                                 pos.top                                                                                                                                 // The absolute mouse position
5195                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
5196                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
5197                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
5198                         ),
5199                         left: (
5200                                 pos.left                                                                                                                                // The absolute mouse position
5201                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
5202                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
5203                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
5204                         )
5205                 };
5207         },
5209         _generatePosition: function(event) {
5211                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5213                 // This is another very weird special case that only happens for relative elements:
5214                 // 1. If the css position is relative
5215                 // 2. and the scroll parent is the document or similar to the offset parent
5216                 // we have to refresh the relative offset during the scroll so there are no jumps
5217                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
5218                         this.offset.relative = this._getRelativeOffset();
5219                 }
5221                 var pageX = event.pageX;
5222                 var pageY = event.pageY;
5224                 /*
5225                  * - Position constraining -
5226                  * Constrain the position to a mix of grid, containment.
5227                  */
5229                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
5231                         if(this.containment) {
5232                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
5233                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
5234                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
5235                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
5236                         }
5238                         if(o.grid) {
5239                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
5240                                 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
5242                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
5243                                 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
5244                         }
5246                 }
5248                 return {
5249                         top: (
5250                                 pageY                                                                                                                           // The absolute mouse position
5251                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
5252                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
5253                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
5254                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
5255                         ),
5256                         left: (
5257                                 pageX                                                                                                                           // The absolute mouse position
5258                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
5259                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
5260                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
5261                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
5262                         )
5263                 };
5265         },
5267         _clear: function() {
5268                 this.helper.removeClass("ui-draggable-dragging");
5269                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
5270                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
5271                 this.helper = null;
5272                 this.cancelHelperRemoval = false;
5273         },
5275         // From now on bulk stuff - mainly helpers
5277         _trigger: function(type, event, ui) {
5278                 ui = ui || this._uiHash();
5279                 $.ui.plugin.call(this, type, [event, ui]);
5280                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
5281                 return $.widget.prototype._trigger.call(this, type, event, ui);
5282         },
5284         plugins: {},
5286         _uiHash: function(event) {
5287                 return {
5288                         helper: this.helper,
5289                         position: this.position,
5290                         absolutePosition: this.positionAbs, //deprecated
5291                         offset: this.positionAbs
5292                 };
5293         }
5295 }));
5297 $.extend($.ui.draggable, {
5298         version: "1.7.2",
5299         eventPrefix: "drag",
5300         defaults: {
5301                 addClasses: true,
5302                 appendTo: "parent",
5303                 axis: false,
5304                 cancel: ":input,option",
5305                 connectToSortable: false,
5306                 containment: false,
5307                 cursor: "auto",
5308                 cursorAt: false,
5309                 delay: 0,
5310                 distance: 1,
5311                 grid: false,
5312                 handle: false,
5313                 helper: "original",
5314                 iframeFix: false,
5315                 opacity: false,
5316                 refreshPositions: false,
5317                 revert: false,
5318                 revertDuration: 500,
5319                 scope: "default",
5320                 scroll: true,
5321                 scrollSensitivity: 20,
5322                 scrollSpeed: 20,
5323                 snap: false,
5324                 snapMode: "both",
5325                 snapTolerance: 20,
5326                 stack: false,
5327                 zIndex: false
5328         }
5331 $.ui.plugin.add("draggable", "connectToSortable", {
5332         start: function(event, ui) {
5334                 var inst = $(this).data("draggable"), o = inst.options,
5335                         uiSortable = $.extend({}, ui, { item: inst.element });
5336                 inst.sortables = [];
5337                 $(o.connectToSortable).each(function() {
5338                         var sortable = $.data(this, 'sortable');
5339                         if (sortable && !sortable.options.disabled) {
5340                                 inst.sortables.push({
5341                                         instance: sortable,
5342                                         shouldRevert: sortable.options.revert
5343                                 });
5344                                 sortable._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
5345                                 sortable._trigger("activate", event, uiSortable);
5346                         }
5347                 });
5349         },
5350         stop: function(event, ui) {
5352                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
5353                 var inst = $(this).data("draggable"),
5354                         uiSortable = $.extend({}, ui, { item: inst.element });
5356                 $.each(inst.sortables, function() {
5357                         if(this.instance.isOver) {
5359                                 this.instance.isOver = 0;
5361                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
5362                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
5364                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
5365                                 if(this.shouldRevert) this.instance.options.revert = true;
5367                                 //Trigger the stop of the sortable
5368                                 this.instance._mouseStop(event);
5370                                 this.instance.options.helper = this.instance.options._helper;
5372                                 //If the helper has been the original item, restore properties in the sortable
5373                                 if(inst.options.helper == 'original')
5374                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
5376                         } else {
5377                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
5378                                 this.instance._trigger("deactivate", event, uiSortable);
5379                         }
5381                 });
5383         },
5384         drag: function(event, ui) {
5386                 var inst = $(this).data("draggable"), self = this;
5388                 var checkPos = function(o) {
5389                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
5390                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
5391                         var itemHeight = o.height, itemWidth = o.width;
5392                         var itemTop = o.top, itemLeft = o.left;
5394                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
5395                 };
5397                 $.each(inst.sortables, function(i) {
5398                         
5399                         //Copy over some variables to allow calling the sortable's native _intersectsWith
5400                         this.instance.positionAbs = inst.positionAbs;
5401                         this.instance.helperProportions = inst.helperProportions;
5402                         this.instance.offset.click = inst.offset.click;
5403                         
5404                         if(this.instance._intersectsWith(this.instance.containerCache)) {
5406                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
5407                                 if(!this.instance.isOver) {
5409                                         this.instance.isOver = 1;
5410                                         //Now we fake the start of dragging for the sortable instance,
5411                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
5412                                         //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
5413                                         this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
5414                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
5415                                         this.instance.options.helper = function() { return ui.helper[0]; };
5417                                         event.target = this.instance.currentItem[0];
5418                                         this.instance._mouseCapture(event, true);
5419                                         this.instance._mouseStart(event, true, true);
5421                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
5422                                         this.instance.offset.click.top = inst.offset.click.top;
5423                                         this.instance.offset.click.left = inst.offset.click.left;
5424                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
5425                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
5427                                         inst._trigger("toSortable", event);
5428                                         inst.dropped = this.instance.element; //draggable revert needs that
5429                                         //hack so receive/update callbacks work (mostly)
5430                                         inst.currentItem = inst.element;
5431                                         this.instance.fromOutside = inst;
5433                                 }
5435                                 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
5436                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
5438                         } else {
5440                                 //If it doesn't intersect with the sortable, and it intersected before,
5441                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
5442                                 if(this.instance.isOver) {
5444                                         this.instance.isOver = 0;
5445                                         this.instance.cancelHelperRemoval = true;
5446                                         
5447                                         //Prevent reverting on this forced stop
5448                                         this.instance.options.revert = false;
5449                                         
5450                                         // The out event needs to be triggered independently
5451                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
5452                                         
5453                                         this.instance._mouseStop(event, true);
5454                                         this.instance.options.helper = this.instance.options._helper;
5456                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
5457                                         this.instance.currentItem.remove();
5458                                         if(this.instance.placeholder) this.instance.placeholder.remove();
5460                                         inst._trigger("fromSortable", event);
5461                                         inst.dropped = false; //draggable revert needs that
5462                                 }
5464                         };
5466                 });
5468         }
5471 $.ui.plugin.add("draggable", "cursor", {
5472         start: function(event, ui) {
5473                 var t = $('body'), o = $(this).data('draggable').options;
5474                 if (t.css("cursor")) o._cursor = t.css("cursor");
5475                 t.css("cursor", o.cursor);
5476         },
5477         stop: function(event, ui) {
5478                 var o = $(this).data('draggable').options;
5479                 if (o._cursor) $('body').css("cursor", o._cursor);
5480         }
5483 $.ui.plugin.add("draggable", "iframeFix", {
5484         start: function(event, ui) {
5485                 var o = $(this).data('draggable').options;
5486                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
5487                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
5488                         .css({
5489                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
5490                                 position: "absolute", opacity: "0.001", zIndex: 1000
5491                         })
5492                         .css($(this).offset())
5493                         .appendTo("body");
5494                 });
5495         },
5496         stop: function(event, ui) {
5497                 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
5498         }
5501 $.ui.plugin.add("draggable", "opacity", {
5502         start: function(event, ui) {
5503                 var t = $(ui.helper), o = $(this).data('draggable').options;
5504                 if(t.css("opacity")) o._opacity = t.css("opacity");
5505                 t.css('opacity', o.opacity);
5506         },
5507         stop: function(event, ui) {
5508                 var o = $(this).data('draggable').options;
5509                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
5510         }
5513 $.ui.plugin.add("draggable", "scroll", {
5514         start: function(event, ui) {
5515                 var i = $(this).data("draggable");
5516                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
5517         },
5518         drag: function(event, ui) {
5520                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
5522                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
5524                         if(!o.axis || o.axis != 'x') {
5525                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
5526                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
5527                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
5528                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
5529                         }
5531                         if(!o.axis || o.axis != 'y') {
5532                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
5533                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
5534                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
5535                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
5536                         }
5538                 } else {
5540                         if(!o.axis || o.axis != 'x') {
5541                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
5542                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
5543                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
5544                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
5545                         }
5547                         if(!o.axis || o.axis != 'y') {
5548                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
5549                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
5550                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
5551                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
5552                         }
5554                 }
5556                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
5557                         $.ui.ddmanager.prepareOffsets(i, event);
5559         }
5562 $.ui.plugin.add("draggable", "snap", {
5563         start: function(event, ui) {
5565                 var i = $(this).data("draggable"), o = i.options;
5566                 i.snapElements = [];
5568                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
5569                         var $t = $(this); var $o = $t.offset();
5570                         if(this != i.element[0]) i.snapElements.push({
5571                                 item: this,
5572                                 width: $t.outerWidth(), height: $t.outerHeight(),
5573                                 top: $o.top, left: $o.left
5574                         });
5575                 });
5577         },
5578         drag: function(event, ui) {
5580                 var inst = $(this).data("draggable"), o = inst.options;
5581                 var d = o.snapTolerance;
5583                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
5584                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
5586                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
5588                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
5589                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
5591                         //Yes, I know, this is insane ;)
5592                         if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
5593                                 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
5594                                 inst.snapElements[i].snapping = false;
5595                                 continue;
5596                         }
5598                         if(o.snapMode != 'inner') {
5599                                 var ts = Math.abs(t - y2) <= d;
5600                                 var bs = Math.abs(b - y1) <= d;
5601                                 var ls = Math.abs(l - x2) <= d;
5602                                 var rs = Math.abs(r - x1) <= d;
5603                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
5604                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
5605                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
5606                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
5607                         }
5609                         var first = (ts || bs || ls || rs);
5611                         if(o.snapMode != 'outer') {
5612                                 var ts = Math.abs(t - y1) <= d;
5613                                 var bs = Math.abs(b - y2) <= d;
5614                                 var ls = Math.abs(l - x1) <= d;
5615                                 var rs = Math.abs(r - x2) <= d;
5616                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
5617                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
5618                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
5619                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
5620                         }
5622                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
5623                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
5624                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
5626                 };
5628         }
5631 $.ui.plugin.add("draggable", "stack", {
5632         start: function(event, ui) {
5634                 var o = $(this).data("draggable").options;
5636                 var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
5637                         return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
5638                 });
5640                 $(group).each(function(i) {
5641                         this.style.zIndex = o.stack.min + i;
5642                 });
5644                 this[0].style.zIndex = o.stack.min + group.length;
5646         }
5649 $.ui.plugin.add("draggable", "zIndex", {
5650         start: function(event, ui) {
5651                 var t = $(ui.helper), o = $(this).data("draggable").options;
5652                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
5653                 t.css('zIndex', o.zIndex);
5654         },
5655         stop: function(event, ui) {
5656                 var o = $(this).data("draggable").options;
5657                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
5658         }
5661 })(jQuery);
5663  * jQuery UI Resizable 1.7.2
5665  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5666  * Dual licensed under the MIT (MIT-LICENSE.txt)
5667  * and GPL (GPL-LICENSE.txt) licenses.
5669  * http://docs.jquery.com/UI/Resizables
5671  * Depends:
5672  *      ui.core.js
5673  */
5674 (function($) {
5676 $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
5678         _init: function() {
5680                 var self = this, o = this.options;
5681                 this.element.addClass("ui-resizable");
5683                 $.extend(this, {
5684                         _aspectRatio: !!(o.aspectRatio),
5685                         aspectRatio: o.aspectRatio,
5686                         originalElement: this.element,
5687                         _proportionallyResizeElements: [],
5688                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
5689                 });
5691                 //Wrap the element if it cannot hold child nodes
5692                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
5694                         //Opera fix for relative positioning
5695                         if (/relative/.test(this.element.css('position')) && $.browser.opera)
5696                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
5698                         //Create a wrapper element and set the wrapper to the new current internal element
5699                         this.element.wrap(
5700                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
5701                                         position: this.element.css('position'),
5702                                         width: this.element.outerWidth(),
5703                                         height: this.element.outerHeight(),
5704                                         top: this.element.css('top'),
5705                                         left: this.element.css('left')
5706                                 })
5707                         );
5709                         //Overwrite the original this.element
5710                         this.element = this.element.parent().data(
5711                                 "resizable", this.element.data('resizable')
5712                         );
5714                         this.elementIsWrapper = true;
5716                         //Move margins to the wrapper
5717                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
5718                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
5720                         //Prevent Safari textarea resize
5721                         this.originalResizeStyle = this.originalElement.css('resize');
5722                         this.originalElement.css('resize', 'none');
5724                         //Push the actual element to our proportionallyResize internal array
5725                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
5727                         // avoid IE jump (hard set the margin)
5728                         this.originalElement.css({ margin: this.originalElement.css('margin') });
5730                         // fix handlers offset
5731                         this._proportionallyResize();
5733                 }
5735                 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
5736                 if(this.handles.constructor == String) {
5738                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
5739                         var n = this.handles.split(","); this.handles = {};
5741                         for(var i = 0; i < n.length; i++) {
5743                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
5744                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
5746                                 // increase zIndex of sw, se, ne, nw axis
5747                                 //TODO : this modifies original option
5748                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
5750                                 //TODO : What's going on here?
5751                                 if ('se' == handle) {
5752                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
5753                                 };
5755                                 //Insert into internal handles object and append to element
5756                                 this.handles[handle] = '.ui-resizable-'+handle;
5757                                 this.element.append(axis);
5758                         }
5760                 }
5762                 this._renderAxis = function(target) {
5764                         target = target || this.element;
5766                         for(var i in this.handles) {
5768                                 if(this.handles[i].constructor == String)
5769                                         this.handles[i] = $(this.handles[i], this.element).show();
5771                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
5772                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
5774                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
5776                                         //Checking the correct pad and border
5777                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
5779                                         //The padding type i have to apply...
5780                                         var padPos = [ 'padding',
5781                                                 /ne|nw|n/.test(i) ? 'Top' :
5782                                                 /se|sw|s/.test(i) ? 'Bottom' :
5783                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
5785                                         target.css(padPos, padWrapper);
5787                                         this._proportionallyResize();
5789                                 }
5791                                 //TODO: What's that good for? There's not anything to be executed left
5792                                 if(!$(this.handles[i]).length)
5793                                         continue;
5795                         }
5796                 };
5798                 //TODO: make renderAxis a prototype function
5799                 this._renderAxis(this.element);
5801                 this._handles = $('.ui-resizable-handle', this.element)
5802                         .disableSelection();
5804                 //Matching axis name
5805                 this._handles.mouseover(function() {
5806                         if (!self.resizing) {
5807                                 if (this.className)
5808                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
5809                                 //Axis, default = se
5810                                 self.axis = axis && axis[1] ? axis[1] : 'se';
5811                         }
5812                 });
5814                 //If we want to auto hide the elements
5815                 if (o.autoHide) {
5816                         this._handles.hide();
5817                         $(this.element)
5818                                 .addClass("ui-resizable-autohide")
5819                                 .hover(function() {
5820                                         $(this).removeClass("ui-resizable-autohide");
5821                                         self._handles.show();
5822                                 },
5823                                 function(){
5824                                         if (!self.resizing) {
5825                                                 $(this).addClass("ui-resizable-autohide");
5826                                                 self._handles.hide();
5827                                         }
5828                                 });
5829                 }
5831                 //Initialize the mouse interaction
5832                 this._mouseInit();
5834         },
5836         destroy: function() {
5838                 this._mouseDestroy();
5840                 var _destroy = function(exp) {
5841                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
5842                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
5843                 };
5845                 //TODO: Unwrap at same DOM position
5846                 if (this.elementIsWrapper) {
5847                         _destroy(this.element);
5848                         var wrapper = this.element;
5849                         wrapper.parent().append(
5850                                 this.originalElement.css({
5851                                         position: wrapper.css('position'),
5852                                         width: wrapper.outerWidth(),
5853                                         height: wrapper.outerHeight(),
5854                                         top: wrapper.css('top'),
5855                                         left: wrapper.css('left')
5856                                 })
5857                         ).end().remove();
5858                 }
5860                 this.originalElement.css('resize', this.originalResizeStyle);
5861                 _destroy(this.originalElement);
5863         },
5865         _mouseCapture: function(event) {
5867                 var handle = false;
5868                 for(var i in this.handles) {
5869                         if($(this.handles[i])[0] == event.target) handle = true;
5870                 }
5872                 return this.options.disabled || !!handle;
5874         },
5876         _mouseStart: function(event) {
5878                 var o = this.options, iniPos = this.element.position(), el = this.element;
5880                 this.resizing = true;
5881                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
5883                 // bugfix for http://dev.jquery.com/ticket/1749
5884                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
5885                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
5886                 }
5888                 //Opera fixing relative position
5889                 if ($.browser.opera && (/relative/).test(el.css('position')))
5890                         el.css({ position: 'relative', top: 'auto', left: 'auto' });
5892                 this._renderProxy();
5894                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
5896                 if (o.containment) {
5897                         curleft += $(o.containment).scrollLeft() || 0;
5898                         curtop += $(o.containment).scrollTop() || 0;
5899                 }
5901                 //Store needed variables
5902                 this.offset = this.helper.offset();
5903                 this.position = { left: curleft, top: curtop };
5904                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
5905                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
5906                 this.originalPosition = { left: curleft, top: curtop };
5907                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
5908                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
5910                 //Aspect Ratio
5911                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
5913             var cursor = $('.ui-resizable-' + this.axis).css('cursor');
5914             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
5916                 el.addClass("ui-resizable-resizing");
5917                 this._propagate("start", event);
5918                 return true;
5919         },
5921         _mouseDrag: function(event) {
5923                 //Increase performance, avoid regex
5924                 var el = this.helper, o = this.options, props = {},
5925                         self = this, smp = this.originalMousePosition, a = this.axis;
5927                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
5928                 var trigger = this._change[a];
5929                 if (!trigger) return false;
5931                 // Calculate the attrs that will be change
5932                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
5934                 if (this._aspectRatio || event.shiftKey)
5935                         data = this._updateRatio(data, event);
5937                 data = this._respectSize(data, event);
5939                 // plugins callbacks need to be called first
5940                 this._propagate("resize", event);
5942                 el.css({
5943                         top: this.position.top + "px", left: this.position.left + "px",
5944                         width: this.size.width + "px", height: this.size.height + "px"
5945                 });
5947                 if (!this._helper && this._proportionallyResizeElements.length)
5948                         this._proportionallyResize();
5950                 this._updateCache(data);
5952                 // calling the user callback at the end
5953                 this._trigger('resize', event, this.ui());
5955                 return false;
5956         },
5958         _mouseStop: function(event) {
5960                 this.resizing = false;
5961                 var o = this.options, self = this;
5963                 if(this._helper) {
5964                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
5965                                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
5966                                                         soffsetw = ista ? 0 : self.sizeDiff.width;
5968                         var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
5969                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
5970                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
5972                         if (!o.animate)
5973                                 this.element.css($.extend(s, { top: top, left: left }));
5975                         self.helper.height(self.size.height);
5976                         self.helper.width(self.size.width);
5978                         if (this._helper && !o.animate) this._proportionallyResize();
5979                 }
5981                 $('body').css('cursor', 'auto');
5983                 this.element.removeClass("ui-resizable-resizing");
5985                 this._propagate("stop", event);
5987                 if (this._helper) this.helper.remove();
5988                 return false;
5990         },
5992         _updateCache: function(data) {
5993                 var o = this.options;
5994                 this.offset = this.helper.offset();
5995                 if (isNumber(data.left)) this.position.left = data.left;
5996                 if (isNumber(data.top)) this.position.top = data.top;
5997                 if (isNumber(data.height)) this.size.height = data.height;
5998                 if (isNumber(data.width)) this.size.width = data.width;
5999         },
6001         _updateRatio: function(data, event) {
6003                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
6005                 if (data.height) data.width = (csize.height * this.aspectRatio);
6006                 else if (data.width) data.height = (csize.width / this.aspectRatio);
6008                 if (a == 'sw') {
6009                         data.left = cpos.left + (csize.width - data.width);
6010                         data.top = null;
6011                 }
6012                 if (a == 'nw') {
6013                         data.top = cpos.top + (csize.height - data.height);
6014                         data.left = cpos.left + (csize.width - data.width);
6015                 }
6017                 return data;
6018         },
6020         _respectSize: function(data, event) {
6022                 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
6023                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
6024                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
6026                 if (isminw) data.width = o.minWidth;
6027                 if (isminh) data.height = o.minHeight;
6028                 if (ismaxw) data.width = o.maxWidth;
6029                 if (ismaxh) data.height = o.maxHeight;
6031                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
6032                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
6034                 if (isminw && cw) data.left = dw - o.minWidth;
6035                 if (ismaxw && cw) data.left = dw - o.maxWidth;
6036                 if (isminh && ch)       data.top = dh - o.minHeight;
6037                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
6039                 // fixing jump error on top/left - bug #2330
6040                 var isNotwh = !data.width && !data.height;
6041                 if (isNotwh && !data.left && data.top) data.top = null;
6042                 else if (isNotwh && !data.top && data.left) data.left = null;
6044                 return data;
6045         },
6047         _proportionallyResize: function() {
6049                 var o = this.options;
6050                 if (!this._proportionallyResizeElements.length) return;
6051                 var element = this.helper || this.element;
6053                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
6055                         var prel = this._proportionallyResizeElements[i];
6057                         if (!this.borderDif) {
6058                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
6059                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
6061                                 this.borderDif = $.map(b, function(v, i) {
6062                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
6063                                         return border + padding;
6064                                 });
6065                         }
6067                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
6068                                 continue;
6070                         prel.css({
6071                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
6072                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
6073                         });
6075                 };
6077         },
6079         _renderProxy: function() {
6081                 var el = this.element, o = this.options;
6082                 this.elementOffset = el.offset();
6084                 if(this._helper) {
6086                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
6088                         // fix ie6 offset TODO: This seems broken
6089                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
6090                         pxyoffset = ( ie6 ? 2 : -1 );
6092                         this.helper.addClass(this._helper).css({
6093                                 width: this.element.outerWidth() + pxyoffset,
6094                                 height: this.element.outerHeight() + pxyoffset,
6095                                 position: 'absolute',
6096                                 left: this.elementOffset.left - ie6offset +'px',
6097                                 top: this.elementOffset.top - ie6offset +'px',
6098                                 zIndex: ++o.zIndex //TODO: Don't modify option
6099                         });
6101                         this.helper
6102                                 .appendTo("body")
6103                                 .disableSelection();
6105                 } else {
6106                         this.helper = this.element;
6107                 }
6109         },
6111         _change: {
6112                 e: function(event, dx, dy) {
6113                         return { width: this.originalSize.width + dx };
6114                 },
6115                 w: function(event, dx, dy) {
6116                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
6117                         return { left: sp.left + dx, width: cs.width - dx };
6118                 },
6119                 n: function(event, dx, dy) {
6120                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
6121                         return { top: sp.top + dy, height: cs.height - dy };
6122                 },
6123                 s: function(event, dx, dy) {
6124                         return { height: this.originalSize.height + dy };
6125                 },
6126                 se: function(event, dx, dy) {
6127                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
6128                 },
6129                 sw: function(event, dx, dy) {
6130                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
6131                 },
6132                 ne: function(event, dx, dy) {
6133                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
6134                 },
6135                 nw: function(event, dx, dy) {
6136                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
6137                 }
6138         },
6140         _propagate: function(n, event) {
6141                 $.ui.plugin.call(this, n, [event, this.ui()]);
6142                 (n != "resize" && this._trigger(n, event, this.ui()));
6143         },
6145         plugins: {},
6147         ui: function() {
6148                 return {
6149                         originalElement: this.originalElement,
6150                         element: this.element,
6151                         helper: this.helper,
6152                         position: this.position,
6153                         size: this.size,
6154                         originalSize: this.originalSize,
6155                         originalPosition: this.originalPosition
6156                 };
6157         }
6159 }));
6161 $.extend($.ui.resizable, {
6162         version: "1.7.2",
6163         eventPrefix: "resize",
6164         defaults: {
6165                 alsoResize: false,
6166                 animate: false,
6167                 animateDuration: "slow",
6168                 animateEasing: "swing",
6169                 aspectRatio: false,
6170                 autoHide: false,
6171                 cancel: ":input,option",
6172                 containment: false,
6173                 delay: 0,
6174                 distance: 1,
6175                 ghost: false,
6176                 grid: false,
6177                 handles: "e,s,se",
6178                 helper: false,
6179                 maxHeight: null,
6180                 maxWidth: null,
6181                 minHeight: 10,
6182                 minWidth: 10,
6183                 zIndex: 1000
6184         }
6188  * Resizable Extensions
6189  */
6191 $.ui.plugin.add("resizable", "alsoResize", {
6193         start: function(event, ui) {
6195                 var self = $(this).data("resizable"), o = self.options;
6197                 _store = function(exp) {
6198                         $(exp).each(function() {
6199                                 $(this).data("resizable-alsoresize", {
6200                                         width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
6201                                         left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
6202                                 });
6203                         });
6204                 };
6206                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
6207                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0];      _store(o.alsoResize); }
6208                         else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
6209                 }else{
6210                         _store(o.alsoResize);
6211                 }
6212         },
6214         resize: function(event, ui){
6215                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
6217                 var delta = {
6218                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
6219                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
6220                 },
6222                 _alsoResize = function(exp, c) {
6223                         $(exp).each(function() {
6224                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
6226                                 $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
6227                                         var sum = (start[prop]||0) + (delta[prop]||0);
6228                                         if (sum && sum >= 0)
6229                                                 style[prop] = sum || null;
6230                                 });
6232                                 //Opera fixing relative position
6233                                 if (/relative/.test(el.css('position')) && $.browser.opera) {
6234                                         self._revertToRelativePosition = true;
6235                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });
6236                                 }
6238                                 el.css(style);
6239                         });
6240                 };
6242                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
6243                         $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
6244                 }else{
6245                         _alsoResize(o.alsoResize);
6246                 }
6247         },
6249         stop: function(event, ui){
6250                 var self = $(this).data("resizable");
6252                 //Opera fixing relative position
6253                 if (self._revertToRelativePosition && $.browser.opera) {
6254                         self._revertToRelativePosition = false;
6255                         el.css({ position: 'relative' });
6256                 }
6258                 $(this).removeData("resizable-alsoresize-start");
6259         }
6262 $.ui.plugin.add("resizable", "animate", {
6264         stop: function(event, ui) {
6265                 var self = $(this).data("resizable"), o = self.options;
6267                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
6268                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
6269                                                 soffsetw = ista ? 0 : self.sizeDiff.width;
6271                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
6272                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
6273                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
6275                 self.element.animate(
6276                         $.extend(style, top && left ? { top: top, left: left } : {}), {
6277                                 duration: o.animateDuration,
6278                                 easing: o.animateEasing,
6279                                 step: function() {
6281                                         var data = {
6282                                                 width: parseInt(self.element.css('width'), 10),
6283                                                 height: parseInt(self.element.css('height'), 10),
6284                                                 top: parseInt(self.element.css('top'), 10),
6285                                                 left: parseInt(self.element.css('left'), 10)
6286                                         };
6288                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
6290                                         // propagating resize, and updating values for each animation step
6291                                         self._updateCache(data);
6292                                         self._propagate("resize", event);
6294                                 }
6295                         }
6296                 );
6297         }
6301 $.ui.plugin.add("resizable", "containment", {
6303         start: function(event, ui) {
6304                 var self = $(this).data("resizable"), o = self.options, el = self.element;
6305                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
6306                 if (!ce) return;
6308                 self.containerElement = $(ce);
6310                 if (/document/.test(oc) || oc == document) {
6311                         self.containerOffset = { left: 0, top: 0 };
6312                         self.containerPosition = { left: 0, top: 0 };
6314                         self.parentData = {
6315                                 element: $(document), left: 0, top: 0,
6316                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
6317                         };
6318                 }
6320                 // i'm a node, so compute top, left, right, bottom
6321                 else {
6322                         var element = $(ce), p = [];
6323                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
6325                         self.containerOffset = element.offset();
6326                         self.containerPosition = element.position();
6327                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
6329                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
6330                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
6332                         self.parentData = {
6333                                 element: ce, left: co.left, top: co.top, width: width, height: height
6334                         };
6335                 }
6336         },
6338         resize: function(event, ui) {
6339                 var self = $(this).data("resizable"), o = self.options,
6340                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
6341                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
6343                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
6345                 if (cp.left < (self._helper ? co.left : 0)) {
6346                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
6347                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;
6348                         self.position.left = o.helper ? co.left : 0;
6349                 }
6351                 if (cp.top < (self._helper ? co.top : 0)) {
6352                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
6353                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;
6354                         self.position.top = self._helper ? co.top : 0;
6355                 }
6357                 self.offset.left = self.parentData.left+self.position.left;
6358                 self.offset.top = self.parentData.top+self.position.top;
6360                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
6361                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
6363                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
6364                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
6366                 if(isParent && isOffsetRelative) woset -= self.parentData.left;
6368                 if (woset + self.size.width >= self.parentData.width) {
6369                         self.size.width = self.parentData.width - woset;
6370                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;
6371                 }
6373                 if (hoset + self.size.height >= self.parentData.height) {
6374                         self.size.height = self.parentData.height - hoset;
6375                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;
6376                 }
6377         },
6379         stop: function(event, ui){
6380                 var self = $(this).data("resizable"), o = self.options, cp = self.position,
6381                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
6383                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
6385                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
6386                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
6388                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
6389                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
6391         }
6394 $.ui.plugin.add("resizable", "ghost", {
6396         start: function(event, ui) {
6398                 var self = $(this).data("resizable"), o = self.options, cs = self.size;
6400                 self.ghost = self.originalElement.clone();
6401                 self.ghost
6402                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
6403                         .addClass('ui-resizable-ghost')
6404                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
6406                 self.ghost.appendTo(self.helper);
6408         },
6410         resize: function(event, ui){
6411                 var self = $(this).data("resizable"), o = self.options;
6412                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
6413         },
6415         stop: function(event, ui){
6416                 var self = $(this).data("resizable"), o = self.options;
6417                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
6418         }
6422 $.ui.plugin.add("resizable", "grid", {
6424         resize: function(event, ui) {
6425                 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
6426                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
6427                 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
6429                 if (/^(se|s|e)$/.test(a)) {
6430                         self.size.width = os.width + ox;
6431                         self.size.height = os.height + oy;
6432                 }
6433                 else if (/^(ne)$/.test(a)) {
6434                         self.size.width = os.width + ox;
6435                         self.size.height = os.height + oy;
6436                         self.position.top = op.top - oy;
6437                 }
6438                 else if (/^(sw)$/.test(a)) {
6439                         self.size.width = os.width + ox;
6440                         self.size.height = os.height + oy;
6441                         self.position.left = op.left - ox;
6442                 }
6443                 else {
6444                         self.size.width = os.width + ox;
6445                         self.size.height = os.height + oy;
6446                         self.position.top = op.top - oy;
6447                         self.position.left = op.left - ox;
6448                 }
6449         }
6453 var num = function(v) {
6454         return parseInt(v, 10) || 0;
6457 var isNumber = function(value) {
6458         return !isNaN(parseInt(value, 10));
6461 })(jQuery);
6463  * jQuery UI Dialog 1.7.2
6465  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
6466  * Dual licensed under the MIT (MIT-LICENSE.txt)
6467  * and GPL (GPL-LICENSE.txt) licenses.
6469  * http://docs.jquery.com/UI/Dialog
6471  * Depends:
6472  *      ui.core.js
6473  *      ui.draggable.js
6474  *      ui.resizable.js
6475  */
6476 (function($) {
6478 var setDataSwitch = {
6479                 dragStart: "start.draggable",
6480                 drag: "drag.draggable",
6481                 dragStop: "stop.draggable",
6482                 maxHeight: "maxHeight.resizable",
6483                 minHeight: "minHeight.resizable",
6484                 maxWidth: "maxWidth.resizable",
6485                 minWidth: "minWidth.resizable",
6486                 resizeStart: "start.resizable",
6487                 resize: "drag.resizable",
6488                 resizeStop: "stop.resizable"
6489         },
6490         
6491         uiDialogClasses =
6492                 'ui-dialog ' +
6493                 'ui-widget ' +
6494                 'ui-widget-content ' +
6495                 'ui-corner-all ';
6497 $.widget("ui.dialog", {
6499         _init: function() {
6500                 this.originalTitle = this.element.attr('title');
6502                 var self = this,
6503                         options = this.options,
6505                         title = options.title || this.originalTitle || '&nbsp;',
6506                         titleId = $.ui.dialog.getTitleId(this.element),
6508                         uiDialog = (this.uiDialog = $('<div/>'))
6509                                 .appendTo(document.body)
6510                                 .hide()
6511                                 .addClass(uiDialogClasses + options.dialogClass)
6512                                 .css({
6513                                         position: 'absolute',
6514                                         overflow: 'hidden',
6515                                         zIndex: options.zIndex
6516                                 })
6517                                 // setting tabIndex makes the div focusable
6518                                 // setting outline to 0 prevents a border on focus in Mozilla
6519                                 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
6520                                         (options.closeOnEscape && event.keyCode
6521                                                 && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
6522                                 })
6523                                 .attr({
6524                                         role: 'dialog',
6525                                         'aria-labelledby': titleId
6526                                 })
6527                                 .mousedown(function(event) {
6528                                         self.moveToTop(false, event);
6529                                 }),
6531                         uiDialogContent = this.element
6532                                 .show()
6533                                 .removeAttr('title')
6534                                 .addClass(
6535                                         'ui-dialog-content ' +
6536                                         'ui-widget-content')
6537                                 .appendTo(uiDialog),
6539                         uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
6540                                 .addClass(
6541                                         'ui-dialog-titlebar ' +
6542                                         'ui-widget-header ' +
6543                                         'ui-corner-all ' +
6544                                         'ui-helper-clearfix'
6545                                 )
6546                                 .prependTo(uiDialog),
6548                         uiDialogTitlebarClose = $('<a href="#"/>')
6549                                 .addClass(
6550                                         'ui-dialog-titlebar-close ' +
6551                                         'ui-corner-all'
6552                                 )
6553                                 .attr('role', 'button')
6554                                 .hover(
6555                                         function() {
6556                                                 uiDialogTitlebarClose.addClass('ui-state-hover');
6557                                         },
6558                                         function() {
6559                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');
6560                                         }
6561                                 )
6562                                 .focus(function() {
6563                                         uiDialogTitlebarClose.addClass('ui-state-focus');
6564                                 })
6565                                 .blur(function() {
6566                                         uiDialogTitlebarClose.removeClass('ui-state-focus');
6567                                 })
6568                                 .mousedown(function(ev) {
6569                                         ev.stopPropagation();
6570                                 })
6571                                 .click(function(event) {
6572                                         self.close(event);
6573                                         return false;
6574                                 })
6575                                 .appendTo(uiDialogTitlebar),
6577                         uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
6578                                 .addClass(
6579                                         'ui-icon ' +
6580                                         'ui-icon-closethick'
6581                                 )
6582                                 .text(options.closeText)
6583                                 .appendTo(uiDialogTitlebarClose),
6585                         uiDialogTitle = $('<span/>')
6586                                 .addClass('ui-dialog-title')
6587                                 .attr('id', titleId)
6588                                 .html(title)
6589                                 .prependTo(uiDialogTitlebar);
6591                 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
6593                 (options.draggable && $.fn.draggable && this._makeDraggable());
6594                 (options.resizable && $.fn.resizable && this._makeResizable());
6596                 this._createButtons(options.buttons);
6597                 this._isOpen = false;
6599                 (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
6600                 (options.autoOpen && this.open());
6601                 
6602         },
6604         destroy: function() {
6605                 (this.overlay && this.overlay.destroy());
6606                 this.uiDialog.hide();
6607                 this.element
6608                         .unbind('.dialog')
6609                         .removeData('dialog')
6610                         .removeClass('ui-dialog-content ui-widget-content')
6611                         .hide().appendTo('body');
6612                 this.uiDialog.remove();
6614                 (this.originalTitle && this.element.attr('title', this.originalTitle));
6615         },
6617         close: function(event) {
6618                 var self = this;
6619                 
6620                 if (false === self._trigger('beforeclose', event)) {
6621                         return;
6622                 }
6624                 (self.overlay && self.overlay.destroy());
6625                 self.uiDialog.unbind('keypress.ui-dialog');
6627                 (self.options.hide
6628                         ? self.uiDialog.hide(self.options.hide, function() {
6629                                 self._trigger('close', event);
6630                         })
6631                         : self.uiDialog.hide() && self._trigger('close', event));
6633                 $.ui.dialog.overlay.resize();
6635                 self._isOpen = false;
6636                 
6637                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6638                 if (self.options.modal) {
6639                         var maxZ = 0;
6640                         $('.ui-dialog').each(function() {
6641                                 if (this != self.uiDialog[0]) {
6642                                         maxZ = Math.max(maxZ, $(this).css('z-index'));
6643                                 }
6644                         });
6645                         $.ui.dialog.maxZ = maxZ;
6646                 }
6647         },
6649         isOpen: function() {
6650                 return this._isOpen;
6651         },
6653         // the force parameter allows us to move modal dialogs to their correct
6654         // position on open
6655         moveToTop: function(force, event) {
6657                 if ((this.options.modal && !force)
6658                         || (!this.options.stack && !this.options.modal)) {
6659                         return this._trigger('focus', event);
6660                 }
6661                 
6662                 if (this.options.zIndex > $.ui.dialog.maxZ) {
6663                         $.ui.dialog.maxZ = this.options.zIndex;
6664                 }
6665                 (this.overlay && this.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = ++$.ui.dialog.maxZ));
6667                 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
6668                 //  http://ui.jquery.com/bugs/ticket/3193
6669                 var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
6670                 this.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
6671                 this.element.attr(saveScroll);
6672                 this._trigger('focus', event);
6673         },
6675         open: function() {
6676                 if (this._isOpen) { return; }
6678                 var options = this.options,
6679                         uiDialog = this.uiDialog;
6681                 this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
6682                 (uiDialog.next().length && uiDialog.appendTo('body'));
6683                 this._size();
6684                 this._position(options.position);
6685                 uiDialog.show(options.show);
6686                 this.moveToTop(true);
6688                 // prevent tabbing out of modal dialogs
6689                 (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
6690                         if (event.keyCode != $.ui.keyCode.TAB) {
6691                                 return;
6692                         }
6694                         var tabbables = $(':tabbable', this),
6695                                 first = tabbables.filter(':first')[0],
6696                                 last  = tabbables.filter(':last')[0];
6698                         if (event.target == last && !event.shiftKey) {
6699                                 setTimeout(function() {
6700                                         first.focus();
6701                                 }, 1);
6702                         } else if (event.target == first && event.shiftKey) {
6703                                 setTimeout(function() {
6704                                         last.focus();
6705                                 }, 1);
6706                         }
6707                 }));
6709                 // set focus to the first tabbable element in the content area or the first button
6710                 // if there are no tabbable elements, set focus on the dialog itself
6711                 $([])
6712                         .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
6713                         .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
6714                         .add(uiDialog)
6715                         .filter(':first')
6716                         .focus();
6718                 this._trigger('open');
6719                 this._isOpen = true;
6720         },
6722         _createButtons: function(buttons) {
6723                 var self = this,
6724                         hasButtons = false,
6725                         uiDialogButtonPane = $('<div></div>')
6726                                 .addClass(
6727                                         'ui-dialog-buttonpane ' +
6728                                         'ui-widget-content ' +
6729                                         'ui-helper-clearfix'
6730                                 );
6732                 // if we already have a button pane, remove it
6733                 this.uiDialog.find('.ui-dialog-buttonpane').remove();
6735                 (typeof buttons == 'object' && buttons !== null &&
6736                         $.each(buttons, function() { return !(hasButtons = true); }));
6737                 if (hasButtons) {
6738                         $.each(buttons, function(name, fn) {
6739                                 $('<button type="button"></button>')
6740                                         .addClass(
6741                                                 'ui-state-default ' +
6742                                                 'ui-corner-all'
6743                                         )
6744                                         .text(name)
6745                                         .click(function() { fn.apply(self.element[0], arguments); })
6746                                         .hover(
6747                                                 function() {
6748                                                         $(this).addClass('ui-state-hover');
6749                                                 },
6750                                                 function() {
6751                                                         $(this).removeClass('ui-state-hover');
6752                                                 }
6753                                         )
6754                                         .focus(function() {
6755                                                 $(this).addClass('ui-state-focus');
6756                                         })
6757                                         .blur(function() {
6758                                                 $(this).removeClass('ui-state-focus');
6759                                         })
6760                                         .appendTo(uiDialogButtonPane);
6761                         });
6762                         uiDialogButtonPane.appendTo(this.uiDialog);
6763                 }
6764         },
6766         _makeDraggable: function() {
6767                 var self = this,
6768                         options = this.options,
6769                         heightBeforeDrag;
6771                 this.uiDialog.draggable({
6772                         cancel: '.ui-dialog-content',
6773                         handle: '.ui-dialog-titlebar',
6774                         containment: 'document',
6775                         start: function() {
6776                                 heightBeforeDrag = options.height;
6777                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6778                                 (options.dragStart && options.dragStart.apply(self.element[0], arguments));
6779                         },
6780                         drag: function() {
6781                                 (options.drag && options.drag.apply(self.element[0], arguments));
6782                         },
6783                         stop: function() {
6784                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6785                                 (options.dragStop && options.dragStop.apply(self.element[0], arguments));
6786                                 $.ui.dialog.overlay.resize();
6787                         }
6788                 });
6789         },
6791         _makeResizable: function(handles) {
6792                 handles = (handles === undefined ? this.options.resizable : handles);
6793                 var self = this,
6794                         options = this.options,
6795                         resizeHandles = typeof handles == 'string'
6796                                 ? handles
6797                                 : 'n,e,s,w,se,sw,ne,nw';
6799                 this.uiDialog.resizable({
6800                         cancel: '.ui-dialog-content',
6801                         alsoResize: this.element,
6802                         maxWidth: options.maxWidth,
6803                         maxHeight: options.maxHeight,
6804                         minWidth: options.minWidth,
6805                         minHeight: options.minHeight,
6806                         start: function() {
6807                                 $(this).addClass("ui-dialog-resizing");
6808                                 (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
6809                         },
6810                         resize: function() {
6811                                 (options.resize && options.resize.apply(self.element[0], arguments));
6812                         },
6813                         handles: resizeHandles,
6814                         stop: function() {
6815                                 $(this).removeClass("ui-dialog-resizing");
6816                                 options.height = $(this).height();
6817                                 options.width = $(this).width();
6818                                 (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
6819                                 $.ui.dialog.overlay.resize();
6820                         }
6821                 })
6822                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6823         },
6825         _position: function(pos) {
6826                 var wnd = $(window), doc = $(document),
6827                         pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
6828                         minTop = pTop;
6830                 if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
6831                         pos = [
6832                                 pos == 'right' || pos == 'left' ? pos : 'center',
6833                                 pos == 'top' || pos == 'bottom' ? pos : 'middle'
6834                         ];
6835                 }
6836                 if (pos.constructor != Array) {
6837                         pos = ['center', 'middle'];
6838                 }
6839                 if (pos[0].constructor == Number) {
6840                         pLeft += pos[0];
6841                 } else {
6842                         switch (pos[0]) {
6843                                 case 'left':
6844                                         pLeft += 0;
6845                                         break;
6846                                 case 'right':
6847                                         pLeft += wnd.width() - this.uiDialog.outerWidth();
6848                                         break;
6849                                 default:
6850                                 case 'center':
6851                                         pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
6852                         }
6853                 }
6854                 if (pos[1].constructor == Number) {
6855                         pTop += pos[1];
6856                 } else {
6857                         switch (pos[1]) {
6858                                 case 'top':
6859                                         pTop += 0;
6860                                         break;
6861                                 case 'bottom':
6862                                         pTop += wnd.height() - this.uiDialog.outerHeight();
6863                                         break;
6864                                 default:
6865                                 case 'middle':
6866                                         pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
6867                         }
6868                 }
6870                 // prevent the dialog from being too high (make sure the titlebar
6871                 // is accessible)
6872                 pTop = Math.max(pTop, minTop);
6873                 this.uiDialog.css({top: pTop, left: pLeft});
6874         },
6876         _setData: function(key, value){
6877                 (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
6878                 switch (key) {
6879                         case "buttons":
6880                                 this._createButtons(value);
6881                                 break;
6882                         case "closeText":
6883                                 this.uiDialogTitlebarCloseText.text(value);
6884                                 break;
6885                         case "dialogClass":
6886                                 this.uiDialog
6887                                         .removeClass(this.options.dialogClass)
6888                                         .addClass(uiDialogClasses + value);
6889                                 break;
6890                         case "draggable":
6891                                 (value
6892                                         ? this._makeDraggable()
6893                                         : this.uiDialog.draggable('destroy'));
6894                                 break;
6895                         case "height":
6896                                 this.uiDialog.height(value);
6897                                 break;
6898                         case "position":
6899                                 this._position(value);
6900                                 break;
6901                         case "resizable":
6902                                 var uiDialog = this.uiDialog,
6903                                         isResizable = this.uiDialog.is(':data(resizable)');
6905                                 // currently resizable, becoming non-resizable
6906                                 (isResizable && !value && uiDialog.resizable('destroy'));
6908                                 // currently resizable, changing handles
6909                                 (isResizable && typeof value == 'string' &&
6910                                         uiDialog.resizable('option', 'handles', value));
6912                                 // currently non-resizable, becoming resizable
6913                                 (isResizable || this._makeResizable(value));
6914                                 break;
6915                         case "title":
6916                                 $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
6917                                 break;
6918                         case "width":
6919                                 this.uiDialog.width(value);
6920                                 break;
6921                 }
6923                 $.widget.prototype._setData.apply(this, arguments);
6924         },
6926         _size: function() {
6927                 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6928                  * divs will both have width and height set, so we need to reset them
6929                  */
6930                 var options = this.options;
6932                 // reset content sizing
6933                 this.element.css({
6934                         height: 0,
6935                         minHeight: 0,
6936                         width: 'auto'
6937                 });
6939                 // reset wrapper sizing
6940                 // determine the height of all the non-content elements
6941                 var nonContentHeight = this.uiDialog.css({
6942                                 height: 'auto',
6943                                 width: options.width
6944                         })
6945                         .height();
6947                 this.element
6948                         .css({
6949                                 minHeight: Math.max(options.minHeight - nonContentHeight, 0),
6950                                 height: options.height == 'auto'
6951                                         ? 'auto'
6952                                         : Math.max(options.height - nonContentHeight, 0)
6953                         });
6954         }
6957 $.extend($.ui.dialog, {
6958         version: "1.7.2",
6959         defaults: {
6960                 autoOpen: true,
6961                 bgiframe: false,
6962                 buttons: {},
6963                 closeOnEscape: true,
6964                 closeText: 'close',
6965                 dialogClass: '',
6966                 draggable: true,
6967                 hide: null,
6968                 height: 'auto',
6969                 maxHeight: false,
6970                 maxWidth: false,
6971                 minHeight: 150,
6972                 minWidth: 150,
6973                 modal: false,
6974                 position: 'center',
6975                 resizable: true,
6976                 show: null,
6977                 stack: true,
6978                 title: '',
6979                 width: 300,
6980                 zIndex: 1000
6981         },
6983         getter: 'isOpen',
6985         uuid: 0,
6986         maxZ: 0,
6988         getTitleId: function($el) {
6989                 return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
6990         },
6992         overlay: function(dialog) {
6993                 this.$el = $.ui.dialog.overlay.create(dialog);
6994         }
6997 $.extend($.ui.dialog.overlay, {
6998         instances: [],
6999         maxZ: 0,
7000         events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
7001                 function(event) { return event + '.dialog-overlay'; }).join(' '),
7002         create: function(dialog) {
7003                 if (this.instances.length === 0) {
7004                         // prevent use of anchors and inputs
7005                         // we use a setTimeout in case the overlay is created from an
7006                         // event that we're going to be cancelling (see #2804)
7007                         setTimeout(function() {
7008                                 // handle $(el).dialog().dialog('close') (see #4065)
7009                                 if ($.ui.dialog.overlay.instances.length) {
7010                                         $(document).bind($.ui.dialog.overlay.events, function(event) {
7011                                                 var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0;
7012                                                 return (dialogZ > $.ui.dialog.overlay.maxZ);
7013                                         });
7014                                 }
7015                         }, 1);
7017                         // allow closing by pressing the escape key
7018                         $(document).bind('keydown.dialog-overlay', function(event) {
7019                                 (dialog.options.closeOnEscape && event.keyCode
7020                                                 && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
7021                         });
7023                         // handle window resize
7024                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
7025                 }
7027                 var $el = $('<div></div>').appendTo(document.body)
7028                         .addClass('ui-widget-overlay').css({
7029                                 width: this.width(),
7030                                 height: this.height()
7031                         });
7033                 (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
7035                 this.instances.push($el);
7036                 return $el;
7037         },
7039         destroy: function($el) {
7040                 this.instances.splice($.inArray(this.instances, $el), 1);
7042                 if (this.instances.length === 0) {
7043                         $([document, window]).unbind('.dialog-overlay');
7044                 }
7046                 $el.remove();
7047                 
7048                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
7049                 var maxZ = 0;
7050                 $.each(this.instances, function() {
7051                         maxZ = Math.max(maxZ, this.css('z-index'));
7052                 });
7053                 this.maxZ = maxZ;
7054         },
7056         height: function() {
7057                 // handle IE 6
7058                 if ($.browser.msie && $.browser.version < 7) {
7059                         var scrollHeight = Math.max(
7060                                 document.documentElement.scrollHeight,
7061                                 document.body.scrollHeight
7062                         );
7063                         var offsetHeight = Math.max(
7064                                 document.documentElement.offsetHeight,
7065                                 document.body.offsetHeight
7066                         );
7068                         if (scrollHeight < offsetHeight) {
7069                                 return $(window).height() + 'px';
7070                         } else {
7071                                 return scrollHeight + 'px';
7072                         }
7073                 // handle "good" browsers
7074                 } else {
7075                         return $(document).height() + 'px';
7076                 }
7077         },
7079         width: function() {
7080                 // handle IE 6
7081                 if ($.browser.msie && $.browser.version < 7) {
7082                         var scrollWidth = Math.max(
7083                                 document.documentElement.scrollWidth,
7084                                 document.body.scrollWidth
7085                         );
7086                         var offsetWidth = Math.max(
7087                                 document.documentElement.offsetWidth,
7088                                 document.body.offsetWidth
7089                         );
7091                         if (scrollWidth < offsetWidth) {
7092                                 return $(window).width() + 'px';
7093                         } else {
7094                                 return scrollWidth + 'px';
7095                         }
7096                 // handle "good" browsers
7097                 } else {
7098                         return $(document).width() + 'px';
7099                 }
7100         },
7102         resize: function() {
7103                 /* If the dialog is draggable and the user drags it past the
7104                  * right edge of the window, the document becomes wider so we
7105                  * need to stretch the overlay. If the user then drags the
7106                  * dialog back to the left, the document will become narrower,
7107                  * so we need to shrink the overlay to the appropriate size.
7108                  * This is handled by shrinking the overlay before setting it
7109                  * to the full document size.
7110                  */
7111                 var $overlays = $([]);
7112                 $.each($.ui.dialog.overlay.instances, function() {
7113                         $overlays = $overlays.add(this);
7114                 });
7116                 $overlays.css({
7117                         width: 0,
7118                         height: 0
7119                 }).css({
7120                         width: $.ui.dialog.overlay.width(),
7121                         height: $.ui.dialog.overlay.height()
7122                 });
7123         }
7126 $.extend($.ui.dialog.overlay.prototype, {
7127         destroy: function() {
7128                 $.ui.dialog.overlay.destroy(this.$el);
7129         }
7132 })(jQuery);
7134  * jQuery UI Tabs 1.7.2
7136  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
7137  * Dual licensed under the MIT (MIT-LICENSE.txt)
7138  * and GPL (GPL-LICENSE.txt) licenses.
7140  * http://docs.jquery.com/UI/Tabs
7142  * Depends:
7143  *      ui.core.js
7144  */
7145 (function($) {
7147 $.widget("ui.tabs", {
7149         _init: function() {
7150                 if (this.options.deselectable !== undefined) {
7151                         this.options.collapsible = this.options.deselectable;
7152                 }
7153                 this._tabify(true);
7154         },
7156         _setData: function(key, value) {
7157                 if (key == 'selected') {
7158                         if (this.options.collapsible && value == this.options.selected) {
7159                                 return;
7160                         }
7161                         this.select(value);
7162                 }
7163                 else {
7164                         this.options[key] = value;
7165                         if (key == 'deselectable') {
7166                                 this.options.collapsible = value;
7167                         }
7168                         this._tabify();
7169                 }
7170         },
7172         _tabId: function(a) {
7173                 return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
7174                         this.options.idPrefix + $.data(a);
7175         },
7177         _sanitizeSelector: function(hash) {
7178                 return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
7179         },
7181         _cookie: function() {
7182                 var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
7183                 return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
7184         },
7186         _ui: function(tab, panel) {
7187                 return {
7188                         tab: tab,
7189                         panel: panel,
7190                         index: this.anchors.index(tab)
7191                 };
7192         },
7194         _cleanup: function() {
7195                 // restore all former loading tabs labels
7196                 this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')
7197                                 .find('span:data(label.tabs)')
7198                                 .each(function() {
7199                                         var el = $(this);
7200                                         el.html(el.data('label.tabs')).removeData('label.tabs');
7201                                 });
7202         },
7204         _tabify: function(init) {
7206                 this.list = this.element.children('ul:first');
7207                 this.lis = $('li:has(a[href])', this.list);
7208                 this.anchors = this.lis.map(function() { return $('a', this)[0]; });
7209                 this.panels = $([]);
7211                 var self = this, o = this.options;
7213                 var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
7214                 this.anchors.each(function(i, a) {
7215                         var href = $(a).attr('href');
7217                         // For dynamically created HTML that contains a hash as href IE < 8 expands
7218                         // such href to the full page url with hash and then misinterprets tab as ajax.
7219                         // Same consideration applies for an added tab with a fragment identifier
7220                         // since a[href=#fragment-identifier] does unexpectedly not match.
7221                         // Thus normalize href attribute...
7222                         var hrefBase = href.split('#')[0], baseEl;
7223                         if (hrefBase && (hrefBase === location.toString().split('#')[0] ||
7224                                         (baseEl = $('base')[0]) && hrefBase === baseEl.href)) {
7225                                 href = a.hash;
7226                                 a.href = href;
7227                         }
7229                         // inline tab
7230                         if (fragmentId.test(href)) {
7231                                 self.panels = self.panels.add(self._sanitizeSelector(href));
7232                         }
7234                         // remote tab
7235                         else if (href != '#') { // prevent loading the page itself if href is just "#"
7236                                 $.data(a, 'href.tabs', href); // required for restore on destroy
7238                                 // TODO until #3808 is fixed strip fragment identifier from url
7239                                 // (IE fails to load from such url)
7240                                 $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
7242                                 var id = self._tabId(a);
7243                                 a.href = '#' + id;
7244                                 var $panel = $('#' + id);
7245                                 if (!$panel.length) {
7246                                         $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
7247                                                 .insertAfter(self.panels[i - 1] || self.list);
7248                                         $panel.data('destroy.tabs', true);
7249                                 }
7250                                 self.panels = self.panels.add($panel);
7251                         }
7253                         // invalid tab href
7254                         else {
7255                                 o.disabled.push(i);
7256                         }
7257                 });
7259                 // initialization from scratch
7260                 if (init) {
7262                         // attach necessary classes for styling
7263                         this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
7264                         this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
7265                         this.lis.addClass('ui-state-default ui-corner-top');
7266                         this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
7268                         // Selected tab
7269                         // use "selected" option or try to retrieve:
7270                         // 1. from fragment identifier in url
7271                         // 2. from cookie
7272                         // 3. from selected class attribute on <li>
7273                         if (o.selected === undefined) {
7274                                 if (location.hash) {
7275                                         this.anchors.each(function(i, a) {
7276                                                 if (a.hash == location.hash) {
7277                                                         o.selected = i;
7278                                                         return false; // break
7279                                                 }
7280                                         });
7281                                 }
7282                                 if (typeof o.selected != 'number' && o.cookie) {
7283                                         o.selected = parseInt(self._cookie(), 10);
7284                                 }
7285                                 if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
7286                                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
7287                                 }
7288                                 o.selected = o.selected || 0;
7289                         }
7290                         else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
7291                                 o.selected = -1;
7292                         }
7294                         // sanity check - default to first tab...
7295                         o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;
7297                         // Take disabling tabs via class attribute from HTML
7298                         // into account and update option properly.
7299                         // A selected tab cannot become disabled.
7300                         o.disabled = $.unique(o.disabled.concat(
7301                                 $.map(this.lis.filter('.ui-state-disabled'),
7302                                         function(n, i) { return self.lis.index(n); } )
7303                         )).sort();
7305                         if ($.inArray(o.selected, o.disabled) != -1) {
7306                                 o.disabled.splice($.inArray(o.selected, o.disabled), 1);
7307                         }
7309                         // highlight selected tab
7310                         this.panels.addClass('ui-tabs-hide');
7311                         this.lis.removeClass('ui-tabs-selected ui-state-active');
7312                         if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
7313                                 this.panels.eq(o.selected).removeClass('ui-tabs-hide');
7314                                 this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');
7316                                 // seems to be expected behavior that the show callback is fired
7317                                 self.element.queue("tabs", function() {
7318                                         self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
7319                                 });
7320                                 
7321                                 this.load(o.selected);
7322                         }
7324                         // clean up to avoid memory leaks in certain versions of IE 6
7325                         $(window).bind('unload', function() {
7326                                 self.lis.add(self.anchors).unbind('.tabs');
7327                                 self.lis = self.anchors = self.panels = null;
7328                         });
7330                 }
7331                 // update selected after add/remove
7332                 else {
7333                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
7334                 }
7336                 // update collapsible
7337                 this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');
7339                 // set or update cookie after init and add/remove respectively
7340                 if (o.cookie) {
7341                         this._cookie(o.selected, o.cookie);
7342                 }
7344                 // disable tabs
7345                 for (var i = 0, li; (li = this.lis[i]); i++) {
7346                         $(li)[$.inArray(i, o.disabled) != -1 &&
7347                                 !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
7348                 }
7350                 // reset cache if switching from cached to not cached
7351                 if (o.cache === false) {
7352                         this.anchors.removeData('cache.tabs');
7353                 }
7355                 // remove all handlers before, tabify may run on existing tabs after add or option change
7356                 this.lis.add(this.anchors).unbind('.tabs');
7358                 if (o.event != 'mouseover') {
7359                         var addState = function(state, el) {
7360                                 if (el.is(':not(.ui-state-disabled)')) {
7361                                         el.addClass('ui-state-' + state);
7362                                 }
7363                         };
7364                         var removeState = function(state, el) {
7365                                 el.removeClass('ui-state-' + state);
7366                         };
7367                         this.lis.bind('mouseover.tabs', function() {
7368                                 addState('hover', $(this));
7369                         });
7370                         this.lis.bind('mouseout.tabs', function() {
7371                                 removeState('hover', $(this));
7372                         });
7373                         this.anchors.bind('focus.tabs', function() {
7374                                 addState('focus', $(this).closest('li'));
7375                         });
7376                         this.anchors.bind('blur.tabs', function() {
7377                                 removeState('focus', $(this).closest('li'));
7378                         });
7379                 }
7381                 // set up animations
7382                 var hideFx, showFx;
7383                 if (o.fx) {
7384                         if ($.isArray(o.fx)) {
7385                                 hideFx = o.fx[0];
7386                                 showFx = o.fx[1];
7387                         }
7388                         else {
7389                                 hideFx = showFx = o.fx;
7390                         }
7391                 }
7393                 // Reset certain styles left over from animation
7394                 // and prevent IE's ClearType bug...
7395                 function resetStyle($el, fx) {
7396                         $el.css({ display: '' });
7397                         if ($.browser.msie && fx.opacity) {
7398                                 $el[0].style.removeAttribute('filter');
7399                         }
7400                 }
7402                 // Show a tab...
7403                 var showTab = showFx ?
7404                         function(clicked, $show) {
7405                                 $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
7406                                 $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
7407                                         .animate(showFx, showFx.duration || 'normal', function() {
7408                                                 resetStyle($show, showFx);
7409                                                 self._trigger('show', null, self._ui(clicked, $show[0]));
7410                                         });
7411                         } :
7412                         function(clicked, $show) {
7413                                 $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
7414                                 $show.removeClass('ui-tabs-hide');
7415                                 self._trigger('show', null, self._ui(clicked, $show[0]));
7416                         };
7418                 // Hide a tab, $show is optional...
7419                 var hideTab = hideFx ?
7420                         function(clicked, $hide) {
7421                                 $hide.animate(hideFx, hideFx.duration || 'normal', function() {
7422                                         self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
7423                                         $hide.addClass('ui-tabs-hide');
7424                                         resetStyle($hide, hideFx);
7425                                         self.element.dequeue("tabs");
7426                                 });
7427                         } :
7428                         function(clicked, $hide, $show) {
7429                                 self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
7430                                 $hide.addClass('ui-tabs-hide');
7431                                 self.element.dequeue("tabs");
7432                         };
7434                 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7435                 this.anchors.bind(o.event + '.tabs', function() {
7436                         var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
7437                                         $show = $(self._sanitizeSelector(this.hash));
7439                         // If tab is already selected and not collapsible or tab disabled or
7440                         // or is already loading or click callback returns false stop here.
7441                         // Check if click handler returns false last so that it is not executed
7442                         // for a disabled or loading tab!
7443                         if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
7444                                 $li.hasClass('ui-state-disabled') ||
7445                                 $li.hasClass('ui-state-processing') ||
7446                                 self._trigger('select', null, self._ui(this, $show[0])) === false) {
7447                                 this.blur();
7448                                 return false;
7449                         }
7451                         o.selected = self.anchors.index(this);
7453                         self.abort();
7455                         // if tab may be closed
7456                         if (o.collapsible) {
7457                                 if ($li.hasClass('ui-tabs-selected')) {
7458                                         o.selected = -1;
7460                                         if (o.cookie) {
7461                                                 self._cookie(o.selected, o.cookie);
7462                                         }
7464                                         self.element.queue("tabs", function() {
7465                                                 hideTab(el, $hide);
7466                                         }).dequeue("tabs");
7467                                         
7468                                         this.blur();
7469                                         return false;
7470                                 }
7471                                 else if (!$hide.length) {
7472                                         if (o.cookie) {
7473                                                 self._cookie(o.selected, o.cookie);
7474                                         }
7475                                         
7476                                         self.element.queue("tabs", function() {
7477                                                 showTab(el, $show);
7478                                         });
7480                                         self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7481                                         
7482                                         this.blur();
7483                                         return false;
7484                                 }
7485                         }
7487                         if (o.cookie) {
7488                                 self._cookie(o.selected, o.cookie);
7489                         }
7491                         // show new tab
7492                         if ($show.length) {
7493                                 if ($hide.length) {
7494                                         self.element.queue("tabs", function() {
7495                                                 hideTab(el, $hide);
7496                                         });
7497                                 }
7498                                 self.element.queue("tabs", function() {
7499                                         showTab(el, $show);
7500                                 });
7501                                 
7502                                 self.load(self.anchors.index(this));
7503                         }
7504                         else {
7505                                 throw 'jQuery UI Tabs: Mismatching fragment identifier.';
7506                         }
7508                         // Prevent IE from keeping other link focussed when using the back button
7509                         // and remove dotted border from clicked link. This is controlled via CSS
7510                         // in modern browsers; blur() removes focus from address bar in Firefox
7511                         // which can become a usability and annoying problem with tabs('rotate').
7512                         if ($.browser.msie) {
7513                                 this.blur();
7514                         }
7516                 });
7518                 // disable click in any case
7519                 this.anchors.bind('click.tabs', function(){return false;});
7521         },
7523         destroy: function() {
7524                 var o = this.options;
7526                 this.abort();
7527                 
7528                 this.element.unbind('.tabs')
7529                         .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
7530                         .removeData('tabs');
7532                 this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
7534                 this.anchors.each(function() {
7535                         var href = $.data(this, 'href.tabs');
7536                         if (href) {
7537                                 this.href = href;
7538                         }
7539                         var $this = $(this).unbind('.tabs');
7540                         $.each(['href', 'load', 'cache'], function(i, prefix) {
7541                                 $this.removeData(prefix + '.tabs');
7542                         });
7543                 });
7545                 this.lis.unbind('.tabs').add(this.panels).each(function() {
7546                         if ($.data(this, 'destroy.tabs')) {
7547                                 $(this).remove();
7548                         }
7549                         else {
7550                                 $(this).removeClass([
7551                                         'ui-state-default',
7552                                         'ui-corner-top',
7553                                         'ui-tabs-selected',
7554                                         'ui-state-active',
7555                                         'ui-state-hover',
7556                                         'ui-state-focus',
7557                                         'ui-state-disabled',
7558                                         'ui-tabs-panel',
7559                                         'ui-widget-content',
7560                                         'ui-corner-bottom',
7561                                         'ui-tabs-hide'
7562                                 ].join(' '));
7563                         }
7564                 });
7566                 if (o.cookie) {
7567                         this._cookie(null, o.cookie);
7568                 }
7569         },
7571         add: function(url, label, index) {
7572                 if (index === undefined) {
7573                         index = this.anchors.length; // append by default
7574                 }
7576                 var self = this, o = this.options,
7577                         $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),
7578                         id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);
7580                 $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
7582                 // try to find an existing element before creating a new one
7583                 var $panel = $('#' + id);
7584                 if (!$panel.length) {
7585                         $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
7586                 }
7587                 $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
7589                 if (index >= this.lis.length) {
7590                         $li.appendTo(this.list);
7591                         $panel.appendTo(this.list[0].parentNode);
7592                 }
7593                 else {
7594                         $li.insertBefore(this.lis[index]);
7595                         $panel.insertBefore(this.panels[index]);
7596                 }
7598                 o.disabled = $.map(o.disabled,
7599                         function(n, i) { return n >= index ? ++n : n; });
7601                 this._tabify();
7603                 if (this.anchors.length == 1) { // after tabify
7604                         $li.addClass('ui-tabs-selected ui-state-active');
7605                         $panel.removeClass('ui-tabs-hide');
7606                         this.element.queue("tabs", function() {
7607                                 self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
7608                         });
7609                                 
7610                         this.load(0);
7611                 }
7613                 // callback
7614                 this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
7615         },
7617         remove: function(index) {
7618                 var o = this.options, $li = this.lis.eq(index).remove(),
7619                         $panel = this.panels.eq(index).remove();
7621                 // If selected tab was removed focus tab to the right or
7622                 // in case the last tab was removed the tab to the left.
7623                 if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
7624                         this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
7625                 }
7627                 o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
7628                         function(n, i) { return n >= index ? --n : n; });
7630                 this._tabify();
7632                 // callback
7633                 this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
7634         },
7636         enable: function(index) {
7637                 var o = this.options;
7638                 if ($.inArray(index, o.disabled) == -1) {
7639                         return;
7640                 }
7642                 this.lis.eq(index).removeClass('ui-state-disabled');
7643                 o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
7645                 // callback
7646                 this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
7647         },
7649         disable: function(index) {
7650                 var self = this, o = this.options;
7651                 if (index != o.selected) { // cannot disable already selected tab
7652                         this.lis.eq(index).addClass('ui-state-disabled');
7654                         o.disabled.push(index);
7655                         o.disabled.sort();
7657                         // callback
7658                         this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
7659                 }
7660         },
7662         select: function(index) {
7663                 if (typeof index == 'string') {
7664                         index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
7665                 }
7666                 else if (index === null) { // usage of null is deprecated, TODO remove in next release
7667                         index = -1;
7668                 }
7669                 if (index == -1 && this.options.collapsible) {
7670                         index = this.options.selected;
7671                 }
7673                 this.anchors.eq(index).trigger(this.options.event + '.tabs');
7674         },
7676         load: function(index) {
7677                 var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs');
7679                 this.abort();
7681                 // not remote or from cache
7682                 if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {
7683                         this.element.dequeue("tabs");
7684                         return;
7685                 }
7687                 // load remote from here on
7688                 this.lis.eq(index).addClass('ui-state-processing');
7690                 if (o.spinner) {
7691                         var span = $('span', a);
7692                         span.data('label.tabs', span.html()).html(o.spinner);
7693                 }
7695                 this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
7696                         url: url,
7697                         success: function(r, s) {
7698                                 $(self._sanitizeSelector(a.hash)).html(r);
7700                                 // take care of tab labels
7701                                 self._cleanup();
7703                                 if (o.cache) {
7704                                         $.data(a, 'cache.tabs', true); // if loaded once do not load them again
7705                                 }
7707                                 // callbacks
7708                                 self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
7709                                 try {
7710                                         o.ajaxOptions.success(r, s);
7711                                 }
7712                                 catch (e) {}
7714                                 // last, so that load event is fired before show...
7715                                 self.element.dequeue("tabs");
7716                         }
7717                 }));
7718         },
7720         abort: function() {
7721                 // stop possibly running animations
7722                 this.element.queue([]);
7723                 this.panels.stop(false, true);
7725                 // terminate pending requests from other tabs
7726                 if (this.xhr) {
7727                         this.xhr.abort();
7728                         delete this.xhr;
7729                 }
7731                 // take care of tab labels
7732                 this._cleanup();
7734         },
7736         url: function(index, url) {
7737                 this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
7738         },
7740         length: function() {
7741                 return this.anchors.length;
7742         }
7746 $.extend($.ui.tabs, {
7747         version: '1.7.2',
7748         getter: 'length',
7749         defaults: {
7750                 ajaxOptions: null,
7751                 cache: false,
7752                 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
7753                 collapsible: false,
7754                 disabled: [],
7755                 event: 'click',
7756                 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
7757                 idPrefix: 'ui-tabs-',
7758                 panelTemplate: '<div></div>',
7759                 spinner: '<em>Loading&#8230;</em>',
7760                 tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
7761         }
7765  * Tabs Extensions
7766  */
7769  * Rotate
7770  */
7771 $.extend($.ui.tabs.prototype, {
7772         rotation: null,
7773         rotate: function(ms, continuing) {
7775                 var self = this, o = this.options;
7776                 
7777                 var rotate = self._rotate || (self._rotate = function(e) {
7778                         clearTimeout(self.rotation);
7779                         self.rotation = setTimeout(function() {
7780                                 var t = o.selected;
7781                                 self.select( ++t < self.anchors.length ? t : 0 );
7782                         }, ms);
7783                         
7784                         if (e) {
7785                                 e.stopPropagation();
7786                         }
7787                 });
7788                 
7789                 var stop = self._unrotate || (self._unrotate = !continuing ?
7790                         function(e) {
7791                                 if (e.clientX) { // in case of a true click
7792                                         self.rotate(null);
7793                                 }
7794                         } :
7795                         function(e) {
7796                                 t = o.selected;
7797                                 rotate();
7798                         });
7800                 // start rotation
7801                 if (ms) {
7802                         this.element.bind('tabsshow', rotate);
7803                         this.anchors.bind(o.event + '.tabs', stop);
7804                         rotate();
7805                 }
7806                 // stop rotation
7807                 else {
7808                         clearTimeout(self.rotation);
7809                         this.element.unbind('tabsshow', rotate);
7810                         this.anchors.unbind(o.event + '.tabs', stop);
7811                         delete this._rotate;
7812                         delete this._unrotate;
7813                 }
7814         }
7817 })(jQuery);
7819  * jQuery UI Datepicker 1.7.2
7821  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
7822  * Dual licensed under the MIT (MIT-LICENSE.txt)
7823  * and GPL (GPL-LICENSE.txt) licenses.
7825  * http://docs.jquery.com/UI/Datepicker
7827  * Depends:
7828  *      ui.core.js
7829  */
7831 (function($) { // hide the namespace
7833 $.extend($.ui, { datepicker: { version: "1.7.2" } });
7835 var PROP_NAME = 'datepicker';
7837 /* Date picker manager.
7838    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7839    Settings for (groups of) date pickers are maintained in an instance object,
7840    allowing multiple different settings on the same page. */
7842 function Datepicker() {
7843         this.debug = false; // Change this to true to start debugging
7844         this._curInst = null; // The current instance in use
7845         this._keyEvent = false; // If the last event was a key event
7846         this._disabledInputs = []; // List of date picker inputs that have been disabled
7847         this._datepickerShowing = false; // True if the popup picker is showing , false if not
7848         this._inDialog = false; // True if showing within a "dialog", false if not
7849         this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7850         this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7851         this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7852         this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7853         this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7854         this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7855         this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7856         this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7857         this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7858         this.regional = []; // Available regional settings, indexed by language code
7859         this.regional[''] = { // Default regional settings
7860                 closeText: 'Done', // Display text for close link
7861                 prevText: 'Prev', // Display text for previous month link
7862                 nextText: 'Next', // Display text for next month link
7863                 currentText: 'Today', // Display text for current month link
7864                 monthNames: ['January','February','March','April','May','June',
7865                         'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7866                 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7867                 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7868                 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7869                 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7870                 dateFormat: 'mm/dd/yy', // See format options on parseDate
7871                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7872                 isRTL: false // True if right-to-left language, false if left-to-right
7873         };
7874         this._defaults = { // Global defaults for all the date picker instances
7875                 showOn: 'focus', // 'focus' for popup on focus,
7876                         // 'button' for trigger button, or 'both' for either
7877                 showAnim: 'show', // Name of jQuery animation for popup
7878                 showOptions: {}, // Options for enhanced animations
7879                 defaultDate: null, // Used when field is blank: actual date,
7880                         // +/-number for offset from today, null for today
7881                 appendText: '', // Display text following the input box, e.g. showing the format
7882                 buttonText: '...', // Text for trigger button
7883                 buttonImage: '', // URL for trigger button image
7884                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7885                 hideIfNoPrevNext: false, // True to hide next/previous month links
7886                         // if not applicable, false to just disable them
7887                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7888                 gotoCurrent: false, // True if today link goes back to current selection instead
7889                 changeMonth: false, // True if month can be selected directly, false if only prev/next
7890                 changeYear: false, // True if year can be selected directly, false if only prev/next
7891                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7892                 yearRange: '-10:+10', // Range of years to display in drop-down,
7893                         // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
7894                 showOtherMonths: false, // True to show dates in other months, false to leave blank
7895                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7896                         // takes a Date and returns the number of the week for it
7897                 shortYearCutoff: '+10', // Short year values < this are in the current century,
7898                         // > this are in the previous century,
7899                         // string value starting with '+' for current year + value
7900                 minDate: null, // The earliest selectable date, or null for no limit
7901                 maxDate: null, // The latest selectable date, or null for no limit
7902                 duration: 'normal', // Duration of display/closure
7903                 beforeShowDay: null, // Function that takes a date and returns an array with
7904                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7905                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7906                 beforeShow: null, // Function that takes an input field and
7907                         // returns a set of custom settings for the date picker
7908                 onSelect: null, // Define a callback function when a date is selected
7909                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7910                 onClose: null, // Define a callback function when the datepicker is closed
7911                 numberOfMonths: 1, // Number of months to show at a time
7912                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7913                 stepMonths: 1, // Number of months to step back/forward
7914                 stepBigMonths: 12, // Number of months to step back/forward for the big links
7915                 altField: '', // Selector for an alternate field to store selected dates into
7916                 altFormat: '', // The date format to use for the alternate field
7917                 constrainInput: true, // The input is constrained by the current date format
7918                 showButtonPanel: false // True to show button panel, false to not show it
7919         };
7920         $.extend(this._defaults, this.regional['']);
7921         this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
7924 $.extend(Datepicker.prototype, {
7925         /* Class name added to elements to indicate already configured with a date picker. */
7926         markerClassName: 'hasDatepicker',
7928         /* Debug logging (if enabled). */
7929         log: function () {
7930                 if (this.debug)
7931                         console.log.apply('', arguments);
7932         },
7934         /* Override the default settings for all instances of the date picker.
7935            @param  settings  object - the new settings to use as defaults (anonymous object)
7936            @return the manager object */
7937         setDefaults: function(settings) {
7938                 extendRemove(this._defaults, settings || {});
7939                 return this;
7940         },
7942         /* Attach the date picker to a jQuery selection.
7943            @param  target    element - the target input field or division or span
7944            @param  settings  object - the new settings to use for this date picker instance (anonymous) */
7945         _attachDatepicker: function(target, settings) {
7946                 // check for settings on the control itself - in namespace 'date:'
7947                 var inlineSettings = null;
7948                 for (var attrName in this._defaults) {
7949                         var attrValue = target.getAttribute('date:' + attrName);
7950                         if (attrValue) {
7951                                 inlineSettings = inlineSettings || {};
7952                                 try {
7953                                         inlineSettings[attrName] = eval(attrValue);
7954                                 } catch (err) {
7955                                         inlineSettings[attrName] = attrValue;
7956                                 }
7957                         }
7958                 }
7959                 var nodeName = target.nodeName.toLowerCase();
7960                 var inline = (nodeName == 'div' || nodeName == 'span');
7961                 if (!target.id)
7962                         target.id = 'dp' + (++this.uuid);
7963                 var inst = this._newInst($(target), inline);
7964                 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7965                 if (nodeName == 'input') {
7966                         this._connectDatepicker(target, inst);
7967                 } else if (inline) {
7968                         this._inlineDatepicker(target, inst);
7969                 }
7970         },
7972         /* Create a new instance object. */
7973         _newInst: function(target, inline) {
7974                 var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
7975                 return {id: id, input: target, // associated target
7976                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7977                         drawMonth: 0, drawYear: 0, // month being drawn
7978                         inline: inline, // is datepicker inline or not
7979                         dpDiv: (!inline ? this.dpDiv : // presentation div
7980                         $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
7981         },
7983         /* Attach the date picker to an input field. */
7984         _connectDatepicker: function(target, inst) {
7985                 var input = $(target);
7986                 inst.append = $([]);
7987                 inst.trigger = $([]);
7988                 if (input.hasClass(this.markerClassName))
7989                         return;
7990                 var appendText = this._get(inst, 'appendText');
7991                 var isRTL = this._get(inst, 'isRTL');
7992                 if (appendText) {
7993                         inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
7994                         input[isRTL ? 'before' : 'after'](inst.append);
7995                 }
7996                 var showOn = this._get(inst, 'showOn');
7997                 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
7998                         input.focus(this._showDatepicker);
7999                 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8000                         var buttonText = this._get(inst, 'buttonText');
8001                         var buttonImage = this._get(inst, 'buttonImage');
8002                         inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8003                                 $('<img/>').addClass(this._triggerClass).
8004                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8005                                 $('<button type="button"></button>').addClass(this._triggerClass).
8006                                         html(buttonImage == '' ? buttonText : $('<img/>').attr(
8007                                         { src:buttonImage, alt:buttonText, title:buttonText })));
8008                         input[isRTL ? 'before' : 'after'](inst.trigger);
8009                         inst.trigger.click(function() {
8010                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
8011                                         $.datepicker._hideDatepicker();
8012                                 else
8013                                         $.datepicker._showDatepicker(target);
8014                                 return false;
8015                         });
8016                 }
8017                 input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
8018                         bind("setData.datepicker", function(event, key, value) {
8019                                 inst.settings[key] = value;
8020                         }).bind("getData.datepicker", function(event, key) {
8021                                 return this._get(inst, key);
8022                         });
8023                 $.data(target, PROP_NAME, inst);
8024         },
8026         /* Attach an inline date picker to a div. */
8027         _inlineDatepicker: function(target, inst) {
8028                 var divSpan = $(target);
8029                 if (divSpan.hasClass(this.markerClassName))
8030                         return;
8031                 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8032                         bind("setData.datepicker", function(event, key, value){
8033                                 inst.settings[key] = value;
8034                         }).bind("getData.datepicker", function(event, key){
8035                                 return this._get(inst, key);
8036                         });
8037                 $.data(target, PROP_NAME, inst);
8038                 this._setDate(inst, this._getDefaultDate(inst));
8039                 this._updateDatepicker(inst);
8040                 this._updateAlternate(inst);
8041         },
8043         /* Pop-up the date picker in a "dialog" box.
8044            @param  input     element - ignored
8045            @param  dateText  string - the initial date to display (in the current format)
8046            @param  onSelect  function - the function(dateText) to call when a date is selected
8047            @param  settings  object - update the dialog date picker instance's settings (anonymous object)
8048            @param  pos       int[2] - coordinates for the dialog's position within the screen or
8049                              event - with x/y coordinates or
8050                              leave empty for default (screen centre)
8051            @return the manager object */
8052         _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
8053                 var inst = this._dialogInst; // internal instance
8054                 if (!inst) {
8055                         var id = 'dp' + (++this.uuid);
8056                         this._dialogInput = $('<input type="text" id="' + id +
8057                                 '" size="1" style="position: absolute; top: -100px;"/>');
8058                         this._dialogInput.keydown(this._doKeyDown);
8059                         $('body').append(this._dialogInput);
8060                         inst = this._dialogInst = this._newInst(this._dialogInput, false);
8061                         inst.settings = {};
8062                         $.data(this._dialogInput[0], PROP_NAME, inst);
8063                 }
8064                 extendRemove(inst.settings, settings || {});
8065                 this._dialogInput.val(dateText);
8067                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8068                 if (!this._pos) {
8069                         var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
8070                         var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
8071                         var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8072                         var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8073                         this._pos = // should use actual width/height below
8074                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8075                 }
8077                 // move input on screen for focus, but hidden behind dialog
8078                 this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
8079                 inst.settings.onSelect = onSelect;
8080                 this._inDialog = true;
8081                 this.dpDiv.addClass(this._dialogClass);
8082                 this._showDatepicker(this._dialogInput[0]);
8083                 if ($.blockUI)
8084                         $.blockUI(this.dpDiv);
8085                 $.data(this._dialogInput[0], PROP_NAME, inst);
8086                 return this;
8087         },
8089         /* Detach a datepicker from its control.
8090            @param  target    element - the target input field or division or span */
8091         _destroyDatepicker: function(target) {
8092                 var $target = $(target);
8093                 var inst = $.data(target, PROP_NAME);
8094                 if (!$target.hasClass(this.markerClassName)) {
8095                         return;
8096                 }
8097                 var nodeName = target.nodeName.toLowerCase();
8098                 $.removeData(target, PROP_NAME);
8099                 if (nodeName == 'input') {
8100                         inst.append.remove();
8101                         inst.trigger.remove();
8102                         $target.removeClass(this.markerClassName).
8103                                 unbind('focus', this._showDatepicker).
8104                                 unbind('keydown', this._doKeyDown).
8105                                 unbind('keypress', this._doKeyPress);
8106                 } else if (nodeName == 'div' || nodeName == 'span')
8107                         $target.removeClass(this.markerClassName).empty();
8108         },
8110         /* Enable the date picker to a jQuery selection.
8111            @param  target    element - the target input field or division or span */
8112         _enableDatepicker: function(target) {
8113                 var $target = $(target);
8114                 var inst = $.data(target, PROP_NAME);
8115                 if (!$target.hasClass(this.markerClassName)) {
8116                         return;
8117                 }
8118                 var nodeName = target.nodeName.toLowerCase();
8119                 if (nodeName == 'input') {
8120                         target.disabled = false;
8121                         inst.trigger.filter('button').
8122                                 each(function() { this.disabled = false; }).end().
8123                                 filter('img').css({opacity: '1.0', cursor: ''});
8124                 }
8125                 else if (nodeName == 'div' || nodeName == 'span') {
8126                         var inline = $target.children('.' + this._inlineClass);
8127                         inline.children().removeClass('ui-state-disabled');
8128                 }
8129                 this._disabledInputs = $.map(this._disabledInputs,
8130                         function(value) { return (value == target ? null : value); }); // delete entry
8131         },
8133         /* Disable the date picker to a jQuery selection.
8134            @param  target    element - the target input field or division or span */
8135         _disableDatepicker: function(target) {
8136                 var $target = $(target);
8137                 var inst = $.data(target, PROP_NAME);
8138                 if (!$target.hasClass(this.markerClassName)) {
8139                         return;
8140                 }
8141                 var nodeName = target.nodeName.toLowerCase();
8142                 if (nodeName == 'input') {
8143                         target.disabled = true;
8144                         inst.trigger.filter('button').
8145                                 each(function() { this.disabled = true; }).end().
8146                                 filter('img').css({opacity: '0.5', cursor: 'default'});
8147                 }
8148                 else if (nodeName == 'div' || nodeName == 'span') {
8149                         var inline = $target.children('.' + this._inlineClass);
8150                         inline.children().addClass('ui-state-disabled');
8151                 }
8152                 this._disabledInputs = $.map(this._disabledInputs,
8153                         function(value) { return (value == target ? null : value); }); // delete entry
8154                 this._disabledInputs[this._disabledInputs.length] = target;
8155         },
8157         /* Is the first field in a jQuery collection disabled as a datepicker?
8158            @param  target    element - the target input field or division or span
8159            @return boolean - true if disabled, false if enabled */
8160         _isDisabledDatepicker: function(target) {
8161                 if (!target) {
8162                         return false;
8163                 }
8164                 for (var i = 0; i < this._disabledInputs.length; i++) {
8165                         if (this._disabledInputs[i] == target)
8166                                 return true;
8167                 }
8168                 return false;
8169         },
8171         /* Retrieve the instance data for the target control.
8172            @param  target  element - the target input field or division or span
8173            @return  object - the associated instance data
8174            @throws  error if a jQuery problem getting data */
8175         _getInst: function(target) {
8176                 try {
8177                         return $.data(target, PROP_NAME);
8178                 }
8179                 catch (err) {
8180                         throw 'Missing instance data for this datepicker';
8181                 }
8182         },
8184         /* Update or retrieve the settings for a date picker attached to an input field or division.
8185            @param  target  element - the target input field or division or span
8186            @param  name    object - the new settings to update or
8187                            string - the name of the setting to change or retrieve,
8188                            when retrieving also 'all' for all instance settings or
8189                            'defaults' for all global defaults
8190            @param  value   any - the new value for the setting
8191                            (omit if above is an object or to retrieve a value) */
8192         _optionDatepicker: function(target, name, value) {
8193                 var inst = this._getInst(target);
8194                 if (arguments.length == 2 && typeof name == 'string') {
8195                         return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8196                                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8197                                 this._get(inst, name)) : null));
8198                 }
8199                 var settings = name || {};
8200                 if (typeof name == 'string') {
8201                         settings = {};
8202                         settings[name] = value;
8203                 }
8204                 if (inst) {
8205                         if (this._curInst == inst) {
8206                                 this._hideDatepicker(null);
8207                         }
8208                         var date = this._getDateDatepicker(target);
8209                         extendRemove(inst.settings, settings);
8210                         this._setDateDatepicker(target, date);
8211                         this._updateDatepicker(inst);
8212                 }
8213         },
8215         // change method deprecated
8216         _changeDatepicker: function(target, name, value) {
8217                 this._optionDatepicker(target, name, value);
8218         },
8220         /* Redraw the date picker attached to an input field or division.
8221            @param  target  element - the target input field or division or span */
8222         _refreshDatepicker: function(target) {
8223                 var inst = this._getInst(target);
8224                 if (inst) {
8225                         this._updateDatepicker(inst);
8226                 }
8227         },
8229         /* Set the dates for a jQuery selection.
8230            @param  target   element - the target input field or division or span
8231            @param  date     Date - the new date
8232            @param  endDate  Date - the new end date for a range (optional) */
8233         _setDateDatepicker: function(target, date, endDate) {
8234                 var inst = this._getInst(target);
8235                 if (inst) {
8236                         this._setDate(inst, date, endDate);
8237                         this._updateDatepicker(inst);
8238                         this._updateAlternate(inst);
8239                 }
8240         },
8242         /* Get the date(s) for the first entry in a jQuery selection.
8243            @param  target  element - the target input field or division or span
8244            @return Date - the current date or
8245                    Date[2] - the current dates for a range */
8246         _getDateDatepicker: function(target) {
8247                 var inst = this._getInst(target);
8248                 if (inst && !inst.inline)
8249                         this._setDateFromField(inst);
8250                 return (inst ? this._getDate(inst) : null);
8251         },
8253         /* Handle keystrokes. */
8254         _doKeyDown: function(event) {
8255                 var inst = $.datepicker._getInst(event.target);
8256                 var handled = true;
8257                 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8258                 inst._keyEvent = true;
8259                 if ($.datepicker._datepickerShowing)
8260                         switch (event.keyCode) {
8261                                 case 9:  $.datepicker._hideDatepicker(null, '');
8262                                                 break; // hide on tab out
8263                                 case 13: var sel = $('td.' + $.datepicker._dayOverClass +
8264                                                         ', td.' + $.datepicker._currentClass, inst.dpDiv);
8265                                                 if (sel[0])
8266                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8267                                                 else
8268                                                         $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
8269                                                 return false; // don't submit the form
8270                                                 break; // select the value on enter
8271                                 case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
8272                                                 break; // hide on escape
8273                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8274                                                         -$.datepicker._get(inst, 'stepBigMonths') :
8275                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
8276                                                 break; // previous month/year on page up/+ ctrl
8277                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8278                                                         +$.datepicker._get(inst, 'stepBigMonths') :
8279                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
8280                                                 break; // next month/year on page down/+ ctrl
8281                                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8282                                                 handled = event.ctrlKey || event.metaKey;
8283                                                 break; // clear on ctrl or command +end
8284                                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8285                                                 handled = event.ctrlKey || event.metaKey;
8286                                                 break; // current on ctrl or command +home
8287                                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8288                                                 handled = event.ctrlKey || event.metaKey;
8289                                                 // -1 day on ctrl or command +left
8290                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8291                                                                         -$.datepicker._get(inst, 'stepBigMonths') :
8292                                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
8293                                                 // next month/year on alt +left on Mac
8294                                                 break;
8295                                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8296                                                 handled = event.ctrlKey || event.metaKey;
8297                                                 break; // -1 week on ctrl or command +up
8298                                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8299                                                 handled = event.ctrlKey || event.metaKey;
8300                                                 // +1 day on ctrl or command +right
8301                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8302                                                                         +$.datepicker._get(inst, 'stepBigMonths') :
8303                                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
8304                                                 // next month/year on alt +right
8305                                                 break;
8306                                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8307                                                 handled = event.ctrlKey || event.metaKey;
8308                                                 break; // +1 week on ctrl or command +down
8309                                 default: handled = false;
8310                         }
8311                 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8312                         $.datepicker._showDatepicker(this);
8313                 else {
8314                         handled = false;
8315                 }
8316                 if (handled) {
8317                         event.preventDefault();
8318                         event.stopPropagation();
8319                 }
8320         },
8322         /* Filter entered characters - based on date format. */
8323         _doKeyPress: function(event) {
8324                 var inst = $.datepicker._getInst(event.target);
8325                 if ($.datepicker._get(inst, 'constrainInput')) {
8326                         var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8327                         var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8328                         return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8329                 }
8330         },
8332         /* Pop-up the date picker for a given input field.
8333            @param  input  element - the input field attached to the date picker or
8334                           event - if triggered by focus */
8335         _showDatepicker: function(input) {
8336                 input = input.target || input;
8337                 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8338                         input = $('input', input.parentNode)[0];
8339                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8340                         return;
8341                 var inst = $.datepicker._getInst(input);
8342                 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8343                 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
8344                 $.datepicker._hideDatepicker(null, '');
8345                 $.datepicker._lastInput = input;
8346                 $.datepicker._setDateFromField(inst);
8347                 if ($.datepicker._inDialog) // hide cursor
8348                         input.value = '';
8349                 if (!$.datepicker._pos) { // position below input
8350                         $.datepicker._pos = $.datepicker._findPos(input);
8351                         $.datepicker._pos[1] += input.offsetHeight; // add the height
8352                 }
8353                 var isFixed = false;
8354                 $(input).parents().each(function() {
8355                         isFixed |= $(this).css('position') == 'fixed';
8356                         return !isFixed;
8357                 });
8358                 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8359                         $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8360                         $.datepicker._pos[1] -= document.documentElement.scrollTop;
8361                 }
8362                 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8363                 $.datepicker._pos = null;
8364                 inst.rangeStart = null;
8365                 // determine sizing offscreen
8366                 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8367                 $.datepicker._updateDatepicker(inst);
8368                 // fix width for dynamic number of date pickers
8369                 // and adjust position before showing
8370                 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8371                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8372                         'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8373                         left: offset.left + 'px', top: offset.top + 'px'});
8374                 if (!inst.inline) {
8375                         var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
8376                         var duration = $.datepicker._get(inst, 'duration');
8377                         var postProcess = function() {
8378                                 $.datepicker._datepickerShowing = true;
8379                                 if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
8380                                         $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
8381                                                 height: inst.dpDiv.height() + 4});
8382                         };
8383                         if ($.effects && $.effects[showAnim])
8384                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8385                         else
8386                                 inst.dpDiv[showAnim](duration, postProcess);
8387                         if (duration == '')
8388                                 postProcess();
8389                         if (inst.input[0].type != 'hidden')
8390                                 inst.input[0].focus();
8391                         $.datepicker._curInst = inst;
8392                 }
8393         },
8395         /* Generate the date picker content. */
8396         _updateDatepicker: function(inst) {
8397                 var dims = {width: inst.dpDiv.width() + 4,
8398                         height: inst.dpDiv.height() + 4};
8399                 var self = this;
8400                 inst.dpDiv.empty().append(this._generateHTML(inst))
8401                         .find('iframe.ui-datepicker-cover').
8402                                 css({width: dims.width, height: dims.height})
8403                         .end()
8404                         .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
8405                                 .bind('mouseout', function(){
8406                                         $(this).removeClass('ui-state-hover');
8407                                         if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
8408                                         if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
8409                                 })
8410                                 .bind('mouseover', function(){
8411                                         if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
8412                                                 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8413                                                 $(this).addClass('ui-state-hover');
8414                                                 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
8415                                                 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
8416                                         }
8417                                 })
8418                         .end()
8419                         .find('.' + this._dayOverClass + ' a')
8420                                 .trigger('mouseover')
8421                         .end();
8422                 var numMonths = this._getNumberOfMonths(inst);
8423                 var cols = numMonths[1];
8424                 var width = 17;
8425                 if (cols > 1) {
8426                         inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8427                 } else {
8428                         inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8429                 }
8430                 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8431                         'Class']('ui-datepicker-multi');
8432                 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8433                         'Class']('ui-datepicker-rtl');
8434                 if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
8435                         $(inst.input[0]).focus();
8436         },
8438         /* Check positioning to remain on screen. */
8439         _checkOffset: function(inst, offset, isFixed) {
8440                 var dpWidth = inst.dpDiv.outerWidth();
8441                 var dpHeight = inst.dpDiv.outerHeight();
8442                 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8443                 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8444                 var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
8445                 var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
8447                 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8448                 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8449                 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8451                 // now check if datepicker is showing outside window viewport - move to a better place if so.
8452                 offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
8453                 offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
8455                 return offset;
8456         },
8458         /* Find an object's position on the screen. */
8459         _findPos: function(obj) {
8460         while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
8461             obj = obj.nextSibling;
8462         }
8463         var position = $(obj).offset();
8464             return [position.left, position.top];
8465         },
8467         /* Hide the date picker from view.
8468            @param  input  element - the input field attached to the date picker
8469            @param  duration  string - the duration over which to close the date picker */
8470         _hideDatepicker: function(input, duration) {
8471                 var inst = this._curInst;
8472                 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8473                         return;
8474                 if (inst.stayOpen)
8475                         this._selectDate('#' + inst.id, this._formatDate(inst,
8476                                 inst.currentDay, inst.currentMonth, inst.currentYear));
8477                 inst.stayOpen = false;
8478                 if (this._datepickerShowing) {
8479                         duration = (duration != null ? duration : this._get(inst, 'duration'));
8480                         var showAnim = this._get(inst, 'showAnim');
8481                         var postProcess = function() {
8482                                 $.datepicker._tidyDialog(inst);
8483                         };
8484                         if (duration != '' && $.effects && $.effects[showAnim])
8485                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
8486                                         duration, postProcess);
8487                         else
8488                                 inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
8489                                         (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
8490                         if (duration == '')
8491                                 this._tidyDialog(inst);
8492                         var onClose = this._get(inst, 'onClose');
8493                         if (onClose)
8494                                 onClose.apply((inst.input ? inst.input[0] : null),
8495                                         [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
8496                         this._datepickerShowing = false;
8497                         this._lastInput = null;
8498                         if (this._inDialog) {
8499                                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8500                                 if ($.blockUI) {
8501                                         $.unblockUI();
8502                                         $('body').append(this.dpDiv);
8503                                 }
8504                         }
8505                         this._inDialog = false;
8506                 }
8507                 this._curInst = null;
8508         },
8510         /* Tidy up after a dialog display. */
8511         _tidyDialog: function(inst) {
8512                 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8513         },
8515         /* Close date picker if clicked elsewhere. */
8516         _checkExternalClick: function(event) {
8517                 if (!$.datepicker._curInst)
8518                         return;
8519                 var $target = $(event.target);
8520                 if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
8521                                 !$target.hasClass($.datepicker.markerClassName) &&
8522                                 !$target.hasClass($.datepicker._triggerClass) &&
8523                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
8524                         $.datepicker._hideDatepicker(null, '');
8525         },
8527         /* Adjust one of the date sub-fields. */
8528         _adjustDate: function(id, offset, period) {
8529                 var target = $(id);
8530                 var inst = this._getInst(target[0]);
8531                 if (this._isDisabledDatepicker(target[0])) {
8532                         return;
8533                 }
8534                 this._adjustInstDate(inst, offset +
8535                         (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8536                         period);
8537                 this._updateDatepicker(inst);
8538         },
8540         /* Action for current link. */
8541         _gotoToday: function(id) {
8542                 var target = $(id);
8543                 var inst = this._getInst(target[0]);
8544                 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8545                         inst.selectedDay = inst.currentDay;
8546                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8547                         inst.drawYear = inst.selectedYear = inst.currentYear;
8548                 }
8549                 else {
8550                 var date = new Date();
8551                 inst.selectedDay = date.getDate();
8552                 inst.drawMonth = inst.selectedMonth = date.getMonth();
8553                 inst.drawYear = inst.selectedYear = date.getFullYear();
8554                 }
8555                 this._notifyChange(inst);
8556                 this._adjustDate(target);
8557         },
8559         /* Action for selecting a new month/year. */
8560         _selectMonthYear: function(id, select, period) {
8561                 var target = $(id);
8562                 var inst = this._getInst(target[0]);
8563                 inst._selectingMonthYear = false;
8564                 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8565                 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8566                         parseInt(select.options[select.selectedIndex].value,10);
8567                 this._notifyChange(inst);
8568                 this._adjustDate(target);
8569         },
8571         /* Restore input focus after not changing month/year. */
8572         _clickMonthYear: function(id) {
8573                 var target = $(id);
8574                 var inst = this._getInst(target[0]);
8575                 if (inst.input && inst._selectingMonthYear && !$.browser.msie)
8576                         inst.input[0].focus();
8577                 inst._selectingMonthYear = !inst._selectingMonthYear;
8578         },
8580         /* Action for selecting a day. */
8581         _selectDay: function(id, month, year, td) {
8582                 var target = $(id);
8583                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8584                         return;
8585                 }
8586                 var inst = this._getInst(target[0]);
8587                 inst.selectedDay = inst.currentDay = $('a', td).html();
8588                 inst.selectedMonth = inst.currentMonth = month;
8589                 inst.selectedYear = inst.currentYear = year;
8590                 if (inst.stayOpen) {
8591                         inst.endDay = inst.endMonth = inst.endYear = null;
8592                 }
8593                 this._selectDate(id, this._formatDate(inst,
8594                         inst.currentDay, inst.currentMonth, inst.currentYear));
8595                 if (inst.stayOpen) {
8596                         inst.rangeStart = this._daylightSavingAdjust(
8597                                 new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
8598                         this._updateDatepicker(inst);
8599                 }
8600         },
8602         /* Erase the input field and hide the date picker. */
8603         _clearDate: function(id) {
8604                 var target = $(id);
8605                 var inst = this._getInst(target[0]);
8606                 inst.stayOpen = false;
8607                 inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
8608                 this._selectDate(target, '');
8609         },
8611         /* Update the input field with the selected date. */
8612         _selectDate: function(id, dateStr) {
8613                 var target = $(id);
8614                 var inst = this._getInst(target[0]);
8615                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8616                 if (inst.input)
8617                         inst.input.val(dateStr);
8618                 this._updateAlternate(inst);
8619                 var onSelect = this._get(inst, 'onSelect');
8620                 if (onSelect)
8621                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
8622                 else if (inst.input)
8623                         inst.input.trigger('change'); // fire the change event
8624                 if (inst.inline)
8625                         this._updateDatepicker(inst);
8626                 else if (!inst.stayOpen) {
8627                         this._hideDatepicker(null, this._get(inst, 'duration'));
8628                         this._lastInput = inst.input[0];
8629                         if (typeof(inst.input[0]) != 'object')
8630                                 inst.input[0].focus(); // restore focus
8631                         this._lastInput = null;
8632                 }
8633         },
8635         /* Update any alternate field to synchronise with the main field. */
8636         _updateAlternate: function(inst) {
8637                 var altField = this._get(inst, 'altField');
8638                 if (altField) { // update alternate field too
8639                         var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8640                         var date = this._getDate(inst);
8641                         dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8642                         $(altField).each(function() { $(this).val(dateStr); });
8643                 }
8644         },
8646         /* Set as beforeShowDay function to prevent selection of weekends.
8647            @param  date  Date - the date to customise
8648            @return [boolean, string] - is this date selectable?, what is its CSS class? */
8649         noWeekends: function(date) {
8650                 var day = date.getDay();
8651                 return [(day > 0 && day < 6), ''];
8652         },
8654         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8655            @param  date  Date - the date to get the week for
8656            @return  number - the number of the week within the year that contains this date */
8657         iso8601Week: function(date) {
8658                 var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
8659                 var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
8660                 var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
8661                 firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
8662                 if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
8663                         checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
8664                         return $.datepicker.iso8601Week(checkDate);
8665                 } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
8666                         firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
8667                         if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
8668                                 return 1;
8669                         }
8670                 }
8671                 return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
8672         },
8674         /* Parse a string value into a date object.
8675            See formatDate below for the possible formats.
8677            @param  format    string - the expected format of the date
8678            @param  value     string - the date in the above format
8679            @param  settings  Object - attributes include:
8680                              shortYearCutoff  number - the cutoff year for determining the century (optional)
8681                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
8682                              dayNames         string[7] - names of the days from Sunday (optional)
8683                              monthNamesShort  string[12] - abbreviated names of the months (optional)
8684                              monthNames       string[12] - names of the months (optional)
8685            @return  Date - the extracted date value or null if value is blank */
8686         parseDate: function (format, value, settings) {
8687                 if (format == null || value == null)
8688                         throw 'Invalid arguments';
8689                 value = (typeof value == 'object' ? value.toString() : value + '');
8690                 if (value == '')
8691                         return null;
8692                 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8693                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8694                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8695                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8696                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8697                 var year = -1;
8698                 var month = -1;
8699                 var day = -1;
8700                 var doy = -1;
8701                 var literal = false;
8702                 // Check whether a format character is doubled
8703                 var lookAhead = function(match) {
8704                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8705                         if (matches)
8706                                 iFormat++;
8707                         return matches;
8708                 };
8709                 // Extract a number from the string value
8710                 var getNumber = function(match) {
8711                         lookAhead(match);
8712                         var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
8713                         var size = origSize;
8714                         var num = 0;
8715                         while (size > 0 && iValue < value.length &&
8716                                         value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
8717                                 num = num * 10 + parseInt(value.charAt(iValue++),10);
8718                                 size--;
8719                         }
8720                         if (size == origSize)
8721                                 throw 'Missing number at position ' + iValue;
8722                         return num;
8723                 };
8724                 // Extract a name from the string value and convert to an index
8725                 var getName = function(match, shortNames, longNames) {
8726                         var names = (lookAhead(match) ? longNames : shortNames);
8727                         var size = 0;
8728                         for (var j = 0; j < names.length; j++)
8729                                 size = Math.max(size, names[j].length);
8730                         var name = '';
8731                         var iInit = iValue;
8732                         while (size > 0 && iValue < value.length) {
8733                                 name += value.charAt(iValue++);
8734                                 for (var i = 0; i < names.length; i++)
8735                                         if (name == names[i])
8736                                                 return i + 1;
8737                                 size--;
8738                         }
8739                         throw 'Unknown name at position ' + iInit;
8740                 };
8741                 // Confirm that a literal character matches the string value
8742                 var checkLiteral = function() {
8743                         if (value.charAt(iValue) != format.charAt(iFormat))
8744                                 throw 'Unexpected literal at position ' + iValue;
8745                         iValue++;
8746                 };
8747                 var iValue = 0;
8748                 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8749                         if (literal)
8750                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8751                                         literal = false;
8752                                 else
8753                                         checkLiteral();
8754                         else
8755                                 switch (format.charAt(iFormat)) {
8756                                         case 'd':
8757                                                 day = getNumber('d');
8758                                                 break;
8759                                         case 'D':
8760                                                 getName('D', dayNamesShort, dayNames);
8761                                                 break;
8762                                         case 'o':
8763                                                 doy = getNumber('o');
8764                                                 break;
8765                                         case 'm':
8766                                                 month = getNumber('m');
8767                                                 break;
8768                                         case 'M':
8769                                                 month = getName('M', monthNamesShort, monthNames);
8770                                                 break;
8771                                         case 'y':
8772                                                 year = getNumber('y');
8773                                                 break;
8774                                         case '@':
8775                                                 var date = new Date(getNumber('@'));
8776                                                 year = date.getFullYear();
8777                                                 month = date.getMonth() + 1;
8778                                                 day = date.getDate();
8779                                                 break;
8780                                         case "'":
8781                                                 if (lookAhead("'"))
8782                                                         checkLiteral();
8783                                                 else
8784                                                         literal = true;
8785                                                 break;
8786                                         default:
8787                                                 checkLiteral();
8788                                 }
8789                 }
8790                 if (year == -1)
8791                         year = new Date().getFullYear();
8792                 else if (year < 100)
8793                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8794                                 (year <= shortYearCutoff ? 0 : -100);
8795                 if (doy > -1) {
8796                         month = 1;
8797                         day = doy;
8798                         do {
8799                                 var dim = this._getDaysInMonth(year, month - 1);
8800                                 if (day <= dim)
8801                                         break;
8802                                 month++;
8803                                 day -= dim;
8804                         } while (true);
8805                 }
8806                 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8807                 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8808                         throw 'Invalid date'; // E.g. 31/02/*
8809                 return date;
8810         },
8812         /* Standard date formats. */
8813         ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8814         COOKIE: 'D, dd M yy',
8815         ISO_8601: 'yy-mm-dd',
8816         RFC_822: 'D, d M y',
8817         RFC_850: 'DD, dd-M-y',
8818         RFC_1036: 'D, d M y',
8819         RFC_1123: 'D, d M yy',
8820         RFC_2822: 'D, d M yy',
8821         RSS: 'D, d M y', // RFC 822
8822         TIMESTAMP: '@',
8823         W3C: 'yy-mm-dd', // ISO 8601
8825         /* Format a date object into a string value.
8826            The format can be combinations of the following:
8827            d  - day of month (no leading zero)
8828            dd - day of month (two digit)
8829            o  - day of year (no leading zeros)
8830            oo - day of year (three digit)
8831            D  - day name short
8832            DD - day name long
8833            m  - month of year (no leading zero)
8834            mm - month of year (two digit)
8835            M  - month name short
8836            MM - month name long
8837            y  - year (two digit)
8838            yy - year (four digit)
8839            @ - Unix timestamp (ms since 01/01/1970)
8840            '...' - literal text
8841            '' - single quote
8843            @param  format    string - the desired format of the date
8844            @param  date      Date - the date value to format
8845            @param  settings  Object - attributes include:
8846                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
8847                              dayNames         string[7] - names of the days from Sunday (optional)
8848                              monthNamesShort  string[12] - abbreviated names of the months (optional)
8849                              monthNames       string[12] - names of the months (optional)
8850            @return  string - the date in the above format */
8851         formatDate: function (format, date, settings) {
8852                 if (!date)
8853                         return '';
8854                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8855                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8856                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8857                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8858                 // Check whether a format character is doubled
8859                 var lookAhead = function(match) {
8860                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8861                         if (matches)
8862                                 iFormat++;
8863                         return matches;
8864                 };
8865                 // Format a number, with leading zero if necessary
8866                 var formatNumber = function(match, value, len) {
8867                         var num = '' + value;
8868                         if (lookAhead(match))
8869                                 while (num.length < len)
8870                                         num = '0' + num;
8871                         return num;
8872                 };
8873                 // Format a name, short or long as requested
8874                 var formatName = function(match, value, shortNames, longNames) {
8875                         return (lookAhead(match) ? longNames[value] : shortNames[value]);
8876                 };
8877                 var output = '';
8878                 var literal = false;
8879                 if (date)
8880                         for (var iFormat = 0; iFormat < format.length; iFormat++) {
8881                                 if (literal)
8882                                         if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8883                                                 literal = false;
8884                                         else
8885                                                 output += format.charAt(iFormat);
8886                                 else
8887                                         switch (format.charAt(iFormat)) {
8888                                                 case 'd':
8889                                                         output += formatNumber('d', date.getDate(), 2);
8890                                                         break;
8891                                                 case 'D':
8892                                                         output += formatName('D', date.getDay(), dayNamesShort, dayNames);
8893                                                         break;
8894                                                 case 'o':
8895                                                         var doy = date.getDate();
8896                                                         for (var m = date.getMonth() - 1; m >= 0; m--)
8897                                                                 doy += this._getDaysInMonth(date.getFullYear(), m);
8898                                                         output += formatNumber('o', doy, 3);
8899                                                         break;
8900                                                 case 'm':
8901                                                         output += formatNumber('m', date.getMonth() + 1, 2);
8902                                                         break;
8903                                                 case 'M':
8904                                                         output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
8905                                                         break;
8906                                                 case 'y':
8907                                                         output += (lookAhead('y') ? date.getFullYear() :
8908                                                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
8909                                                         break;
8910                                                 case '@':
8911                                                         output += date.getTime();
8912                                                         break;
8913                                                 case "'":
8914                                                         if (lookAhead("'"))
8915                                                                 output += "'";
8916                                                         else
8917                                                                 literal = true;
8918                                                         break;
8919                                                 default:
8920                                                         output += format.charAt(iFormat);
8921                                         }
8922                         }
8923                 return output;
8924         },
8926         /* Extract all possible characters from the date format. */
8927         _possibleChars: function (format) {
8928                 var chars = '';
8929                 var literal = false;
8930                 for (var iFormat = 0; iFormat < format.length; iFormat++)
8931                         if (literal)
8932                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8933                                         literal = false;
8934                                 else
8935                                         chars += format.charAt(iFormat);
8936                         else
8937                                 switch (format.charAt(iFormat)) {
8938                                         case 'd': case 'm': case 'y': case '@':
8939                                                 chars += '0123456789';
8940                                                 break;
8941                                         case 'D': case 'M':
8942                                                 return null; // Accept anything
8943                                         case "'":
8944                                                 if (lookAhead("'"))
8945                                                         chars += "'";
8946                                                 else
8947                                                         literal = true;
8948                                                 break;
8949                                         default:
8950                                                 chars += format.charAt(iFormat);
8951                                 }
8952                 return chars;
8953         },
8955         /* Get a setting value, defaulting if necessary. */
8956         _get: function(inst, name) {
8957                 return inst.settings[name] !== undefined ?
8958                         inst.settings[name] : this._defaults[name];
8959         },
8961         /* Parse existing date and initialise date picker. */
8962         _setDateFromField: function(inst) {
8963                 var dateFormat = this._get(inst, 'dateFormat');
8964                 var dates = inst.input ? inst.input.val() : null;
8965                 inst.endDay = inst.endMonth = inst.endYear = null;
8966                 var date = defaultDate = this._getDefaultDate(inst);
8967                 var settings = this._getFormatConfig(inst);
8968                 try {
8969                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8970                 } catch (event) {
8971                         this.log(event);
8972                         date = defaultDate;
8973                 }
8974                 inst.selectedDay = date.getDate();
8975                 inst.drawMonth = inst.selectedMonth = date.getMonth();
8976                 inst.drawYear = inst.selectedYear = date.getFullYear();
8977                 inst.currentDay = (dates ? date.getDate() : 0);
8978                 inst.currentMonth = (dates ? date.getMonth() : 0);
8979                 inst.currentYear = (dates ? date.getFullYear() : 0);
8980                 this._adjustInstDate(inst);
8981         },
8983         /* Retrieve the default date shown on opening. */
8984         _getDefaultDate: function(inst) {
8985                 var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
8986                 var minDate = this._getMinMaxDate(inst, 'min', true);
8987                 var maxDate = this._getMinMaxDate(inst, 'max');
8988                 date = (minDate && date < minDate ? minDate : date);
8989                 date = (maxDate && date > maxDate ? maxDate : date);
8990                 return date;
8991         },
8993         /* A date may be specified as an exact value or a relative one. */
8994         _determineDate: function(date, defaultDate) {
8995                 var offsetNumeric = function(offset) {
8996                         var date = new Date();
8997                         date.setDate(date.getDate() + offset);
8998                         return date;
8999                 };
9000                 var offsetString = function(offset, getDaysInMonth) {
9001                         var date = new Date();
9002                         var year = date.getFullYear();
9003                         var month = date.getMonth();
9004                         var day = date.getDate();
9005                         var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9006                         var matches = pattern.exec(offset);
9007                         while (matches) {
9008                                 switch (matches[2] || 'd') {
9009                                         case 'd' : case 'D' :
9010                                                 day += parseInt(matches[1],10); break;
9011                                         case 'w' : case 'W' :
9012                                                 day += parseInt(matches[1],10) * 7; break;
9013                                         case 'm' : case 'M' :
9014                                                 month += parseInt(matches[1],10);
9015                                                 day = Math.min(day, getDaysInMonth(year, month));
9016                                                 break;
9017                                         case 'y': case 'Y' :
9018                                                 year += parseInt(matches[1],10);
9019                                                 day = Math.min(day, getDaysInMonth(year, month));
9020                                                 break;
9021                                 }
9022                                 matches = pattern.exec(offset);
9023                         }
9024                         return new Date(year, month, day);
9025                 };
9026                 date = (date == null ? defaultDate :
9027                         (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
9028                         (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
9029                 date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
9030                 if (date) {
9031                         date.setHours(0);
9032                         date.setMinutes(0);
9033                         date.setSeconds(0);
9034                         date.setMilliseconds(0);
9035                 }
9036                 return this._daylightSavingAdjust(date);
9037         },
9039         /* Handle switch to/from daylight saving.
9040            Hours may be non-zero on daylight saving cut-over:
9041            > 12 when midnight changeover, but then cannot generate
9042            midnight datetime, so jump to 1AM, otherwise reset.
9043            @param  date  (Date) the date to check
9044            @return  (Date) the corrected date */
9045         _daylightSavingAdjust: function(date) {
9046                 if (!date) return null;
9047                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9048                 return date;
9049         },
9051         /* Set the date(s) directly. */
9052         _setDate: function(inst, date, endDate) {
9053                 var clear = !(date);
9054                 var origMonth = inst.selectedMonth;
9055                 var origYear = inst.selectedYear;
9056                 date = this._determineDate(date, new Date());
9057                 inst.selectedDay = inst.currentDay = date.getDate();
9058                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
9059                 inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
9060                 if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
9061                         this._notifyChange(inst);
9062                 this._adjustInstDate(inst);
9063                 if (inst.input) {
9064                         inst.input.val(clear ? '' : this._formatDate(inst));
9065                 }
9066         },
9068         /* Retrieve the date(s) directly. */
9069         _getDate: function(inst) {
9070                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9071                         this._daylightSavingAdjust(new Date(
9072                         inst.currentYear, inst.currentMonth, inst.currentDay)));
9073                         return startDate;
9074         },
9076         /* Generate the HTML for the current state of the date picker. */
9077         _generateHTML: function(inst) {
9078                 var today = new Date();
9079                 today = this._daylightSavingAdjust(
9080                         new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9081                 var isRTL = this._get(inst, 'isRTL');
9082                 var showButtonPanel = this._get(inst, 'showButtonPanel');
9083                 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9084                 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9085                 var numMonths = this._getNumberOfMonths(inst);
9086                 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9087                 var stepMonths = this._get(inst, 'stepMonths');
9088                 var stepBigMonths = this._get(inst, 'stepBigMonths');
9089                 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9090                 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9091                         new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9092                 var minDate = this._getMinMaxDate(inst, 'min', true);
9093                 var maxDate = this._getMinMaxDate(inst, 'max');
9094                 var drawMonth = inst.drawMonth - showCurrentAtPos;
9095                 var drawYear = inst.drawYear;
9096                 if (drawMonth < 0) {
9097                         drawMonth += 12;
9098                         drawYear--;
9099                 }
9100                 if (maxDate) {
9101                         var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9102                                 maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
9103                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9104                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9105                                 drawMonth--;
9106                                 if (drawMonth < 0) {
9107                                         drawMonth = 11;
9108                                         drawYear--;
9109                                 }
9110                         }
9111                 }
9112                 inst.drawMonth = drawMonth;
9113                 inst.drawYear = drawYear;
9114                 var prevText = this._get(inst, 'prevText');
9115                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9116                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9117                         this._getFormatConfig(inst)));
9118                 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9119                         '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9120                         ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9121                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
9122                 var nextText = this._get(inst, 'nextText');
9123                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9124                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9125                         this._getFormatConfig(inst)));
9126                 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9127                         '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9128                         ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9129                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
9130                 var currentText = this._get(inst, 'currentText');
9131                 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9132                 currentText = (!navigationAsDateFormat ? currentText :
9133                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9134                 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9135                 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9136                         (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9137                         '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9138                 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9139                 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9140                 var dayNames = this._get(inst, 'dayNames');
9141                 var dayNamesShort = this._get(inst, 'dayNamesShort');
9142                 var dayNamesMin = this._get(inst, 'dayNamesMin');
9143                 var monthNames = this._get(inst, 'monthNames');
9144                 var monthNamesShort = this._get(inst, 'monthNamesShort');
9145                 var beforeShowDay = this._get(inst, 'beforeShowDay');
9146                 var showOtherMonths = this._get(inst, 'showOtherMonths');
9147                 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9148                 var endDate = inst.endDay ? this._daylightSavingAdjust(
9149                         new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
9150                 var defaultDate = this._getDefaultDate(inst);
9151                 var html = '';
9152                 for (var row = 0; row < numMonths[0]; row++) {
9153                         var group = '';
9154                         for (var col = 0; col < numMonths[1]; col++) {
9155                                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9156                                 var cornerClass = ' ui-corner-all';
9157                                 var calender = '';
9158                                 if (isMultiMonth) {
9159                                         calender += '<div class="ui-datepicker-group ui-datepicker-group-';
9160                                         switch (col) {
9161                                                 case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9162                                                 case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9163                                                 default: calender += 'middle'; cornerClass = ''; break;
9164                                         }
9165                                         calender += '">';
9166                                 }
9167                                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9168                                         (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9169                                         (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9170                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9171                                         selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9172                                         '</div><table class="ui-datepicker-calendar"><thead>' +
9173                                         '<tr>';
9174                                 var thead = '';
9175                                 for (var dow = 0; dow < 7; dow++) { // days of the week
9176                                         var day = (dow + firstDay) % 7;
9177                                         thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9178                                                 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9179                                 }
9180                                 calender += thead + '</tr></thead><tbody>';
9181                                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9182                                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9183                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9184                                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9185                                 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
9186                                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9187                                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9188                                         calender += '<tr>';
9189                                         var tbody = '';
9190                                         for (var dow = 0; dow < 7; dow++) { // create date picker days
9191                                                 var daySettings = (beforeShowDay ?
9192                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9193                                                 var otherMonth = (printDate.getMonth() != drawMonth);
9194                                                 var unselectable = otherMonth || !daySettings[0] ||
9195                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9196                                                 tbody += '<td class="' +
9197                                                         ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9198                                                         (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9199                                                         ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9200                                                         (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9201                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
9202                                                         ' ' + this._dayOverClass : '') + // highlight selected day
9203                                                         (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
9204                                                         (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9205                                                         (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
9206                                                         ' ' + this._currentClass : '') + // highlight selected day
9207                                                         (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9208                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9209                                                         (unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
9210                                                         inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
9211                                                         (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
9212                                                         (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9213                                                         (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9214                                                         (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
9215                                                         ' ui-state-active' : '') + // highlight selected day
9216                                                         '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
9217                                                 printDate.setDate(printDate.getDate() + 1);
9218                                                 printDate = this._daylightSavingAdjust(printDate);
9219                                         }
9220                                         calender += tbody + '</tr>';
9221                                 }
9222                                 drawMonth++;
9223                                 if (drawMonth > 11) {
9224                                         drawMonth = 0;
9225                                         drawYear++;
9226                                 }
9227                                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
9228                                                         ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9229                                 group += calender;
9230                         }
9231                         html += group;
9232                 }
9233                 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9234                         '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9235                 inst._keyEvent = false;
9236                 return html;
9237         },
9239         /* Generate the month and year header. */
9240         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9241                         selectedDate, secondary, monthNames, monthNamesShort) {
9242                 minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
9243                 var changeMonth = this._get(inst, 'changeMonth');
9244                 var changeYear = this._get(inst, 'changeYear');
9245                 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9246                 var html = '<div class="ui-datepicker-title">';
9247                 var monthHtml = '';
9248                 // month selection
9249                 if (secondary || !changeMonth)
9250                         monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
9251                 else {
9252                         var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9253                         var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9254                         monthHtml += '<select class="ui-datepicker-month" ' +
9255                                 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9256                                 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9257                                 '>';
9258                         for (var month = 0; month < 12; month++) {
9259                                 if ((!inMinYear || month >= minDate.getMonth()) &&
9260                                                 (!inMaxYear || month <= maxDate.getMonth()))
9261                                         monthHtml += '<option value="' + month + '"' +
9262                                                 (month == drawMonth ? ' selected="selected"' : '') +
9263                                                 '>' + monthNamesShort[month] + '</option>';
9264                         }
9265                         monthHtml += '</select>';
9266                 }
9267                 if (!showMonthAfterYear)
9268                         html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
9269                 // year selection
9270                 if (secondary || !changeYear)
9271                         html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9272                 else {
9273                         // determine range of years to display
9274                         var years = this._get(inst, 'yearRange').split(':');
9275                         var year = 0;
9276                         var endYear = 0;
9277                         if (years.length != 2) {
9278                                 year = drawYear - 10;
9279                                 endYear = drawYear + 10;
9280                         } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
9281                                 year = drawYear + parseInt(years[0], 10);
9282                                 endYear = drawYear + parseInt(years[1], 10);
9283                         } else {
9284                                 year = parseInt(years[0], 10);
9285                                 endYear = parseInt(years[1], 10);
9286                         }
9287                         year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9288                         endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9289                         html += '<select class="ui-datepicker-year" ' +
9290                                 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9291                                 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9292                                 '>';
9293                         for (; year <= endYear; year++) {
9294                                 html += '<option value="' + year + '"' +
9295                                         (year == drawYear ? ' selected="selected"' : '') +
9296                                         '>' + year + '</option>';
9297                         }
9298                         html += '</select>';
9299                 }
9300                 if (showMonthAfterYear)
9301                         html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
9302                 html += '</div>'; // Close datepicker_header
9303                 return html;
9304         },
9306         /* Adjust one of the date sub-fields. */
9307         _adjustInstDate: function(inst, offset, period) {
9308                 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9309                 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9310                 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9311                         (period == 'D' ? offset : 0);
9312                 var date = this._daylightSavingAdjust(new Date(year, month, day));
9313                 // ensure it is within the bounds set
9314                 var minDate = this._getMinMaxDate(inst, 'min', true);
9315                 var maxDate = this._getMinMaxDate(inst, 'max');
9316                 date = (minDate && date < minDate ? minDate : date);
9317                 date = (maxDate && date > maxDate ? maxDate : date);
9318                 inst.selectedDay = date.getDate();
9319                 inst.drawMonth = inst.selectedMonth = date.getMonth();
9320                 inst.drawYear = inst.selectedYear = date.getFullYear();
9321                 if (period == 'M' || period == 'Y')
9322                         this._notifyChange(inst);
9323         },
9325         /* Notify change of month/year. */
9326         _notifyChange: function(inst) {
9327                 var onChange = this._get(inst, 'onChangeMonthYear');
9328                 if (onChange)
9329                         onChange.apply((inst.input ? inst.input[0] : null),
9330                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9331         },
9333         /* Determine the number of months to show. */
9334         _getNumberOfMonths: function(inst) {
9335                 var numMonths = this._get(inst, 'numberOfMonths');
9336                 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9337         },
9339         /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
9340         _getMinMaxDate: function(inst, minMax, checkRange) {
9341                 var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
9342                 return (!checkRange || !inst.rangeStart ? date :
9343                         (!date || inst.rangeStart > date ? inst.rangeStart : date));
9344         },
9346         /* Find the number of days in a given month. */
9347         _getDaysInMonth: function(year, month) {
9348                 return 32 - new Date(year, month, 32).getDate();
9349         },
9351         /* Find the day of the week of the first of a month. */
9352         _getFirstDayOfMonth: function(year, month) {
9353                 return new Date(year, month, 1).getDay();
9354         },
9356         /* Determines if we should allow a "next/prev" month display change. */
9357         _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9358                 var numMonths = this._getNumberOfMonths(inst);
9359                 var date = this._daylightSavingAdjust(new Date(
9360                         curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
9361                 if (offset < 0)
9362                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9363                 return this._isInRange(inst, date);
9364         },
9366         /* Is the given date in the accepted range? */
9367         _isInRange: function(inst, date) {
9368                 // during range selection, use minimum of selected date and range start
9369                 var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
9370                         new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
9371                 newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
9372                 var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
9373                 var maxDate = this._getMinMaxDate(inst, 'max');
9374                 return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
9375         },
9377         /* Provide the configuration settings for formatting/parsing. */
9378         _getFormatConfig: function(inst) {
9379                 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9380                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9381                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9382                 return {shortYearCutoff: shortYearCutoff,
9383                         dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9384                         monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9385         },
9387         /* Format the given date for display. */
9388         _formatDate: function(inst, day, month, year) {
9389                 if (!day) {
9390                         inst.currentDay = inst.selectedDay;
9391                         inst.currentMonth = inst.selectedMonth;
9392                         inst.currentYear = inst.selectedYear;
9393                 }
9394                 var date = (day ? (typeof day == 'object' ? day :
9395                         this._daylightSavingAdjust(new Date(year, month, day))) :
9396                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9397                 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9398         }
9401 /* jQuery extend now ignores nulls! */
9402 function extendRemove(target, props) {
9403         $.extend(target, props);
9404         for (var name in props)
9405                 if (props[name] == null || props[name] == undefined)
9406                         target[name] = props[name];
9407         return target;
9410 /* Determine whether an object is an array. */
9411 function isArray(a) {
9412         return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9413                 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9416 /* Invoke the datepicker functionality.
9417    @param  options  string - a command, optionally followed by additional parameters or
9418                     Object - settings for attaching new datepicker functionality
9419    @return  jQuery object */
9420 $.fn.datepicker = function(options){
9422         /* Initialise the date picker. */
9423         if (!$.datepicker.initialized) {
9424                 $(document).mousedown($.datepicker._checkExternalClick).
9425                         find('body').append($.datepicker.dpDiv);
9426                 $.datepicker.initialized = true;
9427         }
9429         var otherArgs = Array.prototype.slice.call(arguments, 1);
9430         if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
9431                 return $.datepicker['_' + options + 'Datepicker'].
9432                         apply($.datepicker, [this[0]].concat(otherArgs));
9433         if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9434                 return $.datepicker['_' + options + 'Datepicker'].
9435                         apply($.datepicker, [this[0]].concat(otherArgs));
9436         return this.each(function() {
9437                 typeof options == 'string' ?
9438                         $.datepicker['_' + options + 'Datepicker'].
9439                                 apply($.datepicker, [this].concat(otherArgs)) :
9440                         $.datepicker._attachDatepicker(this, options);
9441         });
9444 $.datepicker = new Datepicker(); // singleton instance
9445 $.datepicker.initialized = false;
9446 $.datepicker.uuid = new Date().getTime();
9447 $.datepicker.version = "1.7.2";
9449 // Workaround for #4055
9450 // Add another global to avoid noConflict issues with inline event handlers
9451 window.DP_jQuery = $;
9453 })(jQuery);
9454 /* JavaScript for MediaWIki JS2 */
9457  * This is designed to be directly compatible with (and is essentially taken
9458  * directly from) the mv_embed code for bringing internationalized messages into
9459  * the JavaScript space. As such, if we get to the point of merging that stuff
9460  * into the main branch this code will be uneeded and probably cause issues.
9461  */
9464  * Mimics the no-conflict method used by the js2 stuff
9465  */
9466 $j = jQuery.noConflict();
9468  * Provides js2 compatible mw functions
9469  */
9470 if( typeof mw == 'undefined' || !mw ){
9471    mw = { };
9472    /**
9473     * Provides js2 compatible onload hook
9474     * @param func Function to call when ready
9475     */
9476    mw.addOnloadHook = function( func ) {
9477        $j(document).ready( func );
9478    }
9479    // Define a dummy mw.load function:
9480    mw.load = function( deps, callback ) { callback(); };
9481    
9482    // Creates global message object if not already in existence
9483         if ( !gMsg ) var gMsg = {};
9484    
9485         /**
9486          * Caches a list of messages for later retrieval
9487          * @param {Object} msgSet Hash of key:value pairs of messages to cache
9488          */      
9489         mw.addMessages = function ( msgSet ){
9490                 for ( var i in msgSet ){
9491                         gMsg[ i ] = msgSet[i];
9492                 }
9493         }
9494         /**
9495          * Retieves a message from the global message cache, performing on-the-fly
9496          * replacements using MediaWiki message syntax ($1, $2, etc.)
9497          * @param {String} key Name of message as it is in MediaWiki
9498          * @param {Array} args Array of replacement arguments
9499          */
9500         function gM( key, args ) {
9501                 var ms = '';    
9502                 if ( key in gMsg ) {
9503                         ms = gMsg[ key ];
9504                         if ( typeof args == 'object' || typeof args == 'array' ) {
9505                                 for ( var v in args ){
9506                                         var rep = '\$'+ ( parseInt(v) + 1 );
9507                                         ms = ms.replace( rep, args[v]);
9508                                 }
9509                         } else if ( typeof args =='string' || typeof args =='number' ) {
9510                                 ms = ms.replace( /\$1/, args );
9511                         }
9512                         return ms;
9513                 } else {
9514                         return '[' + key + ']';
9515                 }
9516         }
9517