1 /* Modernizr 2.0.6 (Custom Build) | MIT & BSD
2 * Build: http://www.modernizr.com/download/#-iepp
4 ;window.Modernizr=function(a,b,c){function w(a,b){return!!~(""+a).indexOf(b)}function v(a,b){return typeof a===b}function u(a,b){return t(prefixes.join(a+";")+(b||""))}function t(a){j.cssText=a}var d="2.0.6",e={},f=b.documentElement,g=b.head||b.getElementsByTagName("head")[0],h="modernizr",i=b.createElement(h),j=i.style,k,l=Object.prototype.toString,m={},n={},o={},p=[],q,r={}.hasOwnProperty,s;!v(r,c)&&!v(r.call,c)?s=function(a,b){return r.call(a,b)}:s=function(a,b){return b in a&&v(a.constructor.prototype[b],c)};for(var x in m)s(m,x)&&(q=x.toLowerCase(),e[q]=m[x](),p.push((e[q]?"":"no-")+q));t(""),i=k=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b<g)a.createElement(f[b])}a.iepp=a.iepp||{};var d=a.iepp,e=d.html5elements||"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",f=e.split("|"),g=f.length,h=new RegExp("(^|\\s)("+e+")","gi"),i=new RegExp("<(/*)("+e+")","gi"),j=/^\s*[\{\}]\s*$/,k=new RegExp("(^|[^\\n]*?\\s)("+e+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),l=b.createDocumentFragment(),m=b.documentElement,n=m.firstChild,o=b.createElement("body"),p=b.createElement("style"),q=/print|all/,r;d.getCSS=function(a,b){if(a+""===c)return"";var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,q.test(b)&&h.push(d.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},d.parseCSS=function(a){var b=[],c;while((c=k.exec(a))!=null)b.push(((j.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(h,"$1.iepp_$2")+c[4]);return b.join("\n")},d.writeHTML=function(){var a=-1;r=r||b.body;while(++a<g){var c=b.getElementsByTagName(f[a]),d=c.length,e=-1;while(++e<d)c[e].className.indexOf("iepp_")<0&&(c[e].className+=" iepp_"+f[a])}l.appendChild(r),m.appendChild(o),o.className=r.className,o.id=r.id,o.innerHTML=r.innerHTML.replace(i,"<$1font")},d._beforePrint=function(){p.styleSheet.cssText=d.parseCSS(d.getCSS(b.styleSheets,"all")),d.writeHTML()},d.restoreHTML=function(){o.innerHTML="",m.removeChild(o),m.appendChild(r)},d._afterPrint=function(){d.restoreHTML(),p.styleSheet.cssText=""},s(b),s(l);d.disablePP||(n.insertBefore(p,n.firstChild),p.media="print",p.className="iepp-printshim",a.attachEvent("onbeforeprint",d._beforePrint),a.attachEvent("onafterprint",d._afterPrint))}(a,b),e._version=d;return e}(this,this.document);
8 // console methods that may exist
9 for(var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(','), func; func = methods.pop();) {
10 con[func] = con[func] || dummy;
12 }(window.console = window.console || {}));
13 // we do this crazy little dance so that the `console` object
14 // inside the function is a name that can be shortened to a single
15 // letter by the compressor to make the compressed script as tiny
18 * jQuery JavaScript Library v1.6.3
21 * Copyright 2011, John Resig
22 * Dual licensed under the MIT or GPL Version 2 licenses.
23 * http://jquery.org/license
26 * http://sizzlejs.com/
27 * Copyright 2011, The Dojo Foundation
28 * Released under the MIT, BSD, and GPL Licenses.
30 * Date: Wed Aug 31 10:35:15 2011 -0400
32 (function( window, undefined ) {
34 // Use the correct document accordingly with window argument (sandbox)
35 var document = window.document,
36 navigator = window.navigator,
37 location = window.location;
38 var jQuery = (function() {
40 // Define a local copy of jQuery
41 var jQuery = function( selector, context ) {
42 // The jQuery object is actually just the init constructor 'enhanced'
43 return new jQuery.fn.init( selector, context, rootjQuery );
46 // Map over jQuery in case of overwrite
47 _jQuery = window.jQuery,
49 // Map over the $ in case of overwrite
52 // A central reference to the root jQuery(document)
55 // A simple way to check for HTML strings or ID strings
56 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
57 quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
59 // Check if a string has a non-whitespace character in it
62 // Used for trimming whitespace
69 // Match a standalone tag
70 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
73 rvalidchars = /^[\],:{}\s]*$/,
74 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
75 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
76 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
79 rwebkit = /(webkit)[ \/]([\w.]+)/,
80 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
81 rmsie = /(msie) ([\w.]+)/,
82 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
84 // Matches dashed string for camelizing
85 rdashAlpha = /-([a-z]|[0-9])/ig,
88 // Used by jQuery.camelCase as callback to replace()
89 fcamelCase = function( all, letter ) {
90 return ( letter + "" ).toUpperCase();
93 // Keep a UserAgent string for use with jQuery.browser
94 userAgent = navigator.userAgent,
96 // For matching the engine and version of the browser
99 // The deferred used on DOM ready
102 // The ready event handler
105 // Save a reference to some core methods
106 toString = Object.prototype.toString,
107 hasOwn = Object.prototype.hasOwnProperty,
108 push = Array.prototype.push,
109 slice = Array.prototype.slice,
110 trim = String.prototype.trim,
111 indexOf = Array.prototype.indexOf,
113 // [[Class]] -> type pairs
116 jQuery.fn = jQuery.prototype = {
118 init: function( selector, context, rootjQuery ) {
119 var match, elem, ret, doc;
121 // Handle $(""), $(null), or $(undefined)
126 // Handle $(DOMElement)
127 if ( selector.nodeType ) {
128 this.context = this[0] = selector;
133 // The body element only exists once, optimize finding it
134 if ( selector === "body" && !context && document.body ) {
135 this.context = document;
136 this[0] = document.body;
137 this.selector = selector;
142 // Handle HTML strings
143 if ( typeof selector === "string" ) {
144 // Are we dealing with HTML string or an ID?
145 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
146 // Assume that strings that start and end with <> are HTML and skip the regex check
147 match = [ null, selector, null ];
150 match = quickExpr.exec( selector );
153 // Verify a match, and that no context was specified for #id
154 if ( match && (match[1] || !context) ) {
156 // HANDLE: $(html) -> $(array)
158 context = context instanceof jQuery ? context[0] : context;
159 doc = (context ? context.ownerDocument || context : document);
161 // If a single string is passed in and it's a single tag
162 // just do a createElement and skip the rest
163 ret = rsingleTag.exec( selector );
166 if ( jQuery.isPlainObject( context ) ) {
167 selector = [ document.createElement( ret[1] ) ];
168 jQuery.fn.attr.call( selector, context, true );
171 selector = [ doc.createElement( ret[1] ) ];
175 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
176 selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
179 return jQuery.merge( this, selector );
183 elem = document.getElementById( match[2] );
185 // Check parentNode to catch when Blackberry 4.6 returns
186 // nodes that are no longer in the document #6963
187 if ( elem && elem.parentNode ) {
188 // Handle the case where IE and Opera return items
189 // by name instead of ID
190 if ( elem.id !== match[2] ) {
191 return rootjQuery.find( selector );
194 // Otherwise, we inject the element directly into the jQuery object
199 this.context = document;
200 this.selector = selector;
204 // HANDLE: $(expr, $(...))
205 } else if ( !context || context.jquery ) {
206 return (context || rootjQuery).find( selector );
208 // HANDLE: $(expr, context)
209 // (which is just equivalent to: $(context).find(expr)
211 return this.constructor( context ).find( selector );
214 // HANDLE: $(function)
215 // Shortcut for document ready
216 } else if ( jQuery.isFunction( selector ) ) {
217 return rootjQuery.ready( selector );
220 if (selector.selector !== undefined) {
221 this.selector = selector.selector;
222 this.context = selector.context;
225 return jQuery.makeArray( selector, this );
228 // Start with an empty selector
231 // The current version of jQuery being used
234 // The default length of a jQuery object is 0
237 // The number of elements contained in the matched element set
242 toArray: function() {
243 return slice.call( this, 0 );
246 // Get the Nth element in the matched element set OR
247 // Get the whole matched element set as a clean array
248 get: function( num ) {
251 // Return a 'clean' array
254 // Return just the object
255 ( num < 0 ? this[ this.length + num ] : this[ num ] );
258 // Take an array of elements and push it onto the stack
259 // (returning the new matched element set)
260 pushStack: function( elems, name, selector ) {
261 // Build a new jQuery matched element set
262 var ret = this.constructor();
264 if ( jQuery.isArray( elems ) ) {
265 push.apply( ret, elems );
268 jQuery.merge( ret, elems );
271 // Add the old object onto the stack (as a reference)
272 ret.prevObject = this;
274 ret.context = this.context;
276 if ( name === "find" ) {
277 ret.selector = this.selector + (this.selector ? " " : "") + selector;
279 ret.selector = this.selector + "." + name + "(" + selector + ")";
282 // Return the newly-formed element set
286 // Execute a callback for every element in the matched set.
287 // (You can seed the arguments with an array of args, but this is
288 // only used internally.)
289 each: function( callback, args ) {
290 return jQuery.each( this, callback, args );
293 ready: function( fn ) {
294 // Attach the listeners
298 readyList.done( fn );
306 this.slice( i, +i + 1 );
314 return this.eq( -1 );
318 return this.pushStack( slice.apply( this, arguments ),
319 "slice", slice.call(arguments).join(",") );
322 map: function( callback ) {
323 return this.pushStack( jQuery.map(this, function( elem, i ) {
324 return callback.call( elem, i, elem );
329 return this.prevObject || this.constructor(null);
332 // For internal use only.
333 // Behaves like an Array's method, not like a jQuery method.
339 // Give the init function the jQuery prototype for later instantiation
340 jQuery.fn.init.prototype = jQuery.fn;
342 jQuery.extend = jQuery.fn.extend = function() {
343 var options, name, src, copy, copyIsArray, clone,
344 target = arguments[0] || {},
346 length = arguments.length,
349 // Handle a deep copy situation
350 if ( typeof target === "boolean" ) {
352 target = arguments[1] || {};
353 // skip the boolean and the target
357 // Handle case when target is a string or something (possible in deep copy)
358 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
362 // extend jQuery itself if only one argument is passed
363 if ( length === i ) {
368 for ( ; i < length; i++ ) {
369 // Only deal with non-null/undefined values
370 if ( (options = arguments[ i ]) != null ) {
371 // Extend the base object
372 for ( name in options ) {
373 src = target[ name ];
374 copy = options[ name ];
376 // Prevent never-ending loop
377 if ( target === copy ) {
381 // Recurse if we're merging plain objects or arrays
382 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
385 clone = src && jQuery.isArray(src) ? src : [];
388 clone = src && jQuery.isPlainObject(src) ? src : {};
391 // Never move original objects, clone them
392 target[ name ] = jQuery.extend( deep, clone, copy );
394 // Don't bring in undefined values
395 } else if ( copy !== undefined ) {
396 target[ name ] = copy;
402 // Return the modified object
407 noConflict: function( deep ) {
408 if ( window.$ === jQuery ) {
412 if ( deep && window.jQuery === jQuery ) {
413 window.jQuery = _jQuery;
419 // Is the DOM ready to be used? Set to true once it occurs.
422 // A counter to track how many items to wait for before
423 // the ready event fires. See #6781
426 // Hold (or release) the ready event
427 holdReady: function( hold ) {
431 jQuery.ready( true );
435 // Handle when the DOM is ready
436 ready: function( wait ) {
437 // Either a released hold or an DOMready/load event and not yet ready
438 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
439 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
440 if ( !document.body ) {
441 return setTimeout( jQuery.ready, 1 );
444 // Remember that the DOM is ready
445 jQuery.isReady = true;
447 // If a normal DOM Ready event fired, decrement, and wait if need be
448 if ( wait !== true && --jQuery.readyWait > 0 ) {
452 // If there are functions bound, to execute
453 readyList.resolveWith( document, [ jQuery ] );
455 // Trigger any bound ready events
456 if ( jQuery.fn.trigger ) {
457 jQuery( document ).trigger( "ready" ).unbind( "ready" );
462 bindReady: function() {
467 readyList = jQuery._Deferred();
469 // Catch cases where $(document).ready() is called after the
470 // browser event has already occurred.
471 if ( document.readyState === "complete" ) {
472 // Handle it asynchronously to allow scripts the opportunity to delay ready
473 return setTimeout( jQuery.ready, 1 );
476 // Mozilla, Opera and webkit nightlies currently support this event
477 if ( document.addEventListener ) {
478 // Use the handy event callback
479 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
481 // A fallback to window.onload, that will always work
482 window.addEventListener( "load", jQuery.ready, false );
484 // If IE event model is used
485 } else if ( document.attachEvent ) {
486 // ensure firing before onload,
487 // maybe late but safe also for iframes
488 document.attachEvent( "onreadystatechange", DOMContentLoaded );
490 // A fallback to window.onload, that will always work
491 window.attachEvent( "onload", jQuery.ready );
493 // If IE and not a frame
494 // continually check to see if the document is ready
495 var toplevel = false;
498 toplevel = window.frameElement == null;
501 if ( document.documentElement.doScroll && toplevel ) {
507 // See test/unit/core.js for details concerning isFunction.
508 // Since version 1.3, DOM methods and functions like alert
509 // aren't supported. They return false on IE (#2968).
510 isFunction: function( obj ) {
511 return jQuery.type(obj) === "function";
514 isArray: Array.isArray || function( obj ) {
515 return jQuery.type(obj) === "array";
518 // A crude way of determining if an object is a window
519 isWindow: function( obj ) {
520 return obj && typeof obj === "object" && "setInterval" in obj;
523 isNaN: function( obj ) {
524 return obj == null || !rdigit.test( obj ) || isNaN( obj );
527 type: function( obj ) {
530 class2type[ toString.call(obj) ] || "object";
533 isPlainObject: function( obj ) {
534 // Must be an Object.
535 // Because of IE, we also have to check the presence of the constructor property.
536 // Make sure that DOM nodes and window objects don't pass through, as well
537 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
542 // Not own constructor property must be Object
543 if ( obj.constructor &&
544 !hasOwn.call(obj, "constructor") &&
545 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
549 // IE8,9 Will throw exceptions on certain host objects #9897
553 // Own properties are enumerated firstly, so to speed up,
554 // if last one is own, then all properties are own.
557 for ( key in obj ) {}
559 return key === undefined || hasOwn.call( obj, key );
562 isEmptyObject: function( obj ) {
563 for ( var name in obj ) {
569 error: function( msg ) {
573 parseJSON: function( data ) {
574 if ( typeof data !== "string" || !data ) {
578 // Make sure leading/trailing whitespace is removed (IE can't handle it)
579 data = jQuery.trim( data );
581 // Attempt to parse using the native JSON parser first
582 if ( window.JSON && window.JSON.parse ) {
583 return window.JSON.parse( data );
586 // Make sure the incoming data is actual JSON
587 // Logic borrowed from http://json.org/json2.js
588 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
589 .replace( rvalidtokens, "]" )
590 .replace( rvalidbraces, "")) ) {
592 return (new Function( "return " + data ))();
595 jQuery.error( "Invalid JSON: " + data );
598 // Cross-browser xml parsing
599 parseXML: function( data ) {
602 if ( window.DOMParser ) { // Standard
603 tmp = new DOMParser();
604 xml = tmp.parseFromString( data , "text/xml" );
606 xml = new ActiveXObject( "Microsoft.XMLDOM" );
613 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
614 jQuery.error( "Invalid XML: " + data );
621 // Evaluates a script in a global context
622 // Workarounds based on findings by Jim Driscoll
623 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
624 globalEval: function( data ) {
625 if ( data && rnotwhite.test( data ) ) {
626 // We use execScript on Internet Explorer
627 // We use an anonymous function so that context is window
628 // rather than jQuery in Firefox
629 ( window.execScript || function( data ) {
630 window[ "eval" ].call( window, data );
635 // Convert dashed to camelCase; used by the css and data modules
636 // Microsoft forgot to hump their vendor prefix (#9572)
637 camelCase: function( string ) {
638 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
641 nodeName: function( elem, name ) {
642 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
645 // args is for internal usage only
646 each: function( object, callback, args ) {
648 length = object.length,
649 isObj = length === undefined || jQuery.isFunction( object );
653 for ( name in object ) {
654 if ( callback.apply( object[ name ], args ) === false ) {
659 for ( ; i < length; ) {
660 if ( callback.apply( object[ i++ ], args ) === false ) {
666 // A special, fast, case for the most common use of each
669 for ( name in object ) {
670 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
675 for ( ; i < length; ) {
676 if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
686 // Use native String.trim function wherever possible
689 return text == null ?
694 // Otherwise use our own trimming functionality
696 return text == null ?
698 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
701 // results is for internal usage only
702 makeArray: function( array, results ) {
703 var ret = results || [];
705 if ( array != null ) {
706 // The window, strings (and functions) also have 'length'
707 // The extra typeof function check is to prevent crashes
708 // in Safari 2 (See: #3039)
709 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
710 var type = jQuery.type( array );
712 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
713 push.call( ret, array );
715 jQuery.merge( ret, array );
722 inArray: function( elem, array ) {
728 return indexOf.call( array, elem );
731 for ( var i = 0, length = array.length; i < length; i++ ) {
732 if ( array[ i ] === elem ) {
740 merge: function( first, second ) {
741 var i = first.length,
744 if ( typeof second.length === "number" ) {
745 for ( var l = second.length; j < l; j++ ) {
746 first[ i++ ] = second[ j ];
750 while ( second[j] !== undefined ) {
751 first[ i++ ] = second[ j++ ];
760 grep: function( elems, callback, inv ) {
761 var ret = [], retVal;
764 // Go through the array, only saving the items
765 // that pass the validator function
766 for ( var i = 0, length = elems.length; i < length; i++ ) {
767 retVal = !!callback( elems[ i ], i );
768 if ( inv !== retVal ) {
769 ret.push( elems[ i ] );
776 // arg is for internal usage only
777 map: function( elems, callback, arg ) {
778 var value, key, ret = [],
780 length = elems.length,
781 // jquery objects are treated as arrays
782 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
784 // Go through the array, translating each of the items to their
786 for ( ; i < length; i++ ) {
787 value = callback( elems[ i ], i, arg );
789 if ( value != null ) {
790 ret[ ret.length ] = value;
794 // Go through every key on the object,
796 for ( key in elems ) {
797 value = callback( elems[ key ], key, arg );
799 if ( value != null ) {
800 ret[ ret.length ] = value;
805 // Flatten any nested arrays
806 return ret.concat.apply( [], ret );
809 // A global GUID counter for objects
812 // Bind a function to a context, optionally partially applying any
814 proxy: function( fn, context ) {
815 if ( typeof context === "string" ) {
816 var tmp = fn[ context ];
821 // Quick check to determine if target is callable, in the spec
822 // this throws a TypeError, but we will just return undefined.
823 if ( !jQuery.isFunction( fn ) ) {
828 var args = slice.call( arguments, 2 ),
830 return fn.apply( context, args.concat( slice.call( arguments ) ) );
833 // Set the guid of unique handler to the same of original handler, so it can be removed
834 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
839 // Mutifunctional method to get and set values to a collection
840 // The value/s can optionally be executed if it's a function
841 access: function( elems, key, value, exec, fn, pass ) {
842 var length = elems.length;
844 // Setting many attributes
845 if ( typeof key === "object" ) {
846 for ( var k in key ) {
847 jQuery.access( elems, k, key[k], exec, fn, value );
852 // Setting one attribute
853 if ( value !== undefined ) {
854 // Optionally, function values get executed if exec is true
855 exec = !pass && exec && jQuery.isFunction(value);
857 for ( var i = 0; i < length; i++ ) {
858 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
864 // Getting an attribute
865 return length ? fn( elems[0], key ) : undefined;
869 return (new Date()).getTime();
872 // Use of jQuery.browser is frowned upon.
873 // More details: http://docs.jquery.com/Utilities/jQuery.browser
874 uaMatch: function( ua ) {
875 ua = ua.toLowerCase();
877 var match = rwebkit.exec( ua ) ||
880 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
883 return { browser: match[1] || "", version: match[2] || "0" };
887 function jQuerySub( selector, context ) {
888 return new jQuerySub.fn.init( selector, context );
890 jQuery.extend( true, jQuerySub, this );
891 jQuerySub.superclass = this;
892 jQuerySub.fn = jQuerySub.prototype = this();
893 jQuerySub.fn.constructor = jQuerySub;
894 jQuerySub.sub = this.sub;
895 jQuerySub.fn.init = function init( selector, context ) {
896 if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
897 context = jQuerySub( context );
900 return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
902 jQuerySub.fn.init.prototype = jQuerySub.fn;
903 var rootjQuerySub = jQuerySub(document);
910 // Populate the class2type map
911 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
912 class2type[ "[object " + name + "]" ] = name.toLowerCase();
915 browserMatch = jQuery.uaMatch( userAgent );
916 if ( browserMatch.browser ) {
917 jQuery.browser[ browserMatch.browser ] = true;
918 jQuery.browser.version = browserMatch.version;
921 // Deprecated, use jQuery.browser.webkit instead
922 if ( jQuery.browser.webkit ) {
923 jQuery.browser.safari = true;
926 // IE doesn't match non-breaking spaces with \s
927 if ( rnotwhite.test( "\xA0" ) ) {
928 trimLeft = /^[\s\xA0]+/;
929 trimRight = /[\s\xA0]+$/;
932 // All jQuery objects should point back to these
933 rootjQuery = jQuery(document);
935 // Cleanup functions for the document ready method
936 if ( document.addEventListener ) {
937 DOMContentLoaded = function() {
938 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
942 } else if ( document.attachEvent ) {
943 DOMContentLoaded = function() {
944 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
945 if ( document.readyState === "complete" ) {
946 document.detachEvent( "onreadystatechange", DOMContentLoaded );
952 // The DOM ready check for Internet Explorer
953 function doScrollCheck() {
954 if ( jQuery.isReady ) {
959 // If IE is used, use the trick by Diego Perini
960 // http://javascript.nwbox.com/IEContentLoaded/
961 document.documentElement.doScroll("left");
963 setTimeout( doScrollCheck, 1 );
967 // and execute any waiting functions
976 var // Promise methods
977 promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
978 // Static reference to slice
979 sliceDeferred = [].slice;
982 // Create a simple deferred (one callbacks list)
983 _Deferred: function() {
984 var // callbacks list
986 // stored [ context , args ]
988 // to avoid firing when already doing so
990 // flag to know if the deferred has been cancelled
992 // the deferred itself
995 // done( f1, f2, ...)
998 var args = arguments,
1008 for ( i = 0, length = args.length; i < length; i++ ) {
1010 type = jQuery.type( elem );
1011 if ( type === "array" ) {
1012 deferred.done.apply( deferred, elem );
1013 } else if ( type === "function" ) {
1014 callbacks.push( elem );
1018 deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
1024 // resolve with given context and args
1025 resolveWith: function( context, args ) {
1026 if ( !cancelled && !fired && !firing ) {
1027 // make sure args are available (#8421)
1031 while( callbacks[ 0 ] ) {
1032 callbacks.shift().apply( context, args );
1036 fired = [ context, args ];
1043 // resolve with this as context and given arguments
1044 resolve: function() {
1045 deferred.resolveWith( this, arguments );
1049 // Has this deferred been resolved?
1050 isResolved: function() {
1051 return !!( firing || fired );
1055 cancel: function() {
1065 // Full fledged deferred (two callbacks list)
1066 Deferred: function( func ) {
1067 var deferred = jQuery._Deferred(),
1068 failDeferred = jQuery._Deferred(),
1070 // Add errorDeferred methods, then and promise
1071 jQuery.extend( deferred, {
1072 then: function( doneCallbacks, failCallbacks ) {
1073 deferred.done( doneCallbacks ).fail( failCallbacks );
1076 always: function() {
1077 return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
1079 fail: failDeferred.done,
1080 rejectWith: failDeferred.resolveWith,
1081 reject: failDeferred.resolve,
1082 isRejected: failDeferred.isResolved,
1083 pipe: function( fnDone, fnFail ) {
1084 return jQuery.Deferred(function( newDefer ) {
1086 done: [ fnDone, "resolve" ],
1087 fail: [ fnFail, "reject" ]
1088 }, function( handler, data ) {
1092 if ( jQuery.isFunction( fn ) ) {
1093 deferred[ handler ](function() {
1094 returned = fn.apply( this, arguments );
1095 if ( returned && jQuery.isFunction( returned.promise ) ) {
1096 returned.promise().then( newDefer.resolve, newDefer.reject );
1098 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1102 deferred[ handler ]( newDefer[ action ] );
1107 // Get a promise for this deferred
1108 // If obj is provided, the promise aspect is added to the object
1109 promise: function( obj ) {
1110 if ( obj == null ) {
1116 var i = promiseMethods.length;
1118 obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
1123 // Make sure only one callback list will be used
1124 deferred.done( failDeferred.cancel ).fail( deferred.cancel );
1126 delete deferred.cancel;
1127 // Call given func if any
1129 func.call( deferred, deferred );
1135 when: function( firstParam ) {
1136 var args = arguments,
1138 length = args.length,
1140 deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
1143 function resolveFunc( i ) {
1144 return function( value ) {
1145 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1146 if ( !( --count ) ) {
1147 // Strange bug in FF4:
1148 // Values changed onto the arguments object sometimes end up as undefined values
1149 // outside the $.when method. Cloning the object into a fresh array solves the issue
1150 deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
1155 for( ; i < length; i++ ) {
1156 if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
1157 args[ i ].promise().then( resolveFunc(i), deferred.reject );
1163 deferred.resolveWith( deferred, args );
1165 } else if ( deferred !== firstParam ) {
1166 deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1168 return deferred.promise();
1174 jQuery.support = (function() {
1176 var div = document.createElement( "div" ),
1177 documentElement = document.documentElement,
1196 // Preliminary tests
1197 div.setAttribute("className", "t");
1198 div.innerHTML = " <link><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type=checkbox>";
1201 all = div.getElementsByTagName( "*" );
1202 a = div.getElementsByTagName( "a" )[ 0 ];
1204 // Can't get basic test support
1205 if ( !all || !all.length || !a ) {
1209 // First batch of supports tests
1210 select = document.createElement( "select" );
1211 opt = select.appendChild( document.createElement("option") );
1212 input = div.getElementsByTagName( "input" )[ 0 ];
1215 // IE strips leading whitespace when .innerHTML is used
1216 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1218 // Make sure that tbody elements aren't automatically inserted
1219 // IE will insert them into empty tables
1220 tbody: !div.getElementsByTagName( "tbody" ).length,
1222 // Make sure that link elements get serialized correctly by innerHTML
1223 // This requires a wrapper element in IE
1224 htmlSerialize: !!div.getElementsByTagName( "link" ).length,
1226 // Get the style information from getAttribute
1227 // (IE uses .cssText instead)
1228 style: /top/.test( a.getAttribute("style") ),
1230 // Make sure that URLs aren't manipulated
1231 // (IE normalizes it by default)
1232 hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
1234 // Make sure that element opacity exists
1235 // (IE uses filter instead)
1236 // Use a regex to work around a WebKit issue. See #5145
1237 opacity: /^0.55$/.test( a.style.opacity ),
1239 // Verify style float existence
1240 // (IE uses styleFloat instead of cssFloat)
1241 cssFloat: !!a.style.cssFloat,
1243 // Make sure that if no value is specified for a checkbox
1244 // that it defaults to "on".
1245 // (WebKit defaults to "" instead)
1246 checkOn: ( input.value === "on" ),
1248 // Make sure that a selected-by-default option has a working selected property.
1249 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1250 optSelected: opt.selected,
1252 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1253 getSetAttribute: div.className !== "t",
1255 // Will be defined later
1256 submitBubbles: true,
1257 changeBubbles: true,
1258 focusinBubbles: false,
1259 deleteExpando: true,
1261 inlineBlockNeedsLayout: false,
1262 shrinkWrapBlocks: false,
1263 reliableMarginRight: true
1266 // Make sure checked status is properly cloned
1267 input.checked = true;
1268 support.noCloneChecked = input.cloneNode( true ).checked;
1270 // Make sure that the options inside disabled selects aren't marked as disabled
1271 // (WebKit marks them as disabled)
1272 select.disabled = true;
1273 support.optDisabled = !opt.disabled;
1275 // Test to see if it's possible to delete an expando from an element
1276 // Fails in Internet Explorer
1280 support.deleteExpando = false;
1283 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1284 div.attachEvent( "onclick", function() {
1285 // Cloning a node shouldn't copy over any
1286 // bound event handlers (IE does this)
1287 support.noCloneEvent = false;
1289 div.cloneNode( true ).fireEvent( "onclick" );
1292 // Check if a radio maintains it's value
1293 // after being appended to the DOM
1294 input = document.createElement("input");
1296 input.setAttribute("type", "radio");
1297 support.radioValue = input.value === "t";
1299 input.setAttribute("checked", "checked");
1300 div.appendChild( input );
1301 fragment = document.createDocumentFragment();
1302 fragment.appendChild( div.firstChild );
1304 // WebKit doesn't clone checked state correctly in fragments
1305 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1309 // Figure out if the W3C box model works as expected
1310 div.style.width = div.style.paddingLeft = "1px";
1312 body = document.getElementsByTagName( "body" )[ 0 ];
1313 // We use our own, invisible, body unless the body is already present
1314 // in which case we use a div (#9239)
1315 testElement = document.createElement( body ? "div" : "body" );
1316 testElementStyle = {
1317 visibility: "hidden",
1325 jQuery.extend( testElementStyle, {
1326 position: "absolute",
1331 for ( i in testElementStyle ) {
1332 testElement.style[ i ] = testElementStyle[ i ];
1334 testElement.appendChild( div );
1335 testElementParent = body || documentElement;
1336 testElementParent.insertBefore( testElement, testElementParent.firstChild );
1338 // Check if a disconnected checkbox will retain its checked
1339 // value of true after appended to the DOM (IE6/7)
1340 support.appendChecked = input.checked;
1342 support.boxModel = div.offsetWidth === 2;
1344 if ( "zoom" in div.style ) {
1345 // Check if natively block-level elements act like inline-block
1346 // elements when setting their display to 'inline' and giving
1348 // (IE < 8 does this)
1349 div.style.display = "inline";
1351 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
1353 // Check if elements with layout shrink-wrap their children
1355 div.style.display = "";
1356 div.innerHTML = "<div style='width:4px;'></div>";
1357 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
1360 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
1361 tds = div.getElementsByTagName( "td" );
1363 // Check if table cells still have offsetWidth/Height when they are set
1364 // to display:none and there are still other visible table cells in a
1365 // table row; if so, offsetWidth/Height are not reliable for use when
1366 // determining if an element has been hidden directly using
1367 // display:none (it is still safe to use offsets if a parent element is
1368 // hidden; don safety goggles and see bug #4512 for more information).
1369 // (only IE 8 fails this test)
1370 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1372 tds[ 0 ].style.display = "";
1373 tds[ 1 ].style.display = "none";
1375 // Check if empty table cells still have offsetWidth/Height
1376 // (IE < 8 fail this test)
1377 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1380 // Check if div with explicit width and no margin-right incorrectly
1381 // gets computed margin-right based on width of container. For more
1382 // info see bug #3333
1383 // Fails in WebKit before Feb 2011 nightlies
1384 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1385 if ( document.defaultView && document.defaultView.getComputedStyle ) {
1386 marginDiv = document.createElement( "div" );
1387 marginDiv.style.width = "0";
1388 marginDiv.style.marginRight = "0";
1389 div.appendChild( marginDiv );
1390 support.reliableMarginRight =
1391 ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
1394 // Remove the body element we added
1395 testElement.innerHTML = "";
1396 testElementParent.removeChild( testElement );
1398 // Technique from Juriy Zaytsev
1399 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
1400 // We only care about the case where non-standard event systems
1401 // are used, namely in IE. Short-circuiting here helps us to
1402 // avoid an eval call (in setAttribute) which can cause CSP
1403 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1404 if ( div.attachEvent ) {
1410 eventName = "on" + i;
1411 isSupported = ( eventName in div );
1412 if ( !isSupported ) {
1413 div.setAttribute( eventName, "return;" );
1414 isSupported = ( typeof div[ eventName ] === "function" );
1416 support[ i + "Bubbles" ] = isSupported;
1420 // Null connected elements to avoid leaks in IE
1421 testElement = fragment = select = opt = body = marginDiv = div = input = null;
1426 // Keep track of boxModel
1427 jQuery.boxModel = jQuery.support.boxModel;
1432 var rbrace = /^(?:\{.*\}|\[.*\])$/,
1433 rmultiDash = /([a-z])([A-Z])/g;
1438 // Please use with caution
1441 // Unique for each copy of jQuery on the page
1442 // Non-digits removed to match rinlinejQuery
1443 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1445 // The following elements throw uncatchable exceptions if you
1446 // attempt to add expando properties to them.
1449 // Ban all objects except for Flash (which handle expandos)
1450 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1454 hasData: function( elem ) {
1455 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1457 return !!elem && !isEmptyDataObject( elem );
1460 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1461 if ( !jQuery.acceptData( elem ) ) {
1466 internalKey = jQuery.expando,
1467 getByName = typeof name === "string",
1469 // We have to handle DOM nodes and JS objects differently because IE6-7
1470 // can't GC object references properly across the DOM-JS boundary
1471 isNode = elem.nodeType,
1473 // Only DOM nodes need the global jQuery cache; JS object data is
1474 // attached directly to the object so GC can occur automatically
1475 cache = isNode ? jQuery.cache : elem,
1477 // Only defining an ID for JS objects if its cache already exists allows
1478 // the code to shortcut on the same path as a DOM node with no cache
1479 id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
1481 // Avoid doing any more work than we need to when trying to get data on an
1482 // object that has no data at all
1483 if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) {
1488 // Only DOM nodes need a new unique ID for each element since their data
1489 // ends up in the global cache
1491 elem[ jQuery.expando ] = id = ++jQuery.uuid;
1493 id = jQuery.expando;
1497 if ( !cache[ id ] ) {
1500 // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
1501 // metadata on plain JS objects when the object is serialized using
1504 cache[ id ].toJSON = jQuery.noop;
1508 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1509 // shallow copied over onto the existing cache
1510 if ( typeof name === "object" || typeof name === "function" ) {
1512 cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
1514 cache[ id ] = jQuery.extend(cache[ id ], name);
1518 thisCache = cache[ id ];
1520 // Internal jQuery data is stored in a separate object inside the object's data
1521 // cache in order to avoid key collisions between internal data and user-defined
1524 if ( !thisCache[ internalKey ] ) {
1525 thisCache[ internalKey ] = {};
1528 thisCache = thisCache[ internalKey ];
1531 if ( data !== undefined ) {
1532 thisCache[ jQuery.camelCase( name ) ] = data;
1535 // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
1536 // not attempt to inspect the internal events object using jQuery.data, as this
1537 // internal data object is undocumented and subject to change.
1538 if ( name === "events" && !thisCache[name] ) {
1539 return thisCache[ internalKey ] && thisCache[ internalKey ].events;
1542 // Check for both converted-to-camel and non-converted data property names
1543 // If a data property was specified
1546 // First Try to find as-is property data
1547 ret = thisCache[ name ];
1549 // Test for null|undefined property data
1550 if ( ret == null ) {
1552 // Try to find the camelCased property
1553 ret = thisCache[ jQuery.camelCase( name ) ];
1562 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1563 if ( !jQuery.acceptData( elem ) ) {
1569 // Reference to internal data cache key
1570 internalKey = jQuery.expando,
1572 isNode = elem.nodeType,
1574 // See jQuery.data for more information
1575 cache = isNode ? jQuery.cache : elem,
1577 // See jQuery.data for more information
1578 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1580 // If there is already no cache entry for this object, there is no
1581 // purpose in continuing
1582 if ( !cache[ id ] ) {
1588 thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
1592 // Support interoperable removal of hyphenated or camelcased keys
1593 if ( !thisCache[ name ] ) {
1594 name = jQuery.camelCase( name );
1597 delete thisCache[ name ];
1599 // If there is no data left in the cache, we want to continue
1600 // and let the cache object itself get destroyed
1601 if ( !isEmptyDataObject(thisCache) ) {
1607 // See jQuery.data for more information
1609 delete cache[ id ][ internalKey ];
1611 // Don't destroy the parent cache unless the internal data object
1612 // had been the only thing left in it
1613 if ( !isEmptyDataObject(cache[ id ]) ) {
1618 var internalCache = cache[ id ][ internalKey ];
1620 // Browsers that fail expando deletion also refuse to delete expandos on
1621 // the window, but it will allow it on all other JS objects; other browsers
1623 // Ensure that `cache` is not a window object #10080
1624 if ( jQuery.support.deleteExpando || !cache.setInterval ) {
1630 // We destroyed the entire user cache at once because it's faster than
1631 // iterating through each key, but we need to continue to persist internal
1632 // data if it existed
1633 if ( internalCache ) {
1635 // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
1636 // metadata on plain JS objects when the object is serialized using
1639 cache[ id ].toJSON = jQuery.noop;
1642 cache[ id ][ internalKey ] = internalCache;
1644 // Otherwise, we need to eliminate the expando on the node to avoid
1645 // false lookups in the cache for entries that no longer exist
1646 } else if ( isNode ) {
1647 // IE does not allow us to delete expando properties from nodes,
1648 // nor does it have a removeAttribute function on Document nodes;
1649 // we must handle all of these cases
1650 if ( jQuery.support.deleteExpando ) {
1651 delete elem[ jQuery.expando ];
1652 } else if ( elem.removeAttribute ) {
1653 elem.removeAttribute( jQuery.expando );
1655 elem[ jQuery.expando ] = null;
1660 // For internal use only.
1661 _data: function( elem, name, data ) {
1662 return jQuery.data( elem, name, data, true );
1665 // A method for determining if a DOM node can handle the data expando
1666 acceptData: function( elem ) {
1667 if ( elem.nodeName ) {
1668 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
1671 return !(match === true || elem.getAttribute("classid") !== match);
1680 data: function( key, value ) {
1683 if ( typeof key === "undefined" ) {
1684 if ( this.length ) {
1685 data = jQuery.data( this[0] );
1687 if ( this[0].nodeType === 1 ) {
1688 var attr = this[0].attributes, name;
1689 for ( var i = 0, l = attr.length; i < l; i++ ) {
1690 name = attr[i].name;
1692 if ( name.indexOf( "data-" ) === 0 ) {
1693 name = jQuery.camelCase( name.substring(5) );
1695 dataAttr( this[0], name, data[ name ] );
1703 } else if ( typeof key === "object" ) {
1704 return this.each(function() {
1705 jQuery.data( this, key );
1709 var parts = key.split(".");
1710 parts[1] = parts[1] ? "." + parts[1] : "";
1712 if ( value === undefined ) {
1713 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1715 // Try to fetch any internally stored data first
1716 if ( data === undefined && this.length ) {
1717 data = jQuery.data( this[0], key );
1718 data = dataAttr( this[0], key, data );
1721 return data === undefined && parts[1] ?
1722 this.data( parts[0] ) :
1726 return this.each(function() {
1727 var $this = jQuery( this ),
1728 args = [ parts[0], value ];
1730 $this.triggerHandler( "setData" + parts[1] + "!", args );
1731 jQuery.data( this, key, value );
1732 $this.triggerHandler( "changeData" + parts[1] + "!", args );
1737 removeData: function( key ) {
1738 return this.each(function() {
1739 jQuery.removeData( this, key );
1744 function dataAttr( elem, key, data ) {
1745 // If nothing was found internally, try to fetch any
1746 // data from the HTML5 data-* attribute
1747 if ( data === undefined && elem.nodeType === 1 ) {
1748 var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
1750 data = elem.getAttribute( name );
1752 if ( typeof data === "string" ) {
1754 data = data === "true" ? true :
1755 data === "false" ? false :
1756 data === "null" ? null :
1757 !jQuery.isNaN( data ) ? parseFloat( data ) :
1758 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1762 // Make sure we set the data so it isn't changed later
1763 jQuery.data( elem, key, data );
1773 // TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
1774 // property to be considered empty objects; this property always exists in
1775 // order to make sure JSON.stringify does not expose internal metadata
1776 function isEmptyDataObject( obj ) {
1777 for ( var name in obj ) {
1778 if ( name !== "toJSON" ) {
1789 function handleQueueMarkDefer( elem, type, src ) {
1790 var deferDataKey = type + "defer",
1791 queueDataKey = type + "queue",
1792 markDataKey = type + "mark",
1793 defer = jQuery.data( elem, deferDataKey, undefined, true );
1795 ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
1796 ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
1797 // Give room for hard-coded callbacks to fire first
1798 // and eventually mark/queue something else on the element
1799 setTimeout( function() {
1800 if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
1801 !jQuery.data( elem, markDataKey, undefined, true ) ) {
1802 jQuery.removeData( elem, deferDataKey, true );
1811 _mark: function( elem, type ) {
1813 type = (type || "fx") + "mark";
1814 jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
1818 _unmark: function( force, elem, type ) {
1819 if ( force !== true ) {
1825 type = type || "fx";
1826 var key = type + "mark",
1827 count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
1829 jQuery.data( elem, key, count, true );
1831 jQuery.removeData( elem, key, true );
1832 handleQueueMarkDefer( elem, type, "mark" );
1837 queue: function( elem, type, data ) {
1839 type = (type || "fx") + "queue";
1840 var q = jQuery.data( elem, type, undefined, true );
1841 // Speed up dequeue by getting out quickly if this is just a lookup
1843 if ( !q || jQuery.isArray(data) ) {
1844 q = jQuery.data( elem, type, jQuery.makeArray(data), true );
1853 dequeue: function( elem, type ) {
1854 type = type || "fx";
1856 var queue = jQuery.queue( elem, type ),
1860 // If the fx queue is dequeued, always remove the progress sentinel
1861 if ( fn === "inprogress" ) {
1866 // Add a progress sentinel to prevent the fx queue from being
1867 // automatically dequeued
1868 if ( type === "fx" ) {
1869 queue.unshift("inprogress");
1872 fn.call(elem, function() {
1873 jQuery.dequeue(elem, type);
1877 if ( !queue.length ) {
1878 jQuery.removeData( elem, type + "queue", true );
1879 handleQueueMarkDefer( elem, type, "queue" );
1885 queue: function( type, data ) {
1886 if ( typeof type !== "string" ) {
1891 if ( data === undefined ) {
1892 return jQuery.queue( this[0], type );
1894 return this.each(function() {
1895 var queue = jQuery.queue( this, type, data );
1897 if ( type === "fx" && queue[0] !== "inprogress" ) {
1898 jQuery.dequeue( this, type );
1902 dequeue: function( type ) {
1903 return this.each(function() {
1904 jQuery.dequeue( this, type );
1907 // Based off of the plugin by Clint Helfers, with permission.
1908 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1909 delay: function( time, type ) {
1910 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1911 type = type || "fx";
1913 return this.queue( type, function() {
1915 setTimeout(function() {
1916 jQuery.dequeue( elem, type );
1920 clearQueue: function( type ) {
1921 return this.queue( type || "fx", [] );
1923 // Get a promise resolved when queues of a certain type
1924 // are emptied (fx is the type by default)
1925 promise: function( type, object ) {
1926 if ( typeof type !== "string" ) {
1930 type = type || "fx";
1931 var defer = jQuery.Deferred(),
1933 i = elements.length,
1935 deferDataKey = type + "defer",
1936 queueDataKey = type + "queue",
1937 markDataKey = type + "mark",
1939 function resolve() {
1940 if ( !( --count ) ) {
1941 defer.resolveWith( elements, [ elements ] );
1945 if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
1946 ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
1947 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
1948 jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
1950 tmp.done( resolve );
1954 return defer.promise();
1961 var rclass = /[\n\t\r]/g,
1964 rtype = /^(?:button|input)$/i,
1965 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1966 rclickable = /^a(?:rea)?$/i,
1967 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
1971 attr: function( name, value ) {
1972 return jQuery.access( this, name, value, true, jQuery.attr );
1975 removeAttr: function( name ) {
1976 return this.each(function() {
1977 jQuery.removeAttr( this, name );
1981 prop: function( name, value ) {
1982 return jQuery.access( this, name, value, true, jQuery.prop );
1985 removeProp: function( name ) {
1986 name = jQuery.propFix[ name ] || name;
1987 return this.each(function() {
1988 // try/catch handles cases where IE balks (such as removing a property on window)
1990 this[ name ] = undefined;
1991 delete this[ name ];
1996 addClass: function( value ) {
1997 var classNames, i, l, elem,
2000 if ( jQuery.isFunction( value ) ) {
2001 return this.each(function( j ) {
2002 jQuery( this ).addClass( value.call(this, j, this.className) );
2006 if ( value && typeof value === "string" ) {
2007 classNames = value.split( rspace );
2009 for ( i = 0, l = this.length; i < l; i++ ) {
2012 if ( elem.nodeType === 1 ) {
2013 if ( !elem.className && classNames.length === 1 ) {
2014 elem.className = value;
2017 setClass = " " + elem.className + " ";
2019 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2020 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2021 setClass += classNames[ c ] + " ";
2024 elem.className = jQuery.trim( setClass );
2033 removeClass: function( value ) {
2034 var classNames, i, l, elem, className, c, cl;
2036 if ( jQuery.isFunction( value ) ) {
2037 return this.each(function( j ) {
2038 jQuery( this ).removeClass( value.call(this, j, this.className) );
2042 if ( (value && typeof value === "string") || value === undefined ) {
2043 classNames = (value || "").split( rspace );
2045 for ( i = 0, l = this.length; i < l; i++ ) {
2048 if ( elem.nodeType === 1 && elem.className ) {
2050 className = (" " + elem.className + " ").replace( rclass, " " );
2051 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2052 className = className.replace(" " + classNames[ c ] + " ", " ");
2054 elem.className = jQuery.trim( className );
2057 elem.className = "";
2066 toggleClass: function( value, stateVal ) {
2067 var type = typeof value,
2068 isBool = typeof stateVal === "boolean";
2070 if ( jQuery.isFunction( value ) ) {
2071 return this.each(function( i ) {
2072 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2076 return this.each(function() {
2077 if ( type === "string" ) {
2078 // toggle individual class names
2081 self = jQuery( this ),
2083 classNames = value.split( rspace );
2085 while ( (className = classNames[ i++ ]) ) {
2086 // check each className given, space seperated list
2087 state = isBool ? state : !self.hasClass( className );
2088 self[ state ? "addClass" : "removeClass" ]( className );
2091 } else if ( type === "undefined" || type === "boolean" ) {
2092 if ( this.className ) {
2093 // store className if set
2094 jQuery._data( this, "__className__", this.className );
2097 // toggle whole className
2098 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2103 hasClass: function( selector ) {
2104 var className = " " + selector + " ";
2105 for ( var i = 0, l = this.length; i < l; i++ ) {
2106 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2114 val: function( value ) {
2118 if ( !arguments.length ) {
2120 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2122 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2128 return typeof ret === "string" ?
2129 // handle most common string cases
2130 ret.replace(rreturn, "") :
2131 // handle cases where value is null/undef or number
2132 ret == null ? "" : ret;
2138 var isFunction = jQuery.isFunction( value );
2140 return this.each(function( i ) {
2141 var self = jQuery(this), val;
2143 if ( this.nodeType !== 1 ) {
2148 val = value.call( this, i, self.val() );
2153 // Treat null/undefined as ""; convert numbers to string
2154 if ( val == null ) {
2156 } else if ( typeof val === "number" ) {
2158 } else if ( jQuery.isArray( val ) ) {
2159 val = jQuery.map(val, function ( value ) {
2160 return value == null ? "" : value + "";
2164 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
2166 // If set returns undefined, fall back to normal setting
2167 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2177 get: function( elem ) {
2178 // attributes.value is undefined in Blackberry 4.7 but
2179 // uses .value. See #6932
2180 var val = elem.attributes.value;
2181 return !val || val.specified ? elem.value : elem.text;
2185 get: function( elem ) {
2187 index = elem.selectedIndex,
2189 options = elem.options,
2190 one = elem.type === "select-one";
2192 // Nothing was selected
2197 // Loop through all the selected options
2198 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
2199 var option = options[ i ];
2201 // Don't return options that are disabled or in a disabled optgroup
2202 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2203 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2205 // Get the specific value for the option
2206 value = jQuery( option ).val();
2208 // We don't need an array for one selects
2213 // Multi-Selects return an array
2214 values.push( value );
2218 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2219 if ( one && !values.length && options.length ) {
2220 return jQuery( options[ index ] ).val();
2226 set: function( elem, value ) {
2227 var values = jQuery.makeArray( value );
2229 jQuery(elem).find("option").each(function() {
2230 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2233 if ( !values.length ) {
2234 elem.selectedIndex = -1;
2253 // Always normalize to ensure hook usage
2254 tabindex: "tabIndex"
2257 attr: function( elem, name, value, pass ) {
2258 var nType = elem.nodeType;
2260 // don't get/set attributes on text, comment and attribute nodes
2261 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2265 if ( pass && name in jQuery.attrFn ) {
2266 return jQuery( elem )[ name ]( value );
2269 // Fallback to prop when attributes are not supported
2270 if ( !("getAttribute" in elem) ) {
2271 return jQuery.prop( elem, name, value );
2275 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2277 // Normalize the name if needed
2279 name = jQuery.attrFix[ name ] || name;
2281 hooks = jQuery.attrHooks[ name ];
2284 // Use boolHook for boolean attributes
2285 if ( rboolean.test( name ) ) {
2288 // Use nodeHook if available( IE6/7 )
2289 } else if ( nodeHook ) {
2295 if ( value !== undefined ) {
2297 if ( value === null ) {
2298 jQuery.removeAttr( elem, name );
2301 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2305 elem.setAttribute( name, "" + value );
2309 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2314 ret = elem.getAttribute( name );
2316 // Non-existent attributes return null, we normalize to undefined
2317 return ret === null ?
2323 removeAttr: function( elem, name ) {
2325 if ( elem.nodeType === 1 ) {
2326 name = jQuery.attrFix[ name ] || name;
2328 jQuery.attr( elem, name, "" );
2329 elem.removeAttribute( name );
2331 // Set corresponding property to false for boolean attributes
2332 if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
2333 elem[ propName ] = false;
2340 set: function( elem, value ) {
2341 // We can't allow the type property to be changed (since it causes problems in IE)
2342 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2343 jQuery.error( "type property can't be changed" );
2344 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2345 // Setting the type on a radio button after the value resets the value in IE6-9
2346 // Reset value to it's default in case type is set after value
2347 // This is for element creation
2348 var val = elem.value;
2349 elem.setAttribute( "type", value );
2357 // Use the value property for back compat
2358 // Use the nodeHook for button elements in IE6/7 (#1954)
2360 get: function( elem, name ) {
2361 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2362 return nodeHook.get( elem, name );
2364 return name in elem ?
2368 set: function( elem, value, name ) {
2369 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2370 return nodeHook.set( elem, value, name );
2372 // Does not return so that setAttribute is also used
2379 tabindex: "tabIndex",
2380 readonly: "readOnly",
2382 "class": "className",
2383 maxlength: "maxLength",
2384 cellspacing: "cellSpacing",
2385 cellpadding: "cellPadding",
2389 frameborder: "frameBorder",
2390 contenteditable: "contentEditable"
2393 prop: function( elem, name, value ) {
2394 var nType = elem.nodeType;
2396 // don't get/set properties on text, comment and attribute nodes
2397 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2402 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2405 // Fix name and attach hooks
2406 name = jQuery.propFix[ name ] || name;
2407 hooks = jQuery.propHooks[ name ];
2410 if ( value !== undefined ) {
2411 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2415 return (elem[ name ] = value);
2419 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2423 return elem[ name ];
2430 get: function( elem ) {
2431 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2432 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2433 var attributeNode = elem.getAttributeNode("tabindex");
2435 return attributeNode && attributeNode.specified ?
2436 parseInt( attributeNode.value, 10 ) :
2437 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2445 // Add the tabindex propHook to attrHooks for back-compat
2446 jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex;
2448 // Hook for boolean attributes
2450 get: function( elem, name ) {
2451 // Align boolean attributes with corresponding properties
2452 // Fall back to attribute presence where some booleans are not supported
2454 return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ?
2455 name.toLowerCase() :
2458 set: function( elem, value, name ) {
2460 if ( value === false ) {
2461 // Remove boolean attributes when set to false
2462 jQuery.removeAttr( elem, name );
2464 // value is true since we know at this point it's type boolean and not false
2465 // Set boolean attributes to the same name and set the DOM property
2466 propName = jQuery.propFix[ name ] || name;
2467 if ( propName in elem ) {
2468 // Only set the IDL specifically if it already exists on the element
2469 elem[ propName ] = true;
2472 elem.setAttribute( name, name.toLowerCase() );
2478 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2479 if ( !jQuery.support.getSetAttribute ) {
2481 // Use this for any attribute in IE6/7
2482 // This fixes almost every IE6/7 issue
2483 nodeHook = jQuery.valHooks.button = {
2484 get: function( elem, name ) {
2486 ret = elem.getAttributeNode( name );
2487 // Return undefined if nodeValue is empty string
2488 return ret && ret.nodeValue !== "" ?
2492 set: function( elem, value, name ) {
2493 // Set the existing or create a new attribute node
2494 var ret = elem.getAttributeNode( name );
2496 ret = document.createAttribute( name );
2497 elem.setAttributeNode( ret );
2499 return (ret.nodeValue = value + "");
2503 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2504 // This is for removals
2505 jQuery.each([ "width", "height" ], function( i, name ) {
2506 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2507 set: function( elem, value ) {
2508 if ( value === "" ) {
2509 elem.setAttribute( name, "auto" );
2518 // Some attributes require a special call on IE
2519 if ( !jQuery.support.hrefNormalized ) {
2520 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2521 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2522 get: function( elem ) {
2523 var ret = elem.getAttribute( name, 2 );
2524 return ret === null ? undefined : ret;
2530 if ( !jQuery.support.style ) {
2531 jQuery.attrHooks.style = {
2532 get: function( elem ) {
2533 // Return undefined in the case of empty string
2534 // Normalize to lowercase since IE uppercases css property names
2535 return elem.style.cssText.toLowerCase() || undefined;
2537 set: function( elem, value ) {
2538 return (elem.style.cssText = "" + value);
2543 // Safari mis-reports the default selected property of an option
2544 // Accessing the parent's selectedIndex property fixes it
2545 if ( !jQuery.support.optSelected ) {
2546 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2547 get: function( elem ) {
2548 var parent = elem.parentNode;
2551 parent.selectedIndex;
2553 // Make sure that it also works with optgroups, see #5701
2554 if ( parent.parentNode ) {
2555 parent.parentNode.selectedIndex;
2563 // Radios and checkboxes getter/setter
2564 if ( !jQuery.support.checkOn ) {
2565 jQuery.each([ "radio", "checkbox" ], function() {
2566 jQuery.valHooks[ this ] = {
2567 get: function( elem ) {
2568 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2569 return elem.getAttribute("value") === null ? "on" : elem.value;
2574 jQuery.each([ "radio", "checkbox" ], function() {
2575 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2576 set: function( elem, value ) {
2577 if ( jQuery.isArray( value ) ) {
2578 return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
2587 var rnamespaces = /\.(.*)$/,
2588 rformElems = /^(?:textarea|input|select)$/i,
2591 rescape = /[^\w\s.|`]/g,
2592 fcleanup = function( nm ) {
2593 return nm.replace(rescape, "\\$&");
2597 * A number of helper functions used for managing events.
2598 * Many of the ideas behind this code originated from
2599 * Dean Edwards' addEvent library.
2603 // Bind an event to an element
2604 // Original by Dean Edwards
2605 add: function( elem, types, handler, data ) {
2606 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2610 if ( handler === false ) {
2611 handler = returnFalse;
2612 } else if ( !handler ) {
2613 // Fixes bug #7229. Fix recommended by jdalton
2617 var handleObjIn, handleObj;
2619 if ( handler.handler ) {
2620 handleObjIn = handler;
2621 handler = handleObjIn.handler;
2624 // Make sure that the function being executed has a unique ID
2625 if ( !handler.guid ) {
2626 handler.guid = jQuery.guid++;
2629 // Init the element's event structure
2630 var elemData = jQuery._data( elem );
2632 // If no elemData is found then we must be trying to bind to one of the
2633 // banned noData elements
2638 var events = elemData.events,
2639 eventHandle = elemData.handle;
2642 elemData.events = events = {};
2645 if ( !eventHandle ) {
2646 elemData.handle = eventHandle = function( e ) {
2647 // Discard the second event of a jQuery.event.trigger() and
2648 // when an event is called after a page has unloaded
2649 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2650 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
2655 // Add elem as a property of the handle function
2656 // This is to prevent a memory leak with non-native events in IE.
2657 eventHandle.elem = elem;
2659 // Handle multiple events separated by a space
2660 // jQuery(...).bind("mouseover mouseout", fn);
2661 types = types.split(" ");
2663 var type, i = 0, namespaces;
2665 while ( (type = types[ i++ ]) ) {
2666 handleObj = handleObjIn ?
2667 jQuery.extend({}, handleObjIn) :
2668 { handler: handler, data: data };
2670 // Namespaced event handlers
2671 if ( type.indexOf(".") > -1 ) {
2672 namespaces = type.split(".");
2673 type = namespaces.shift();
2674 handleObj.namespace = namespaces.slice(0).sort().join(".");
2678 handleObj.namespace = "";
2681 handleObj.type = type;
2682 if ( !handleObj.guid ) {
2683 handleObj.guid = handler.guid;
2686 // Get the current list of functions bound to this event
2687 var handlers = events[ type ],
2688 special = jQuery.event.special[ type ] || {};
2690 // Init the event handler queue
2692 handlers = events[ type ] = [];
2694 // Check for a special event handler
2695 // Only use addEventListener/attachEvent if the special
2696 // events handler returns false
2697 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2698 // Bind the global event handler to the element
2699 if ( elem.addEventListener ) {
2700 elem.addEventListener( type, eventHandle, false );
2702 } else if ( elem.attachEvent ) {
2703 elem.attachEvent( "on" + type, eventHandle );
2708 if ( special.add ) {
2709 special.add.call( elem, handleObj );
2711 if ( !handleObj.handler.guid ) {
2712 handleObj.handler.guid = handler.guid;
2716 // Add the function to the element's handler list
2717 handlers.push( handleObj );
2719 // Keep track of which events have been used, for event optimization
2720 jQuery.event.global[ type ] = true;
2723 // Nullify elem to prevent memory leaks in IE
2729 // Detach an event or set of events from an element
2730 remove: function( elem, types, handler, pos ) {
2731 // don't do events on text and comment nodes
2732 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2736 if ( handler === false ) {
2737 handler = returnFalse;
2740 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
2741 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
2742 events = elemData && elemData.events;
2744 if ( !elemData || !events ) {
2748 // types is actually an event object here
2749 if ( types && types.type ) {
2750 handler = types.handler;
2754 // Unbind all events for the element
2755 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
2756 types = types || "";
2758 for ( type in events ) {
2759 jQuery.event.remove( elem, type + types );
2765 // Handle multiple events separated by a space
2766 // jQuery(...).unbind("mouseover mouseout", fn);
2767 types = types.split(" ");
2769 while ( (type = types[ i++ ]) ) {
2772 all = type.indexOf(".") < 0;
2776 // Namespaced event handlers
2777 namespaces = type.split(".");
2778 type = namespaces.shift();
2780 namespace = new RegExp("(^|\\.)" +
2781 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
2784 eventType = events[ type ];
2791 for ( j = 0; j < eventType.length; j++ ) {
2792 handleObj = eventType[ j ];
2794 if ( all || namespace.test( handleObj.namespace ) ) {
2795 jQuery.event.remove( elem, origType, handleObj.handler, j );
2796 eventType.splice( j--, 1 );
2803 special = jQuery.event.special[ type ] || {};
2805 for ( j = pos || 0; j < eventType.length; j++ ) {
2806 handleObj = eventType[ j ];
2808 if ( handler.guid === handleObj.guid ) {
2809 // remove the given handler for the given type
2810 if ( all || namespace.test( handleObj.namespace ) ) {
2811 if ( pos == null ) {
2812 eventType.splice( j--, 1 );
2815 if ( special.remove ) {
2816 special.remove.call( elem, handleObj );
2820 if ( pos != null ) {
2826 // remove generic event handler if no more handlers exist
2827 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
2828 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
2829 jQuery.removeEvent( elem, type, elemData.handle );
2833 delete events[ type ];
2837 // Remove the expando if it's no longer used
2838 if ( jQuery.isEmptyObject( events ) ) {
2839 var handle = elemData.handle;
2844 delete elemData.events;
2845 delete elemData.handle;
2847 if ( jQuery.isEmptyObject( elemData ) ) {
2848 jQuery.removeData( elem, undefined, true );
2853 // Events that are safe to short-circuit if no handlers are attached.
2854 // Native DOM events should not be added, they may have inline handlers.
2861 trigger: function( event, data, elem, onlyHandlers ) {
2862 // Event object or event type
2863 var type = event.type || event,
2867 if ( type.indexOf("!") >= 0 ) {
2868 // Exclusive events trigger only for the exact event (no namespaces)
2869 type = type.slice(0, -1);
2873 if ( type.indexOf(".") >= 0 ) {
2874 // Namespaced trigger; create a regexp to match event type in handle()
2875 namespaces = type.split(".");
2876 type = namespaces.shift();
2880 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
2881 // No jQuery handlers for this event type, and it can't have inline handlers
2885 // Caller can pass in an Event, Object, or just an event type string
2886 event = typeof event === "object" ?
2887 // jQuery.Event object
2888 event[ jQuery.expando ] ? event :
2890 new jQuery.Event( type, event ) :
2891 // Just the event type (string)
2892 new jQuery.Event( type );
2895 event.exclusive = exclusive;
2896 event.namespace = namespaces.join(".");
2897 event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
2899 // triggerHandler() and global events don't bubble or run the default action
2900 if ( onlyHandlers || !elem ) {
2901 event.preventDefault();
2902 event.stopPropagation();
2905 // Handle a global trigger
2907 // TODO: Stop taunting the data cache; remove global events and always attach to document
2908 jQuery.each( jQuery.cache, function() {
2909 // internalKey variable is just used to make it easier to find
2910 // and potentially change this stuff later; currently it just
2911 // points to jQuery.expando
2912 var internalKey = jQuery.expando,
2913 internalCache = this[ internalKey ];
2914 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
2915 jQuery.event.trigger( event, data, internalCache.handle.elem );
2921 // Don't do events on text and comment nodes
2922 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2926 // Clean up the event in case it is being reused
2927 event.result = undefined;
2928 event.target = elem;
2930 // Clone any incoming data and prepend the event, creating the handler arg list
2931 data = data != null ? jQuery.makeArray( data ) : [];
2932 data.unshift( event );
2935 // IE doesn't like method names with a colon (#3533, #8272)
2936 ontype = type.indexOf(":") < 0 ? "on" + type : "";
2938 // Fire event on the current element, then bubble up the DOM tree
2940 var handle = jQuery._data( cur, "handle" );
2942 event.currentTarget = cur;
2944 handle.apply( cur, data );
2947 // Trigger an inline bound script
2948 if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
2949 event.result = false;
2950 event.preventDefault();
2953 // Bubble up to document, then to window
2954 cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
2955 } while ( cur && !event.isPropagationStopped() );
2957 // If nobody prevented the default action, do it now
2958 if ( !event.isDefaultPrevented() ) {
2960 special = jQuery.event.special[ type ] || {};
2962 if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
2963 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2965 // Call a native DOM method on the target with the same name name as the event.
2966 // Can't use an .isFunction)() check here because IE6/7 fails that test.
2967 // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
2969 if ( ontype && elem[ type ] ) {
2970 // Don't re-trigger an onFOO event when we call its FOO() method
2971 old = elem[ ontype ];
2974 elem[ ontype ] = null;
2977 jQuery.event.triggered = type;
2980 } catch ( ieError ) {}
2983 elem[ ontype ] = old;
2986 jQuery.event.triggered = undefined;
2990 return event.result;
2993 handle: function( event ) {
2994 event = jQuery.event.fix( event || window.event );
2995 // Snapshot the handlers list since a called handler may add/remove events.
2996 var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
2997 run_all = !event.exclusive && !event.namespace,
2998 args = Array.prototype.slice.call( arguments, 0 );
3000 // Use the fix-ed Event rather than the (read-only) native event
3002 event.currentTarget = this;
3004 for ( var j = 0, l = handlers.length; j < l; j++ ) {
3005 var handleObj = handlers[ j ];
3007 // Triggered event must 1) be non-exclusive and have no namespace, or
3008 // 2) have namespace(s) a subset or equal to those in the bound event.
3009 if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
3010 // Pass in a reference to the handler function itself
3011 // So that we can later remove it
3012 event.handler = handleObj.handler;
3013 event.data = handleObj.data;
3014 event.handleObj = handleObj;
3016 var ret = handleObj.handler.apply( this, args );
3018 if ( ret !== undefined ) {
3020 if ( ret === false ) {
3021 event.preventDefault();
3022 event.stopPropagation();
3026 if ( event.isImmediatePropagationStopped() ) {
3031 return event.result;
3034 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
3036 fix: function( event ) {
3037 if ( event[ jQuery.expando ] ) {
3041 // store a copy of the original event object
3042 // and "clone" to set read-only properties
3043 var originalEvent = event;
3044 event = jQuery.Event( originalEvent );
3046 for ( var i = this.props.length, prop; i; ) {
3047 prop = this.props[ --i ];
3048 event[ prop ] = originalEvent[ prop ];
3051 // Fix target property, if necessary
3052 if ( !event.target ) {
3053 // Fixes #1925 where srcElement might not be defined either
3054 event.target = event.srcElement || document;
3057 // check if target is a textnode (safari)
3058 if ( event.target.nodeType === 3 ) {
3059 event.target = event.target.parentNode;
3062 // Add relatedTarget, if necessary
3063 if ( !event.relatedTarget && event.fromElement ) {
3064 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
3067 // Calculate pageX/Y if missing and clientX/Y available
3068 if ( event.pageX == null && event.clientX != null ) {
3069 var eventDocument = event.target.ownerDocument || document,
3070 doc = eventDocument.documentElement,
3071 body = eventDocument.body;
3073 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3074 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
3077 // Add which for key events
3078 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
3079 event.which = event.charCode != null ? event.charCode : event.keyCode;
3082 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
3083 if ( !event.metaKey && event.ctrlKey ) {
3084 event.metaKey = event.ctrlKey;
3087 // Add which for click: 1 === left; 2 === middle; 3 === right
3088 // Note: button is not normalized, so don't use it
3089 if ( !event.which && event.button !== undefined ) {
3090 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
3096 // Deprecated, use jQuery.guid instead
3099 // Deprecated, use jQuery.proxy instead
3100 proxy: jQuery.proxy,
3104 // Make sure the ready event is setup
3105 setup: jQuery.bindReady,
3106 teardown: jQuery.noop
3110 add: function( handleObj ) {
3111 jQuery.event.add( this,
3112 liveConvert( handleObj.origType, handleObj.selector ),
3113 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
3116 remove: function( handleObj ) {
3117 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
3122 setup: function( data, namespaces, eventHandle ) {
3123 // We only want to do this special case on windows
3124 if ( jQuery.isWindow( this ) ) {
3125 this.onbeforeunload = eventHandle;
3129 teardown: function( namespaces, eventHandle ) {
3130 if ( this.onbeforeunload === eventHandle ) {
3131 this.onbeforeunload = null;
3138 jQuery.removeEvent = document.removeEventListener ?
3139 function( elem, type, handle ) {
3140 if ( elem.removeEventListener ) {
3141 elem.removeEventListener( type, handle, false );
3144 function( elem, type, handle ) {
3145 if ( elem.detachEvent ) {
3146 elem.detachEvent( "on" + type, handle );
3150 jQuery.Event = function( src, props ) {
3151 // Allow instantiation without the 'new' keyword
3152 if ( !this.preventDefault ) {
3153 return new jQuery.Event( src, props );
3157 if ( src && src.type ) {
3158 this.originalEvent = src;
3159 this.type = src.type;
3161 // Events bubbling up the document may have been marked as prevented
3162 // by a handler lower down the tree; reflect the correct value.
3163 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
3164 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
3171 // Put explicitly provided properties onto the event object
3173 jQuery.extend( this, props );
3176 // timeStamp is buggy for some events on Firefox(#3843)
3177 // So we won't rely on the native value
3178 this.timeStamp = jQuery.now();
3181 this[ jQuery.expando ] = true;
3184 function returnFalse() {
3187 function returnTrue() {
3191 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3192 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3193 jQuery.Event.prototype = {
3194 preventDefault: function() {
3195 this.isDefaultPrevented = returnTrue;
3197 var e = this.originalEvent;
3202 // if preventDefault exists run it on the original event
3203 if ( e.preventDefault ) {
3206 // otherwise set the returnValue property of the original event to false (IE)
3208 e.returnValue = false;
3211 stopPropagation: function() {
3212 this.isPropagationStopped = returnTrue;
3214 var e = this.originalEvent;
3218 // if stopPropagation exists run it on the original event
3219 if ( e.stopPropagation ) {
3220 e.stopPropagation();
3222 // otherwise set the cancelBubble property of the original event to true (IE)
3223 e.cancelBubble = true;
3225 stopImmediatePropagation: function() {
3226 this.isImmediatePropagationStopped = returnTrue;
3227 this.stopPropagation();
3229 isDefaultPrevented: returnFalse,
3230 isPropagationStopped: returnFalse,
3231 isImmediatePropagationStopped: returnFalse
3234 // Checks if an event happened on an element within another element
3235 // Used in jQuery.event.special.mouseenter and mouseleave handlers
3236 var withinElement = function( event ) {
3238 // Check if mouse(over|out) are still within the same parent element
3239 var related = event.relatedTarget,
3241 eventType = event.type;
3243 event.type = event.data;
3245 if ( related !== this ) {
3248 inside = jQuery.contains( this, related );
3253 jQuery.event.handle.apply( this, arguments );
3255 event.type = eventType;
3260 // In case of event delegation, we only need to rename the event.type,
3261 // liveHandler will take care of the rest.
3262 delegate = function( event ) {
3263 event.type = event.data;
3264 jQuery.event.handle.apply( this, arguments );
3267 // Create mouseenter and mouseleave events
3269 mouseenter: "mouseover",
3270 mouseleave: "mouseout"
3271 }, function( orig, fix ) {
3272 jQuery.event.special[ orig ] = {
3273 setup: function( data ) {
3274 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
3276 teardown: function( data ) {
3277 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
3282 // submit delegation
3283 if ( !jQuery.support.submitBubbles ) {
3285 jQuery.event.special.submit = {
3286 setup: function( data, namespaces ) {
3287 if ( !jQuery.nodeName( this, "form" ) ) {
3288 jQuery.event.add(this, "click.specialSubmit", function( e ) {
3289 var elem = e.target,
3290 type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3292 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
3293 trigger( "submit", this, arguments );
3297 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
3298 var elem = e.target,
3299 type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3301 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
3302 trigger( "submit", this, arguments );
3311 teardown: function( namespaces ) {
3312 jQuery.event.remove( this, ".specialSubmit" );
3318 // change delegation, happens here so we have bind.
3319 if ( !jQuery.support.changeBubbles ) {
3323 getVal = function( elem ) {
3324 var type = jQuery.nodeName( elem, "input" ) ? elem.type : "",
3327 if ( type === "radio" || type === "checkbox" ) {
3330 } else if ( type === "select-multiple" ) {
3331 val = elem.selectedIndex > -1 ?
3332 jQuery.map( elem.options, function( elem ) {
3333 return elem.selected;
3337 } else if ( jQuery.nodeName( elem, "select" ) ) {
3338 val = elem.selectedIndex;
3344 testChange = function testChange( e ) {
3345 var elem = e.target, data, val;
3347 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
3351 data = jQuery._data( elem, "_change_data" );
3354 // the current data will be also retrieved by beforeactivate
3355 if ( e.type !== "focusout" || elem.type !== "radio" ) {
3356 jQuery._data( elem, "_change_data", val );
3359 if ( data === undefined || val === data ) {
3363 if ( data != null || val ) {
3365 e.liveFired = undefined;
3366 jQuery.event.trigger( e, arguments[1], elem );
3370 jQuery.event.special.change = {
3372 focusout: testChange,
3374 beforedeactivate: testChange,
3376 click: function( e ) {
3377 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3379 if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
3380 testChange.call( this, e );
3384 // Change has to be called before submit
3385 // Keydown will be called before keypress, which is used in submit-event delegation
3386 keydown: function( e ) {
3387 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3389 if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
3390 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
3391 type === "select-multiple" ) {
3392 testChange.call( this, e );
3396 // Beforeactivate happens also before the previous element is blurred
3397 // with this event you can't trigger a change event, but you can store
3399 beforeactivate: function( e ) {
3400 var elem = e.target;
3401 jQuery._data( elem, "_change_data", getVal(elem) );
3405 setup: function( data, namespaces ) {
3406 if ( this.type === "file" ) {
3410 for ( var type in changeFilters ) {
3411 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
3414 return rformElems.test( this.nodeName );
3417 teardown: function( namespaces ) {
3418 jQuery.event.remove( this, ".specialChange" );
3420 return rformElems.test( this.nodeName );
3424 changeFilters = jQuery.event.special.change.filters;
3426 // Handle when the input is .focus()'d
3427 changeFilters.focus = changeFilters.beforeactivate;
3430 function trigger( type, elem, args ) {
3431 // Piggyback on a donor event to simulate a different one.
3432 // Fake originalEvent to avoid donor's stopPropagation, but if the
3433 // simulated event prevents default then we do the same on the donor.
3434 // Don't pass args or remember liveFired; they apply to the donor event.
3435 var event = jQuery.extend( {}, args[ 0 ] );
3437 event.originalEvent = {};
3438 event.liveFired = undefined;
3439 jQuery.event.handle.call( elem, event );
3440 if ( event.isDefaultPrevented() ) {
3441 args[ 0 ].preventDefault();
3445 // Create "bubbling" focus and blur events
3446 if ( !jQuery.support.focusinBubbles ) {
3447 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3449 // Attach a single capturing handler while someone wants focusin/focusout
3452 jQuery.event.special[ fix ] = {
3454 if ( attaches++ === 0 ) {
3455 document.addEventListener( orig, handler, true );
3458 teardown: function() {
3459 if ( --attaches === 0 ) {
3460 document.removeEventListener( orig, handler, true );
3465 function handler( donor ) {
3466 // Donor event is always a native one; fix it and switch its type.
3467 // Let focusin/out handler cancel the donor focus/blur event.
3468 var e = jQuery.event.fix( donor );
3470 e.originalEvent = {};
3471 jQuery.event.trigger( e, null, e.target );
3472 if ( e.isDefaultPrevented() ) {
3473 donor.preventDefault();
3479 jQuery.each(["bind", "one"], function( i, name ) {
3480 jQuery.fn[ name ] = function( type, data, fn ) {
3483 // Handle object literals
3484 if ( typeof type === "object" ) {
3485 for ( var key in type ) {
3486 this[ name ](key, data, type[key], fn);
3491 if ( arguments.length === 2 || data === false ) {
3496 if ( name === "one" ) {
3497 handler = function( event ) {
3498 jQuery( this ).unbind( event, handler );
3499 return fn.apply( this, arguments );
3501 handler.guid = fn.guid || jQuery.guid++;
3506 if ( type === "unload" && name !== "one" ) {
3507 this.one( type, data, fn );
3510 for ( var i = 0, l = this.length; i < l; i++ ) {
3511 jQuery.event.add( this[i], type, handler, data );
3520 unbind: function( type, fn ) {
3521 // Handle object literals
3522 if ( typeof type === "object" && !type.preventDefault ) {
3523 for ( var key in type ) {
3524 this.unbind(key, type[key]);
3528 for ( var i = 0, l = this.length; i < l; i++ ) {
3529 jQuery.event.remove( this[i], type, fn );
3536 delegate: function( selector, types, data, fn ) {
3537 return this.live( types, data, fn, selector );
3540 undelegate: function( selector, types, fn ) {
3541 if ( arguments.length === 0 ) {
3542 return this.unbind( "live" );
3545 return this.die( types, null, fn, selector );
3549 trigger: function( type, data ) {
3550 return this.each(function() {
3551 jQuery.event.trigger( type, data, this );
3555 triggerHandler: function( type, data ) {
3557 return jQuery.event.trigger( type, data, this[0], true );
3561 toggle: function( fn ) {
3562 // Save reference to arguments for access in closure
3563 var args = arguments,
3564 guid = fn.guid || jQuery.guid++,
3566 toggler = function( event ) {
3567 // Figure out which function to execute
3568 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
3569 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
3571 // Make sure that clicks stop
3572 event.preventDefault();
3574 // and execute the function
3575 return args[ lastToggle ].apply( this, arguments ) || false;
3578 // link all the functions, so any of them can unbind this click handler
3579 toggler.guid = guid;
3580 while ( i < args.length ) {
3581 args[ i++ ].guid = guid;
3584 return this.click( toggler );
3587 hover: function( fnOver, fnOut ) {
3588 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3595 mouseenter: "mouseover",
3596 mouseleave: "mouseout"
3599 jQuery.each(["live", "die"], function( i, name ) {
3600 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
3601 var type, i = 0, match, namespaces, preType,
3602 selector = origSelector || this.selector,
3603 context = origSelector ? this : jQuery( this.context );
3605 if ( typeof types === "object" && !types.preventDefault ) {
3606 for ( var key in types ) {
3607 context[ name ]( key, data, types[key], selector );
3613 if ( name === "die" && !types &&
3614 origSelector && origSelector.charAt(0) === "." ) {
3616 context.unbind( origSelector );
3621 if ( data === false || jQuery.isFunction( data ) ) {
3622 fn = data || returnFalse;
3626 types = (types || "").split(" ");
3628 while ( (type = types[ i++ ]) != null ) {
3629 match = rnamespaces.exec( type );
3633 namespaces = match[0];
3634 type = type.replace( rnamespaces, "" );
3637 if ( type === "hover" ) {
3638 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
3644 if ( liveMap[ type ] ) {
3645 types.push( liveMap[ type ] + namespaces );
3646 type = type + namespaces;
3649 type = (liveMap[ type ] || type) + namespaces;
3652 if ( name === "live" ) {
3653 // bind live handler
3654 for ( var j = 0, l = context.length; j < l; j++ ) {
3655 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
3656 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
3660 // unbind live handler
3661 context.unbind( "live." + liveConvert( type, selector ), fn );
3669 function liveHandler( event ) {
3670 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
3673 events = jQuery._data( this, "events" );
3675 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
3676 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
3680 if ( event.namespace ) {
3681 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
3684 event.liveFired = this;
3686 var live = events.live.slice(0);
3688 for ( j = 0; j < live.length; j++ ) {
3689 handleObj = live[j];
3691 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
3692 selectors.push( handleObj.selector );
3695 live.splice( j--, 1 );
3699 match = jQuery( event.target ).closest( selectors, event.currentTarget );
3701 for ( i = 0, l = match.length; i < l; i++ ) {
3704 for ( j = 0; j < live.length; j++ ) {
3705 handleObj = live[j];
3707 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
3711 // Those two events require additional checking
3712 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
3713 event.type = handleObj.preType;
3714 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
3716 // Make sure not to accidentally match a child element with the same selector
3717 if ( related && jQuery.contains( elem, related ) ) {
3722 if ( !related || related !== elem ) {
3723 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
3729 for ( i = 0, l = elems.length; i < l; i++ ) {
3732 if ( maxLevel && match.level > maxLevel ) {
3736 event.currentTarget = match.elem;
3737 event.data = match.handleObj.data;
3738 event.handleObj = match.handleObj;
3740 ret = match.handleObj.origHandler.apply( match.elem, arguments );
3742 if ( ret === false || event.isPropagationStopped() ) {
3743 maxLevel = match.level;
3745 if ( ret === false ) {
3748 if ( event.isImmediatePropagationStopped() ) {
3757 function liveConvert( type, selector ) {
3758 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
3761 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3762 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3763 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
3765 // Handle event binding
3766 jQuery.fn[ name ] = function( data, fn ) {
3772 return arguments.length > 0 ?
3773 this.bind( name, data, fn ) :
3774 this.trigger( name );
3777 if ( jQuery.attrFn ) {
3778 jQuery.attrFn[ name ] = true;
3785 * Sizzle CSS Selector Engine
3786 * Copyright 2011, The Dojo Foundation
3787 * Released under the MIT, BSD, and GPL Licenses.
3788 * More information: http://sizzlejs.com/
3792 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3794 toString = Object.prototype.toString,
3795 hasDuplicate = false,
3796 baseHasDuplicate = true,
3800 // Here we check if the JavaScript engine is using some sort of
3801 // optimization where it does not always call our comparision
3802 // function. If that is the case, discard the hasDuplicate value.
3803 // Thus far that includes Google Chrome.
3804 [0, 0].sort(function() {
3805 baseHasDuplicate = false;
3809 var Sizzle = function( selector, context, results, seed ) {
3810 results = results || [];
3811 context = context || document;
3813 var origContext = context;
3815 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
3819 if ( !selector || typeof selector !== "string" ) {
3823 var m, set, checkSet, extra, ret, cur, pop, i,
3825 contextXML = Sizzle.isXML( context ),
3829 // Reset the position of the chunker regexp (start from head)
3832 m = chunker.exec( soFar );
3846 if ( parts.length > 1 && origPOS.exec( selector ) ) {
3848 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
3849 set = posProcess( parts[0] + parts[1], context );
3852 set = Expr.relative[ parts[0] ] ?
3854 Sizzle( parts.shift(), context );
3856 while ( parts.length ) {
3857 selector = parts.shift();
3859 if ( Expr.relative[ selector ] ) {
3860 selector += parts.shift();
3863 set = posProcess( selector, set );
3868 // Take a shortcut and set the context if the root selector is an ID
3869 // (but not if it'll be faster if the inner selector is an ID)
3870 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
3871 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
3873 ret = Sizzle.find( parts.shift(), context, contextXML );
3874 context = ret.expr ?
3875 Sizzle.filter( ret.expr, ret.set )[0] :
3881 { expr: parts.pop(), set: makeArray(seed) } :
3882 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
3885 Sizzle.filter( ret.expr, ret.set ) :
3888 if ( parts.length > 0 ) {
3889 checkSet = makeArray( set );
3895 while ( parts.length ) {
3899 if ( !Expr.relative[ cur ] ) {
3905 if ( pop == null ) {
3909 Expr.relative[ cur ]( checkSet, pop, contextXML );
3913 checkSet = parts = [];
3922 Sizzle.error( cur || selector );
3925 if ( toString.call(checkSet) === "[object Array]" ) {
3927 results.push.apply( results, checkSet );
3929 } else if ( context && context.nodeType === 1 ) {
3930 for ( i = 0; checkSet[i] != null; i++ ) {
3931 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
3932 results.push( set[i] );
3937 for ( i = 0; checkSet[i] != null; i++ ) {
3938 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
3939 results.push( set[i] );
3945 makeArray( checkSet, results );
3949 Sizzle( extra, origContext, results, seed );
3950 Sizzle.uniqueSort( results );
3956 Sizzle.uniqueSort = function( results ) {
3958 hasDuplicate = baseHasDuplicate;
3959 results.sort( sortOrder );
3961 if ( hasDuplicate ) {
3962 for ( var i = 1; i < results.length; i++ ) {
3963 if ( results[i] === results[ i - 1 ] ) {
3964 results.splice( i--, 1 );
3973 Sizzle.matches = function( expr, set ) {
3974 return Sizzle( expr, null, null, set );
3977 Sizzle.matchesSelector = function( node, expr ) {
3978 return Sizzle( expr, null, null, [node] ).length > 0;
3981 Sizzle.find = function( expr, context, isXML ) {
3988 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
3990 type = Expr.order[i];
3992 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
3993 var left = match[1];
3994 match.splice( 1, 1 );
3996 if ( left.substr( left.length - 1 ) !== "\\" ) {
3997 match[1] = (match[1] || "").replace( rBackslash, "" );
3998 set = Expr.find[ type ]( match, context, isXML );
4000 if ( set != null ) {
4001 expr = expr.replace( Expr.match[ type ], "" );
4009 set = typeof context.getElementsByTagName !== "undefined" ?
4010 context.getElementsByTagName( "*" ) :
4014 return { set: set, expr: expr };
4017 Sizzle.filter = function( expr, set, inplace, not ) {
4018 var match, anyFound,
4022 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
4024 while ( expr && set.length ) {
4025 for ( var type in Expr.filter ) {
4026 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
4028 filter = Expr.filter[ type ],
4035 if ( left.substr( left.length - 1 ) === "\\" ) {
4039 if ( curLoop === result ) {
4043 if ( Expr.preFilter[ type ] ) {
4044 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4047 anyFound = found = true;
4049 } else if ( match === true ) {
4055 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
4057 found = filter( item, match, i, curLoop );
4058 var pass = not ^ !!found;
4060 if ( inplace && found != null ) {
4068 } else if ( pass ) {
4069 result.push( item );
4076 if ( found !== undefined ) {
4081 expr = expr.replace( Expr.match[ type ], "" );
4092 // Improper expression
4093 if ( expr === old ) {
4094 if ( anyFound == null ) {
4095 Sizzle.error( expr );
4108 Sizzle.error = function( msg ) {
4109 throw "Syntax error, unrecognized expression: " + msg;
4112 var Expr = Sizzle.selectors = {
4113 order: [ "ID", "NAME", "TAG" ],
4116 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4117 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4118 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
4119 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
4120 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
4121 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
4122 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
4123 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
4129 "class": "className",
4134 href: function( elem ) {
4135 return elem.getAttribute( "href" );
4137 type: function( elem ) {
4138 return elem.getAttribute( "type" );
4143 "+": function(checkSet, part){
4144 var isPartStr = typeof part === "string",
4145 isTag = isPartStr && !rNonWord.test( part ),
4146 isPartStrNotTag = isPartStr && !isTag;
4149 part = part.toLowerCase();
4152 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4153 if ( (elem = checkSet[i]) ) {
4154 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4156 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
4162 if ( isPartStrNotTag ) {
4163 Sizzle.filter( part, checkSet, true );
4167 ">": function( checkSet, part ) {
4169 isPartStr = typeof part === "string",
4171 l = checkSet.length;
4173 if ( isPartStr && !rNonWord.test( part ) ) {
4174 part = part.toLowerCase();
4176 for ( ; i < l; i++ ) {
4180 var parent = elem.parentNode;
4181 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
4186 for ( ; i < l; i++ ) {
4190 checkSet[i] = isPartStr ?
4192 elem.parentNode === part;
4197 Sizzle.filter( part, checkSet, true );
4202 "": function(checkSet, part, isXML){
4207 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4208 part = part.toLowerCase();
4210 checkFn = dirNodeCheck;
4213 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
4216 "~": function( checkSet, part, isXML ) {
4221 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4222 part = part.toLowerCase();
4224 checkFn = dirNodeCheck;
4227 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
4232 ID: function( match, context, isXML ) {
4233 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4234 var m = context.getElementById(match[1]);
4235 // Check parentNode to catch when Blackberry 4.6 returns
4236 // nodes that are no longer in the document #6963
4237 return m && m.parentNode ? [m] : [];
4241 NAME: function( match, context ) {
4242 if ( typeof context.getElementsByName !== "undefined" ) {
4244 results = context.getElementsByName( match[1] );
4246 for ( var i = 0, l = results.length; i < l; i++ ) {
4247 if ( results[i].getAttribute("name") === match[1] ) {
4248 ret.push( results[i] );
4252 return ret.length === 0 ? null : ret;
4256 TAG: function( match, context ) {
4257 if ( typeof context.getElementsByTagName !== "undefined" ) {
4258 return context.getElementsByTagName( match[1] );
4263 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
4264 match = " " + match[1].replace( rBackslash, "" ) + " ";
4270 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
4272 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
4274 result.push( elem );
4277 } else if ( inplace ) {
4286 ID: function( match ) {
4287 return match[1].replace( rBackslash, "" );
4290 TAG: function( match, curLoop ) {
4291 return match[1].replace( rBackslash, "" ).toLowerCase();
4294 CHILD: function( match ) {
4295 if ( match[1] === "nth" ) {
4297 Sizzle.error( match[0] );
4300 match[2] = match[2].replace(/^\+|\s*/g, '');
4302 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
4303 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
4304 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
4305 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
4307 // calculate the numbers (first)n+(last) including if they are negative
4308 match[2] = (test[1] + (test[2] || 1)) - 0;
4309 match[3] = test[3] - 0;
4311 else if ( match[2] ) {
4312 Sizzle.error( match[0] );
4315 // TODO: Move to normal caching system
4321 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
4322 var name = match[1] = match[1].replace( rBackslash, "" );
4324 if ( !isXML && Expr.attrMap[name] ) {
4325 match[1] = Expr.attrMap[name];
4328 // Handle if an un-quoted value was used
4329 match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
4331 if ( match[2] === "~=" ) {
4332 match[4] = " " + match[4] + " ";
4338 PSEUDO: function( match, curLoop, inplace, result, not ) {
4339 if ( match[1] === "not" ) {
4340 // If we're dealing with a complex expression, or a simple one
4341 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
4342 match[3] = Sizzle(match[3], null, null, curLoop);
4345 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
4348 result.push.apply( result, ret );
4354 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
4361 POS: function( match ) {
4362 match.unshift( true );
4369 enabled: function( elem ) {
4370 return elem.disabled === false && elem.type !== "hidden";
4373 disabled: function( elem ) {
4374 return elem.disabled === true;
4377 checked: function( elem ) {
4378 return elem.checked === true;
4381 selected: function( elem ) {
4382 // Accessing this property makes selected-by-default
4383 // options in Safari work properly
4384 if ( elem.parentNode ) {
4385 elem.parentNode.selectedIndex;
4388 return elem.selected === true;
4391 parent: function( elem ) {
4392 return !!elem.firstChild;
4395 empty: function( elem ) {
4396 return !elem.firstChild;
4399 has: function( elem, i, match ) {
4400 return !!Sizzle( match[3], elem ).length;
4403 header: function( elem ) {
4404 return (/h\d/i).test( elem.nodeName );
4407 text: function( elem ) {
4408 var attr = elem.getAttribute( "type" ), type = elem.type;
4409 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4410 // use getAttribute instead to test this case
4411 return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
4414 radio: function( elem ) {
4415 return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
4418 checkbox: function( elem ) {
4419 return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
4422 file: function( elem ) {
4423 return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
4426 password: function( elem ) {
4427 return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
4430 submit: function( elem ) {
4431 var name = elem.nodeName.toLowerCase();
4432 return (name === "input" || name === "button") && "submit" === elem.type;
4435 image: function( elem ) {
4436 return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
4439 reset: function( elem ) {
4440 var name = elem.nodeName.toLowerCase();
4441 return (name === "input" || name === "button") && "reset" === elem.type;
4444 button: function( elem ) {
4445 var name = elem.nodeName.toLowerCase();
4446 return name === "input" && "button" === elem.type || name === "button";
4449 input: function( elem ) {
4450 return (/input|select|textarea|button/i).test( elem.nodeName );
4453 focus: function( elem ) {
4454 return elem === elem.ownerDocument.activeElement;
4458 first: function( elem, i ) {
4462 last: function( elem, i, match, array ) {
4463 return i === array.length - 1;
4466 even: function( elem, i ) {
4470 odd: function( elem, i ) {
4474 lt: function( elem, i, match ) {
4475 return i < match[3] - 0;
4478 gt: function( elem, i, match ) {
4479 return i > match[3] - 0;
4482 nth: function( elem, i, match ) {
4483 return match[3] - 0 === i;
4486 eq: function( elem, i, match ) {
4487 return match[3] - 0 === i;
4491 PSEUDO: function( elem, match, i, array ) {
4492 var name = match[1],
4493 filter = Expr.filters[ name ];
4496 return filter( elem, i, match, array );
4498 } else if ( name === "contains" ) {
4499 return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
4501 } else if ( name === "not" ) {
4504 for ( var j = 0, l = not.length; j < l; j++ ) {
4505 if ( not[j] === elem ) {
4513 Sizzle.error( name );
4517 CHILD: function( elem, match ) {
4518 var type = match[1],
4524 while ( (node = node.previousSibling) ) {
4525 if ( node.nodeType === 1 ) {
4530 if ( type === "first" ) {
4537 while ( (node = node.nextSibling) ) {
4538 if ( node.nodeType === 1 ) {
4546 var first = match[2],
4549 if ( first === 1 && last === 0 ) {
4553 var doneName = match[0],
4554 parent = elem.parentNode;
4556 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
4559 for ( node = parent.firstChild; node; node = node.nextSibling ) {
4560 if ( node.nodeType === 1 ) {
4561 node.nodeIndex = ++count;
4565 parent.sizcache = doneName;
4568 var diff = elem.nodeIndex - last;
4570 if ( first === 0 ) {
4574 return ( diff % first === 0 && diff / first >= 0 );
4579 ID: function( elem, match ) {
4580 return elem.nodeType === 1 && elem.getAttribute("id") === match;
4583 TAG: function( elem, match ) {
4584 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
4587 CLASS: function( elem, match ) {
4588 return (" " + (elem.className || elem.getAttribute("class")) + " ")
4589 .indexOf( match ) > -1;
4592 ATTR: function( elem, match ) {
4593 var name = match[1],
4594 result = Expr.attrHandle[ name ] ?
4595 Expr.attrHandle[ name ]( elem ) :
4596 elem[ name ] != null ?
4598 elem.getAttribute( name ),
4599 value = result + "",
4603 return result == null ?
4608 value.indexOf(check) >= 0 :
4610 (" " + value + " ").indexOf(check) >= 0 :
4612 value && result !== false :
4616 value.indexOf(check) === 0 :
4618 value.substr(value.length - check.length) === check :
4620 value === check || value.substr(0, check.length + 1) === check + "-" :
4624 POS: function( elem, match, i, array ) {
4625 var name = match[2],
4626 filter = Expr.setFilters[ name ];
4629 return filter( elem, i, match, array );
4635 var origPOS = Expr.match.POS,
4636 fescape = function(all, num){
4637 return "\\" + (num - 0 + 1);
4640 for ( var type in Expr.match ) {
4641 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
4642 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
4645 var makeArray = function( array, results ) {
4646 array = Array.prototype.slice.call( array, 0 );
4649 results.push.apply( results, array );
4656 // Perform a simple check to determine if the browser is capable of
4657 // converting a NodeList to an array using builtin methods.
4658 // Also verifies that the returned array holds DOM nodes
4659 // (which is not the case in the Blackberry browser)
4661 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
4663 // Provide a fallback method if it does not work
4665 makeArray = function( array, results ) {
4667 ret = results || [];
4669 if ( toString.call(array) === "[object Array]" ) {
4670 Array.prototype.push.apply( ret, array );
4673 if ( typeof array.length === "number" ) {
4674 for ( var l = array.length; i < l; i++ ) {
4675 ret.push( array[i] );
4679 for ( ; array[i]; i++ ) {
4680 ret.push( array[i] );
4689 var sortOrder, siblingCheck;
4691 if ( document.documentElement.compareDocumentPosition ) {
4692 sortOrder = function( a, b ) {
4694 hasDuplicate = true;
4698 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
4699 return a.compareDocumentPosition ? -1 : 1;
4702 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
4706 sortOrder = function( a, b ) {
4707 // The nodes are identical, we can exit early
4709 hasDuplicate = true;
4712 // Fallback to using sourceIndex (in IE) if it's available on both nodes
4713 } else if ( a.sourceIndex && b.sourceIndex ) {
4714 return a.sourceIndex - b.sourceIndex;
4724 // If the nodes are siblings (or identical) we can do a quick check
4725 if ( aup === bup ) {
4726 return siblingCheck( a, b );
4728 // If no parents were found then the nodes are disconnected
4729 } else if ( !aup ) {
4732 } else if ( !bup ) {
4736 // Otherwise they're somewhere else in the tree so we need
4737 // to build up a full list of the parentNodes for comparison
4740 cur = cur.parentNode;
4747 cur = cur.parentNode;
4753 // Start walking down the tree looking for a discrepancy
4754 for ( var i = 0; i < al && i < bl; i++ ) {
4755 if ( ap[i] !== bp[i] ) {
4756 return siblingCheck( ap[i], bp[i] );
4760 // We ended someplace up the tree so do a sibling check
4762 siblingCheck( a, bp[i], -1 ) :
4763 siblingCheck( ap[i], b, 1 );
4766 siblingCheck = function( a, b, ret ) {
4771 var cur = a.nextSibling;
4778 cur = cur.nextSibling;
4785 // Utility function for retreiving the text value of an array of DOM nodes
4786 Sizzle.getText = function( elems ) {
4789 for ( var i = 0; elems[i]; i++ ) {
4792 // Get the text from text nodes and CDATA nodes
4793 if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
4794 ret += elem.nodeValue;
4796 // Traverse everything else, except comment nodes
4797 } else if ( elem.nodeType !== 8 ) {
4798 ret += Sizzle.getText( elem.childNodes );
4805 // Check to see if the browser returns elements by name when
4806 // querying by getElementById (and provide a workaround)
4808 // We're going to inject a fake input element with a specified name
4809 var form = document.createElement("div"),
4810 id = "script" + (new Date()).getTime(),
4811 root = document.documentElement;
4813 form.innerHTML = "<a name='" + id + "'/>";
4815 // Inject it into the root element, check its status, and remove it quickly
4816 root.insertBefore( form, root.firstChild );
4818 // The workaround has to do additional checks after a getElementById
4819 // Which slows things down for other browsers (hence the branching)
4820 if ( document.getElementById( id ) ) {
4821 Expr.find.ID = function( match, context, isXML ) {
4822 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4823 var m = context.getElementById(match[1]);
4826 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
4833 Expr.filter.ID = function( elem, match ) {
4834 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4836 return elem.nodeType === 1 && node && node.nodeValue === match;
4840 root.removeChild( form );
4842 // release memory in IE
4847 // Check to see if the browser returns only elements
4848 // when doing getElementsByTagName("*")
4850 // Create a fake element
4851 var div = document.createElement("div");
4852 div.appendChild( document.createComment("") );
4854 // Make sure no comments are found
4855 if ( div.getElementsByTagName("*").length > 0 ) {
4856 Expr.find.TAG = function( match, context ) {
4857 var results = context.getElementsByTagName( match[1] );
4859 // Filter out possible comments
4860 if ( match[1] === "*" ) {
4863 for ( var i = 0; results[i]; i++ ) {
4864 if ( results[i].nodeType === 1 ) {
4865 tmp.push( results[i] );
4876 // Check to see if an attribute returns normalized href attributes
4877 div.innerHTML = "<a href='#'></a>";
4879 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
4880 div.firstChild.getAttribute("href") !== "#" ) {
4882 Expr.attrHandle.href = function( elem ) {
4883 return elem.getAttribute( "href", 2 );
4887 // release memory in IE
4891 if ( document.querySelectorAll ) {
4893 var oldSizzle = Sizzle,
4894 div = document.createElement("div"),
4897 div.innerHTML = "<p class='TEST'></p>";
4899 // Safari can't handle uppercase or unicode characters when
4901 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
4905 Sizzle = function( query, context, extra, seed ) {
4906 context = context || document;
4908 // Only use querySelectorAll on non-XML documents
4909 // (ID selectors don't work in non-HTML documents)
4910 if ( !seed && !Sizzle.isXML(context) ) {
4911 // See if we find a selector to speed up
4912 var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
4914 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
4915 // Speed-up: Sizzle("TAG")
4917 return makeArray( context.getElementsByTagName( query ), extra );
4919 // Speed-up: Sizzle(".CLASS")
4920 } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
4921 return makeArray( context.getElementsByClassName( match[2] ), extra );
4925 if ( context.nodeType === 9 ) {
4926 // Speed-up: Sizzle("body")
4927 // The body element only exists once, optimize finding it
4928 if ( query === "body" && context.body ) {
4929 return makeArray( [ context.body ], extra );
4931 // Speed-up: Sizzle("#ID")
4932 } else if ( match && match[3] ) {
4933 var elem = context.getElementById( match[3] );
4935 // Check parentNode to catch when Blackberry 4.6 returns
4936 // nodes that are no longer in the document #6963
4937 if ( elem && elem.parentNode ) {
4938 // Handle the case where IE and Opera return items
4939 // by name instead of ID
4940 if ( elem.id === match[3] ) {
4941 return makeArray( [ elem ], extra );
4945 return makeArray( [], extra );
4950 return makeArray( context.querySelectorAll(query), extra );
4951 } catch(qsaError) {}
4953 // qSA works strangely on Element-rooted queries
4954 // We can work around this by specifying an extra ID on the root
4955 // and working up from there (Thanks to Andrew Dupont for the technique)
4956 // IE 8 doesn't work on object elements
4957 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4958 var oldContext = context,
4959 old = context.getAttribute( "id" ),
4961 hasParent = context.parentNode,
4962 relativeHierarchySelector = /^\s*[+~]/.test( query );
4965 context.setAttribute( "id", nid );
4967 nid = nid.replace( /'/g, "\\$&" );
4969 if ( relativeHierarchySelector && hasParent ) {
4970 context = context.parentNode;
4974 if ( !relativeHierarchySelector || hasParent ) {
4975 return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
4978 } catch(pseudoError) {
4981 oldContext.removeAttribute( "id" );
4987 return oldSizzle(query, context, extra, seed);
4990 for ( var prop in oldSizzle ) {
4991 Sizzle[ prop ] = oldSizzle[ prop ];
4994 // release memory in IE
5000 var html = document.documentElement,
5001 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
5004 // Check to see if it's possible to do matchesSelector
5005 // on a disconnected node (IE 9 fails this)
5006 var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
5007 pseudoWorks = false;
5010 // This should fail with an exception
5011 // Gecko does not error, returns false instead
5012 matches.call( document.documentElement, "[test!='']:sizzle" );
5014 } catch( pseudoError ) {
5018 Sizzle.matchesSelector = function( node, expr ) {
5019 // Make sure that attribute selectors are quoted
5020 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
5022 if ( !Sizzle.isXML( node ) ) {
5024 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
5025 var ret = matches.call( node, expr );
5027 // IE 9's matchesSelector returns false on disconnected nodes
5028 if ( ret || !disconnectedMatch ||
5029 // As well, disconnected nodes are said to be in a document
5030 // fragment in IE 9, so check for that
5031 node.document && node.document.nodeType !== 11 ) {
5038 return Sizzle(expr, null, null, [node]).length > 0;
5044 var div = document.createElement("div");
5046 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
5048 // Opera can't find a second classname (in 9.6)
5049 // Also, make sure that getElementsByClassName actually exists
5050 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
5054 // Safari caches class attributes, doesn't catch changes (in 3.2)
5055 div.lastChild.className = "e";
5057 if ( div.getElementsByClassName("e").length === 1 ) {
5061 Expr.order.splice(1, 0, "CLASS");
5062 Expr.find.CLASS = function( match, context, isXML ) {
5063 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
5064 return context.getElementsByClassName(match[1]);
5068 // release memory in IE
5072 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5073 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5074 var elem = checkSet[i];
5082 if ( elem.sizcache === doneName ) {
5083 match = checkSet[elem.sizset];
5087 if ( elem.nodeType === 1 && !isXML ){
5088 elem.sizcache = doneName;
5092 if ( elem.nodeName.toLowerCase() === cur ) {
5100 checkSet[i] = match;
5105 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5106 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5107 var elem = checkSet[i];
5115 if ( elem.sizcache === doneName ) {
5116 match = checkSet[elem.sizset];
5120 if ( elem.nodeType === 1 ) {
5122 elem.sizcache = doneName;
5126 if ( typeof cur !== "string" ) {
5127 if ( elem === cur ) {
5132 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
5141 checkSet[i] = match;
5146 if ( document.documentElement.contains ) {
5147 Sizzle.contains = function( a, b ) {
5148 return a !== b && (a.contains ? a.contains(b) : true);
5151 } else if ( document.documentElement.compareDocumentPosition ) {
5152 Sizzle.contains = function( a, b ) {
5153 return !!(a.compareDocumentPosition(b) & 16);
5157 Sizzle.contains = function() {
5162 Sizzle.isXML = function( elem ) {
5163 // documentElement is verified for cases where it doesn't yet exist
5164 // (such as loading iframes in IE - #4833)
5165 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
5167 return documentElement ? documentElement.nodeName !== "HTML" : false;
5170 var posProcess = function( selector, context ) {
5174 root = context.nodeType ? [context] : context;
5176 // Position selectors must be done after the filter
5177 // And so must :not(positional) so we move all PSEUDOs to the end
5178 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
5180 selector = selector.replace( Expr.match.PSEUDO, "" );
5183 selector = Expr.relative[selector] ? selector + "*" : selector;
5185 for ( var i = 0, l = root.length; i < l; i++ ) {
5186 Sizzle( selector, root[i], tmpSet );
5189 return Sizzle.filter( later, tmpSet );
5193 jQuery.find = Sizzle;
5194 jQuery.expr = Sizzle.selectors;
5195 jQuery.expr[":"] = jQuery.expr.filters;
5196 jQuery.unique = Sizzle.uniqueSort;
5197 jQuery.text = Sizzle.getText;
5198 jQuery.isXMLDoc = Sizzle.isXML;
5199 jQuery.contains = Sizzle.contains;
5205 var runtil = /Until$/,
5206 rparentsprev = /^(?:parents|prevUntil|prevAll)/,
5207 // Note: This RegExp should be improved, or likely pulled from Sizzle
5208 rmultiselector = /,/,
5209 isSimple = /^.[^:#\[\.,]*$/,
5210 slice = Array.prototype.slice,
5211 POS = jQuery.expr.match.POS,
5212 // methods guaranteed to produce a unique set when starting from a unique set
5213 guaranteedUnique = {
5221 find: function( selector ) {
5225 if ( typeof selector !== "string" ) {
5226 return jQuery( selector ).filter(function() {
5227 for ( i = 0, l = self.length; i < l; i++ ) {
5228 if ( jQuery.contains( self[ i ], this ) ) {
5235 var ret = this.pushStack( "", "find", selector ),
5238 for ( i = 0, l = this.length; i < l; i++ ) {
5239 length = ret.length;
5240 jQuery.find( selector, this[i], ret );
5243 // Make sure that the results are unique
5244 for ( n = length; n < ret.length; n++ ) {
5245 for ( r = 0; r < length; r++ ) {
5246 if ( ret[r] === ret[n] ) {
5258 has: function( target ) {
5259 var targets = jQuery( target );
5260 return this.filter(function() {
5261 for ( var i = 0, l = targets.length; i < l; i++ ) {
5262 if ( jQuery.contains( this, targets[i] ) ) {
5269 not: function( selector ) {
5270 return this.pushStack( winnow(this, selector, false), "not", selector);
5273 filter: function( selector ) {
5274 return this.pushStack( winnow(this, selector, true), "filter", selector );
5277 is: function( selector ) {
5278 return !!selector && ( typeof selector === "string" ?
5279 jQuery.filter( selector, this ).length > 0 :
5280 this.filter( selector ).length > 0 );
5283 closest: function( selectors, context ) {
5284 var ret = [], i, l, cur = this[0];
5287 if ( jQuery.isArray( selectors ) ) {
5288 var match, selector,
5292 if ( cur && selectors.length ) {
5293 for ( i = 0, l = selectors.length; i < l; i++ ) {
5294 selector = selectors[i];
5296 if ( !matches[ selector ] ) {
5297 matches[ selector ] = POS.test( selector ) ?
5298 jQuery( selector, context || this.context ) :
5303 while ( cur && cur.ownerDocument && cur !== context ) {
5304 for ( selector in matches ) {
5305 match = matches[ selector ];
5307 if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
5308 ret.push({ selector: selector, elem: cur, level: level });
5312 cur = cur.parentNode;
5321 var pos = POS.test( selectors ) || typeof selectors !== "string" ?
5322 jQuery( selectors, context || this.context ) :
5325 for ( i = 0, l = this.length; i < l; i++ ) {
5329 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5334 cur = cur.parentNode;
5335 if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
5342 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
5344 return this.pushStack( ret, "closest", selectors );
5347 // Determine the position of an element within
5348 // the matched set of elements
5349 index: function( elem ) {
5351 // No argument, return index in parent
5353 return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
5356 // index in selector
5357 if ( typeof elem === "string" ) {
5358 return jQuery.inArray( this[0], jQuery( elem ) );
5361 // Locate the position of the desired element
5362 return jQuery.inArray(
5363 // If it receives a jQuery object, the first element is used
5364 elem.jquery ? elem[0] : elem, this );
5367 add: function( selector, context ) {
5368 var set = typeof selector === "string" ?
5369 jQuery( selector, context ) :
5370 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5371 all = jQuery.merge( this.get(), set );
5373 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
5375 jQuery.unique( all ) );
5378 andSelf: function() {
5379 return this.add( this.prevObject );
5383 // A painfully simple check to see if an element is disconnected
5384 // from a document (should be improved, where feasible).
5385 function isDisconnected( node ) {
5386 return !node || !node.parentNode || node.parentNode.nodeType === 11;
5390 parent: function( elem ) {
5391 var parent = elem.parentNode;
5392 return parent && parent.nodeType !== 11 ? parent : null;
5394 parents: function( elem ) {
5395 return jQuery.dir( elem, "parentNode" );
5397 parentsUntil: function( elem, i, until ) {
5398 return jQuery.dir( elem, "parentNode", until );
5400 next: function( elem ) {
5401 return jQuery.nth( elem, 2, "nextSibling" );
5403 prev: function( elem ) {
5404 return jQuery.nth( elem, 2, "previousSibling" );
5406 nextAll: function( elem ) {
5407 return jQuery.dir( elem, "nextSibling" );
5409 prevAll: function( elem ) {
5410 return jQuery.dir( elem, "previousSibling" );
5412 nextUntil: function( elem, i, until ) {
5413 return jQuery.dir( elem, "nextSibling", until );
5415 prevUntil: function( elem, i, until ) {
5416 return jQuery.dir( elem, "previousSibling", until );
5418 siblings: function( elem ) {
5419 return jQuery.sibling( elem.parentNode.firstChild, elem );
5421 children: function( elem ) {
5422 return jQuery.sibling( elem.firstChild );
5424 contents: function( elem ) {
5425 return jQuery.nodeName( elem, "iframe" ) ?
5426 elem.contentDocument || elem.contentWindow.document :
5427 jQuery.makeArray( elem.childNodes );
5429 }, function( name, fn ) {
5430 jQuery.fn[ name ] = function( until, selector ) {
5431 var ret = jQuery.map( this, fn, until ),
5432 // The variable 'args' was introduced in
5433 // https://github.com/jquery/jquery/commit/52a0238
5434 // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
5435 // http://code.google.com/p/v8/issues/detail?id=1050
5436 args = slice.call(arguments);
5438 if ( !runtil.test( name ) ) {
5442 if ( selector && typeof selector === "string" ) {
5443 ret = jQuery.filter( selector, ret );
5446 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5448 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
5449 ret = ret.reverse();
5452 return this.pushStack( ret, name, args.join(",") );
5457 filter: function( expr, elems, not ) {
5459 expr = ":not(" + expr + ")";
5462 return elems.length === 1 ?
5463 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5464 jQuery.find.matches(expr, elems);
5467 dir: function( elem, dir, until ) {
5471 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5472 if ( cur.nodeType === 1 ) {
5473 matched.push( cur );
5480 nth: function( cur, result, dir, elem ) {
5481 result = result || 1;
5484 for ( ; cur; cur = cur[dir] ) {
5485 if ( cur.nodeType === 1 && ++num === result ) {
5493 sibling: function( n, elem ) {
5496 for ( ; n; n = n.nextSibling ) {
5497 if ( n.nodeType === 1 && n !== elem ) {
5506 // Implement the identical functionality for filter and not
5507 function winnow( elements, qualifier, keep ) {
5509 // Can't pass null or undefined to indexOf in Firefox 4
5510 // Set to 0 to skip string check
5511 qualifier = qualifier || 0;
5513 if ( jQuery.isFunction( qualifier ) ) {
5514 return jQuery.grep(elements, function( elem, i ) {
5515 var retVal = !!qualifier.call( elem, i, elem );
5516 return retVal === keep;
5519 } else if ( qualifier.nodeType ) {
5520 return jQuery.grep(elements, function( elem, i ) {
5521 return (elem === qualifier) === keep;
5524 } else if ( typeof qualifier === "string" ) {
5525 var filtered = jQuery.grep(elements, function( elem ) {
5526 return elem.nodeType === 1;
5529 if ( isSimple.test( qualifier ) ) {
5530 return jQuery.filter(qualifier, filtered, !keep);
5532 qualifier = jQuery.filter( qualifier, filtered );
5536 return jQuery.grep(elements, function( elem, i ) {
5537 return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
5544 var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
5545 rleadingWhitespace = /^\s+/,
5546 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
5547 rtagName = /<([\w:]+)/,
5549 rhtml = /<|&#?\w+;/,
5550 rnocache = /<(?:script|object|embed|option|style)/i,
5551 // checked="checked" or checked
5552 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5553 rscriptType = /\/(java|ecma)script/i,
5554 rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
5556 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5557 legend: [ 1, "<fieldset>", "</fieldset>" ],
5558 thead: [ 1, "<table>", "</table>" ],
5559 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5560 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5561 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5562 area: [ 1, "<map>", "</map>" ],
5563 _default: [ 0, "", "" ]
5566 wrapMap.optgroup = wrapMap.option;
5567 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5568 wrapMap.th = wrapMap.td;
5570 // IE can't serialize <link> and <script> tags normally
5571 if ( !jQuery.support.htmlSerialize ) {
5572 wrapMap._default = [ 1, "div<div>", "</div>" ];
5576 text: function( text ) {
5577 if ( jQuery.isFunction(text) ) {
5578 return this.each(function(i) {
5579 var self = jQuery( this );
5581 self.text( text.call(this, i, self.text()) );
5585 if ( typeof text !== "object" && text !== undefined ) {
5586 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
5589 return jQuery.text( this );
5592 wrapAll: function( html ) {
5593 if ( jQuery.isFunction( html ) ) {
5594 return this.each(function(i) {
5595 jQuery(this).wrapAll( html.call(this, i) );
5600 // The elements to wrap the target around
5601 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5603 if ( this[0].parentNode ) {
5604 wrap.insertBefore( this[0] );
5607 wrap.map(function() {
5610 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5611 elem = elem.firstChild;
5621 wrapInner: function( html ) {
5622 if ( jQuery.isFunction( html ) ) {
5623 return this.each(function(i) {
5624 jQuery(this).wrapInner( html.call(this, i) );
5628 return this.each(function() {
5629 var self = jQuery( this ),
5630 contents = self.contents();
5632 if ( contents.length ) {
5633 contents.wrapAll( html );
5636 self.append( html );
5641 wrap: function( html ) {
5642 return this.each(function() {
5643 jQuery( this ).wrapAll( html );
5647 unwrap: function() {
5648 return this.parent().each(function() {
5649 if ( !jQuery.nodeName( this, "body" ) ) {
5650 jQuery( this ).replaceWith( this.childNodes );
5655 append: function() {
5656 return this.domManip(arguments, true, function( elem ) {
5657 if ( this.nodeType === 1 ) {
5658 this.appendChild( elem );
5663 prepend: function() {
5664 return this.domManip(arguments, true, function( elem ) {
5665 if ( this.nodeType === 1 ) {
5666 this.insertBefore( elem, this.firstChild );
5671 before: function() {
5672 if ( this[0] && this[0].parentNode ) {
5673 return this.domManip(arguments, false, function( elem ) {
5674 this.parentNode.insertBefore( elem, this );
5676 } else if ( arguments.length ) {
5677 var set = jQuery(arguments[0]);
5678 set.push.apply( set, this.toArray() );
5679 return this.pushStack( set, "before", arguments );
5684 if ( this[0] && this[0].parentNode ) {
5685 return this.domManip(arguments, false, function( elem ) {
5686 this.parentNode.insertBefore( elem, this.nextSibling );
5688 } else if ( arguments.length ) {
5689 var set = this.pushStack( this, "after", arguments );
5690 set.push.apply( set, jQuery(arguments[0]).toArray() );
5695 // keepData is for internal use only--do not document
5696 remove: function( selector, keepData ) {
5697 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
5698 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
5699 if ( !keepData && elem.nodeType === 1 ) {
5700 jQuery.cleanData( elem.getElementsByTagName("*") );
5701 jQuery.cleanData( [ elem ] );
5704 if ( elem.parentNode ) {
5705 elem.parentNode.removeChild( elem );
5714 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
5715 // Remove element nodes and prevent memory leaks
5716 if ( elem.nodeType === 1 ) {
5717 jQuery.cleanData( elem.getElementsByTagName("*") );
5720 // Remove any remaining nodes
5721 while ( elem.firstChild ) {
5722 elem.removeChild( elem.firstChild );
5729 clone: function( dataAndEvents, deepDataAndEvents ) {
5730 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5731 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5733 return this.map( function () {
5734 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5738 html: function( value ) {
5739 if ( value === undefined ) {
5740 return this[0] && this[0].nodeType === 1 ?
5741 this[0].innerHTML.replace(rinlinejQuery, "") :
5744 // See if we can take a shortcut and just use innerHTML
5745 } else if ( typeof value === "string" && !rnocache.test( value ) &&
5746 (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
5747 !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
5749 value = value.replace(rxhtmlTag, "<$1></$2>");
5752 for ( var i = 0, l = this.length; i < l; i++ ) {
5753 // Remove element nodes and prevent memory leaks
5754 if ( this[i].nodeType === 1 ) {
5755 jQuery.cleanData( this[i].getElementsByTagName("*") );
5756 this[i].innerHTML = value;
5760 // If using innerHTML throws an exception, use the fallback method
5762 this.empty().append( value );
5765 } else if ( jQuery.isFunction( value ) ) {
5766 this.each(function(i){
5767 var self = jQuery( this );
5769 self.html( value.call(this, i, self.html()) );
5773 this.empty().append( value );
5779 replaceWith: function( value ) {
5780 if ( this[0] && this[0].parentNode ) {
5781 // Make sure that the elements are removed from the DOM before they are inserted
5782 // this can help fix replacing a parent with child elements
5783 if ( jQuery.isFunction( value ) ) {
5784 return this.each(function(i) {
5785 var self = jQuery(this), old = self.html();
5786 self.replaceWith( value.call( this, i, old ) );
5790 if ( typeof value !== "string" ) {
5791 value = jQuery( value ).detach();
5794 return this.each(function() {
5795 var next = this.nextSibling,
5796 parent = this.parentNode;
5798 jQuery( this ).remove();
5801 jQuery(next).before( value );
5803 jQuery(parent).append( value );
5807 return this.length ?
5808 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
5813 detach: function( selector ) {
5814 return this.remove( selector, true );
5817 domManip: function( args, table, callback ) {
5818 var results, first, fragment, parent,
5822 // We can't cloneNode fragments that contain checked, in WebKit
5823 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
5824 return this.each(function() {
5825 jQuery(this).domManip( args, table, callback, true );
5829 if ( jQuery.isFunction(value) ) {
5830 return this.each(function(i) {
5831 var self = jQuery(this);
5832 args[0] = value.call(this, i, table ? self.html() : undefined);
5833 self.domManip( args, table, callback );
5838 parent = value && value.parentNode;
5840 // If we're in a fragment, just use that instead of building a new one
5841 if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
5842 results = { fragment: parent };
5845 results = jQuery.buildFragment( args, this, scripts );
5848 fragment = results.fragment;
5850 if ( fragment.childNodes.length === 1 ) {
5851 first = fragment = fragment.firstChild;
5853 first = fragment.firstChild;
5857 table = table && jQuery.nodeName( first, "tr" );
5859 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
5862 root(this[i], first) :
5864 // Make sure that we do not leak memory by inadvertently discarding
5865 // the original fragment (which might have attached data) instead of
5866 // using it; in addition, use the original fragment object for the last
5867 // item instead of first because it can end up being emptied incorrectly
5868 // in certain situations (Bug #8070).
5869 // Fragments from the fragment cache must always be cloned and never used
5871 results.cacheable || (l > 1 && i < lastIndex) ?
5872 jQuery.clone( fragment, true, true ) :
5878 if ( scripts.length ) {
5879 jQuery.each( scripts, evalScript );
5887 function root( elem, cur ) {
5888 return jQuery.nodeName(elem, "table") ?
5889 (elem.getElementsByTagName("tbody")[0] ||
5890 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
5894 function cloneCopyEvent( src, dest ) {
5896 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
5900 var internalKey = jQuery.expando,
5901 oldData = jQuery.data( src ),
5902 curData = jQuery.data( dest, oldData );
5904 // Switch to use the internal data object, if it exists, for the next
5905 // stage of data copying
5906 if ( (oldData = oldData[ internalKey ]) ) {
5907 var events = oldData.events;
5908 curData = curData[ internalKey ] = jQuery.extend({}, oldData);
5911 delete curData.handle;
5912 curData.events = {};
5914 for ( var type in events ) {
5915 for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
5916 jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
5923 function cloneFixAttributes( src, dest ) {
5926 // We do not need to do anything for non-Elements
5927 if ( dest.nodeType !== 1 ) {
5931 // clearAttributes removes the attributes, which we don't want,
5932 // but also removes the attachEvent events, which we *do* want
5933 if ( dest.clearAttributes ) {
5934 dest.clearAttributes();
5937 // mergeAttributes, in contrast, only merges back on the
5938 // original attributes, not the events
5939 if ( dest.mergeAttributes ) {
5940 dest.mergeAttributes( src );
5943 nodeName = dest.nodeName.toLowerCase();
5945 // IE6-8 fail to clone children inside object elements that use
5946 // the proprietary classid attribute value (rather than the type
5947 // attribute) to identify the type of content to display
5948 if ( nodeName === "object" ) {
5949 dest.outerHTML = src.outerHTML;
5951 } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
5952 // IE6-8 fails to persist the checked state of a cloned checkbox
5953 // or radio button. Worse, IE6-7 fail to give the cloned element
5954 // a checked appearance if the defaultChecked value isn't also set
5955 if ( src.checked ) {
5956 dest.defaultChecked = dest.checked = src.checked;
5959 // IE6-7 get confused and end up setting the value of a cloned
5960 // checkbox/radio button to an empty string instead of "on"
5961 if ( dest.value !== src.value ) {
5962 dest.value = src.value;
5965 // IE6-8 fails to return the selected option to the default selected
5966 // state when cloning options
5967 } else if ( nodeName === "option" ) {
5968 dest.selected = src.defaultSelected;
5970 // IE6-8 fails to set the defaultValue to the correct value when
5971 // cloning other types of input fields
5972 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5973 dest.defaultValue = src.defaultValue;
5976 // Event data gets referenced instead of copied if the expando
5978 dest.removeAttribute( jQuery.expando );
5981 jQuery.buildFragment = function( args, nodes, scripts ) {
5982 var fragment, cacheable, cacheresults, doc;
5984 // nodes may contain either an explicit document object,
5985 // a jQuery collection or context object.
5986 // If nodes[0] contains a valid object to assign to doc
5987 if ( nodes && nodes[0] ) {
5988 doc = nodes[0].ownerDocument || nodes[0];
5991 // Ensure that an attr object doesn't incorrectly stand in as a document object
5992 // Chrome and Firefox seem to allow this to occur and will throw exception
5994 if ( !doc.createDocumentFragment ) {
5998 // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
5999 // Cloning options loses the selected state, so don't cache them
6000 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
6001 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
6002 if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
6003 args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
6007 cacheresults = jQuery.fragments[ args[0] ];
6008 if ( cacheresults && cacheresults !== 1 ) {
6009 fragment = cacheresults;
6014 fragment = doc.createDocumentFragment();
6015 jQuery.clean( args, doc, fragment, scripts );
6019 jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
6022 return { fragment: fragment, cacheable: cacheable };
6025 jQuery.fragments = {};
6029 prependTo: "prepend",
6030 insertBefore: "before",
6031 insertAfter: "after",
6032 replaceAll: "replaceWith"
6033 }, function( name, original ) {
6034 jQuery.fn[ name ] = function( selector ) {
6036 insert = jQuery( selector ),
6037 parent = this.length === 1 && this[0].parentNode;
6039 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
6040 insert[ original ]( this[0] );
6044 for ( var i = 0, l = insert.length; i < l; i++ ) {
6045 var elems = (i > 0 ? this.clone(true) : this).get();
6046 jQuery( insert[i] )[ original ]( elems );
6047 ret = ret.concat( elems );
6050 return this.pushStack( ret, name, insert.selector );
6055 function getAll( elem ) {
6056 if ( "getElementsByTagName" in elem ) {
6057 return elem.getElementsByTagName( "*" );
6059 } else if ( "querySelectorAll" in elem ) {
6060 return elem.querySelectorAll( "*" );
6067 // Used in clean, fixes the defaultChecked property
6068 function fixDefaultChecked( elem ) {
6069 if ( elem.type === "checkbox" || elem.type === "radio" ) {
6070 elem.defaultChecked = elem.checked;
6073 // Finds all inputs and passes them to fixDefaultChecked
6074 function findInputs( elem ) {
6075 if ( jQuery.nodeName( elem, "input" ) ) {
6076 fixDefaultChecked( elem );
6077 } else if ( "getElementsByTagName" in elem ) {
6078 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6083 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6084 var clone = elem.cloneNode(true),
6089 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6090 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6091 // IE copies events bound via attachEvent when using cloneNode.
6092 // Calling detachEvent on the clone will also remove the events
6093 // from the original. In order to get around this, we use some
6094 // proprietary methods to clear the events. Thanks to MooTools
6095 // guys for this hotness.
6097 cloneFixAttributes( elem, clone );
6099 // Using Sizzle here is crazy slow, so we use getElementsByTagName
6101 srcElements = getAll( elem );
6102 destElements = getAll( clone );
6104 // Weird iteration because IE will replace the length property
6105 // with an element if you are cloning the body and one of the
6106 // elements on the page has a name or id of "length"
6107 for ( i = 0; srcElements[i]; ++i ) {
6108 // Ensure that the destination node is not null; Fixes #9587
6109 if ( destElements[i] ) {
6110 cloneFixAttributes( srcElements[i], destElements[i] );
6115 // Copy the events from the original to the clone
6116 if ( dataAndEvents ) {
6117 cloneCopyEvent( elem, clone );
6119 if ( deepDataAndEvents ) {
6120 srcElements = getAll( elem );
6121 destElements = getAll( clone );
6123 for ( i = 0; srcElements[i]; ++i ) {
6124 cloneCopyEvent( srcElements[i], destElements[i] );
6129 srcElements = destElements = null;
6131 // Return the cloned set
6135 clean: function( elems, context, fragment, scripts ) {
6136 var checkScriptType;
6138 context = context || document;
6140 // !context.createElement fails in IE with an error but returns typeof 'object'
6141 if ( typeof context.createElement === "undefined" ) {
6142 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
6147 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6148 if ( typeof elem === "number" ) {
6156 // Convert html string into DOM nodes
6157 if ( typeof elem === "string" ) {
6158 if ( !rhtml.test( elem ) ) {
6159 elem = context.createTextNode( elem );
6161 // Fix "XHTML"-style tags in all browsers
6162 elem = elem.replace(rxhtmlTag, "<$1></$2>");
6164 // Trim whitespace, otherwise indexOf won't work as expected
6165 var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
6166 wrap = wrapMap[ tag ] || wrapMap._default,
6168 div = context.createElement("div");
6170 // Go to html and back, then peel off extra wrappers
6171 div.innerHTML = wrap[1] + elem + wrap[2];
6173 // Move to the right depth
6175 div = div.lastChild;
6178 // Remove IE's autoinserted <tbody> from table fragments
6179 if ( !jQuery.support.tbody ) {
6181 // String was a <table>, *may* have spurious <tbody>
6182 var hasBody = rtbody.test(elem),
6183 tbody = tag === "table" && !hasBody ?
6184 div.firstChild && div.firstChild.childNodes :
6186 // String was a bare <thead> or <tfoot>
6187 wrap[1] === "<table>" && !hasBody ?
6191 for ( j = tbody.length - 1; j >= 0 ; --j ) {
6192 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
6193 tbody[ j ].parentNode.removeChild( tbody[ j ] );
6198 // IE completely kills leading whitespace when innerHTML is used
6199 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6200 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
6203 elem = div.childNodes;
6207 // Resets defaultChecked for any radios and checkboxes
6208 // about to be appended to the DOM in IE 6/7 (#8060)
6210 if ( !jQuery.support.appendChecked ) {
6211 if ( elem[0] && typeof (len = elem.length) === "number" ) {
6212 for ( j = 0; j < len; j++ ) {
6213 findInputs( elem[j] );
6220 if ( elem.nodeType ) {
6223 ret = jQuery.merge( ret, elem );
6228 checkScriptType = function( elem ) {
6229 return !elem.type || rscriptType.test( elem.type );
6231 for ( i = 0; ret[i]; i++ ) {
6232 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
6233 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
6236 if ( ret[i].nodeType === 1 ) {
6237 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
6239 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
6241 fragment.appendChild( ret[i] );
6249 cleanData: function( elems ) {
6250 var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
6251 deleteExpando = jQuery.support.deleteExpando;
6253 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6254 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
6258 id = elem[ jQuery.expando ];
6261 data = cache[ id ] && cache[ id ][ internalKey ];
6263 if ( data && data.events ) {
6264 for ( var type in data.events ) {
6265 if ( special[ type ] ) {
6266 jQuery.event.remove( elem, type );
6268 // This is a shortcut to avoid jQuery.event.remove's overhead
6270 jQuery.removeEvent( elem, type, data.handle );
6274 // Null the DOM reference to avoid IE6/7/8 leak (#7054)
6275 if ( data.handle ) {
6276 data.handle.elem = null;
6280 if ( deleteExpando ) {
6281 delete elem[ jQuery.expando ];
6283 } else if ( elem.removeAttribute ) {
6284 elem.removeAttribute( jQuery.expando );
6293 function evalScript( i, elem ) {
6301 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
6304 if ( elem.parentNode ) {
6305 elem.parentNode.removeChild( elem );
6312 var ralpha = /alpha\([^)]*\)/i,
6313 ropacity = /opacity=([^)]*)/,
6314 // fixed for IE9, see #8346
6315 rupper = /([A-Z]|^ms)/g,
6316 rnumpx = /^-?\d+(?:px)?$/i,
6318 rrelNum = /^([\-+])=([\-+.\de]+)/,
6320 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6321 cssWidth = [ "Left", "Right" ],
6322 cssHeight = [ "Top", "Bottom" ],
6328 jQuery.fn.css = function( name, value ) {
6329 // Setting 'undefined' is a no-op
6330 if ( arguments.length === 2 && value === undefined ) {
6334 return jQuery.access( this, name, value, true, function( elem, name, value ) {
6335 return value !== undefined ?
6336 jQuery.style( elem, name, value ) :
6337 jQuery.css( elem, name );
6342 // Add in style property hooks for overriding the default
6343 // behavior of getting and setting a style property
6346 get: function( elem, computed ) {
6348 // We should always get a number back from opacity
6349 var ret = curCSS( elem, "opacity", "opacity" );
6350 return ret === "" ? "1" : ret;
6353 return elem.style.opacity;
6359 // Exclude the following css properties to add px
6361 "fillOpacity": true,
6371 // Add in properties whose names you wish to fix before
6372 // setting or getting the value
6374 // normalize float css property
6375 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6378 // Get and set the style property on a DOM Node
6379 style: function( elem, name, value, extra ) {
6380 // Don't set styles on text and comment nodes
6381 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6385 // Make sure that we're working with the right name
6386 var ret, type, origName = jQuery.camelCase( name ),
6387 style = elem.style, hooks = jQuery.cssHooks[ origName ];
6389 name = jQuery.cssProps[ origName ] || origName;
6391 // Check if we're setting a value
6392 if ( value !== undefined ) {
6393 type = typeof value;
6395 // convert relative number strings (+= or -=) to relative numbers. #7345
6396 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6397 value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
6402 // Make sure that NaN and null values aren't set. See: #7116
6403 if ( value == null || type === "number" && isNaN( value ) ) {
6407 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6408 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6412 // If a hook was provided, use that value, otherwise just set the specified value
6413 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
6414 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6417 style[ name ] = value;
6422 // If a hook was provided get the non-computed value from there
6423 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6427 // Otherwise just get the value from the style object
6428 return style[ name ];
6432 css: function( elem, name, extra ) {
6435 // Make sure that we're working with the right name
6436 name = jQuery.camelCase( name );
6437 hooks = jQuery.cssHooks[ name ];
6438 name = jQuery.cssProps[ name ] || name;
6440 // cssFloat needs a special treatment
6441 if ( name === "cssFloat" ) {
6445 // If a hook was provided get the computed value from there
6446 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
6449 // Otherwise, if a way to get the computed value exists, use that
6450 } else if ( curCSS ) {
6451 return curCSS( elem, name );
6455 // A method for quickly swapping in/out CSS properties to get correct calculations
6456 swap: function( elem, options, callback ) {
6459 // Remember the old values, and insert the new ones
6460 for ( var name in options ) {
6461 old[ name ] = elem.style[ name ];
6462 elem.style[ name ] = options[ name ];
6465 callback.call( elem );
6467 // Revert the old values
6468 for ( name in options ) {
6469 elem.style[ name ] = old[ name ];
6474 // DEPRECATED, Use jQuery.css() instead
6475 jQuery.curCSS = jQuery.css;
6477 jQuery.each(["height", "width"], function( i, name ) {
6478 jQuery.cssHooks[ name ] = {
6479 get: function( elem, computed, extra ) {
6483 if ( elem.offsetWidth !== 0 ) {
6484 return getWH( elem, name, extra );
6486 jQuery.swap( elem, cssShow, function() {
6487 val = getWH( elem, name, extra );
6495 set: function( elem, value ) {
6496 if ( rnumpx.test( value ) ) {
6497 // ignore negative width and height values #1599
6498 value = parseFloat( value );
6501 return value + "px";
6511 if ( !jQuery.support.opacity ) {
6512 jQuery.cssHooks.opacity = {
6513 get: function( elem, computed ) {
6514 // IE uses filters for opacity
6515 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
6516 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
6517 computed ? "1" : "";
6520 set: function( elem, value ) {
6521 var style = elem.style,
6522 currentStyle = elem.currentStyle,
6523 opacity = jQuery.isNaN( value ) ? "" : "alpha(opacity=" + value * 100 + ")",
6524 filter = currentStyle && currentStyle.filter || style.filter || "";
6526 // IE has trouble with opacity if it does not have layout
6527 // Force it by setting the zoom level
6530 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
6531 if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
6533 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
6534 // if "filter:" is present at all, clearType is disabled, we want to avoid this
6535 // style.removeAttribute is IE Only, but so apparently is this code path...
6536 style.removeAttribute( "filter" );
6538 // if there there is no filter style applied in a css rule, we are done
6539 if ( currentStyle && !currentStyle.filter ) {
6544 // otherwise, set new filter values
6545 style.filter = ralpha.test( filter ) ?
6546 filter.replace( ralpha, opacity ) :
6547 filter + " " + opacity;
6553 // This hook cannot be added until DOM ready because the support test
6554 // for it is not run until after DOM ready
6555 if ( !jQuery.support.reliableMarginRight ) {
6556 jQuery.cssHooks.marginRight = {
6557 get: function( elem, computed ) {
6558 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6559 // Work around by temporarily setting element display to inline-block
6561 jQuery.swap( elem, { "display": "inline-block" }, function() {
6563 ret = curCSS( elem, "margin-right", "marginRight" );
6565 ret = elem.style.marginRight;
6574 if ( document.defaultView && document.defaultView.getComputedStyle ) {
6575 getComputedStyle = function( elem, name ) {
6576 var ret, defaultView, computedStyle;
6578 name = name.replace( rupper, "-$1" ).toLowerCase();
6580 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
6584 if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
6585 ret = computedStyle.getPropertyValue( name );
6586 if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
6587 ret = jQuery.style( elem, name );
6595 if ( document.documentElement.currentStyle ) {
6596 currentStyle = function( elem, name ) {
6598 ret = elem.currentStyle && elem.currentStyle[ name ],
6599 rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
6602 // From the awesome hack by Dean Edwards
6603 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6605 // If we're not dealing with a regular pixel number
6606 // but a number that has a weird ending, we need to convert it to pixels
6607 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
6608 // Remember the original values
6611 // Put in the new values to get a computed value out
6613 elem.runtimeStyle.left = elem.currentStyle.left;
6615 style.left = name === "fontSize" ? "1em" : (ret || 0);
6616 ret = style.pixelLeft + "px";
6618 // Revert the changed values
6621 elem.runtimeStyle.left = rsLeft;
6625 return ret === "" ? "auto" : ret;
6629 curCSS = getComputedStyle || currentStyle;
6631 function getWH( elem, name, extra ) {
6633 // Start with offset property
6634 var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6635 which = name === "width" ? cssWidth : cssHeight;
6638 if ( extra !== "border" ) {
6639 jQuery.each( which, function() {
6641 val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
6643 if ( extra === "margin" ) {
6644 val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
6646 val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
6654 // Fall back to computed then uncomputed css if necessary
6655 val = curCSS( elem, name, name );
6656 if ( val < 0 || val == null ) {
6657 val = elem.style[ name ] || 0;
6659 // Normalize "", auto, and prepare for extra
6660 val = parseFloat( val ) || 0;
6662 // Add padding, border, margin
6664 jQuery.each( which, function() {
6665 val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
6666 if ( extra !== "padding" ) {
6667 val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
6669 if ( extra === "margin" ) {
6670 val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
6678 if ( jQuery.expr && jQuery.expr.filters ) {
6679 jQuery.expr.filters.hidden = function( elem ) {
6680 var width = elem.offsetWidth,
6681 height = elem.offsetHeight;
6683 return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
6686 jQuery.expr.filters.visible = function( elem ) {
6687 return !jQuery.expr.filters.hidden( elem );
6698 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
6699 rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
6700 // #7653, #8125, #8152: local protocol detection
6701 rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
6702 rnoContent = /^(?:GET|HEAD)$/,
6703 rprotocol = /^\/\//,
6705 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
6706 rselectTextarea = /^(?:select|textarea)/i,
6707 rspacesAjax = /\s+/,
6708 rts = /([?&])_=[^&]*/,
6709 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
6711 // Keep a copy of the old load method
6712 _load = jQuery.fn.load,
6715 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
6716 * 2) These are called:
6717 * - BEFORE asking for a transport
6718 * - AFTER param serialization (s.data is a string if s.processData is true)
6719 * 3) key is the dataType
6720 * 4) the catchall symbol "*" can be used
6721 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
6725 /* Transports bindings
6726 * 1) key is the dataType
6727 * 2) the catchall symbol "*" can be used
6728 * 3) selection will start with transport dataType and THEN go to "*" if needed
6732 // Document location
6735 // Document location segments
6738 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
6739 allTypes = ["*/"] + ["*"];
6741 // #8138, IE may throw an exception when accessing
6742 // a field from window.location if document.domain has been set
6744 ajaxLocation = location.href;
6746 // Use the href attribute of an A element
6747 // since IE will modify it given document.location
6748 ajaxLocation = document.createElement( "a" );
6749 ajaxLocation.href = "";
6750 ajaxLocation = ajaxLocation.href;
6753 // Segment location into parts
6754 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
6756 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
6757 function addToPrefiltersOrTransports( structure ) {
6759 // dataTypeExpression is optional and defaults to "*"
6760 return function( dataTypeExpression, func ) {
6762 if ( typeof dataTypeExpression !== "string" ) {
6763 func = dataTypeExpression;
6764 dataTypeExpression = "*";
6767 if ( jQuery.isFunction( func ) ) {
6768 var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
6770 length = dataTypes.length,
6775 // For each dataType in the dataTypeExpression
6776 for(; i < length; i++ ) {
6777 dataType = dataTypes[ i ];
6778 // We control if we're asked to add before
6779 // any existing element
6780 placeBefore = /^\+/.test( dataType );
6781 if ( placeBefore ) {
6782 dataType = dataType.substr( 1 ) || "*";
6784 list = structure[ dataType ] = structure[ dataType ] || [];
6785 // then we add to the structure accordingly
6786 list[ placeBefore ? "unshift" : "push" ]( func );
6792 // Base inspection function for prefilters and transports
6793 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
6794 dataType /* internal */, inspected /* internal */ ) {
6796 dataType = dataType || options.dataTypes[ 0 ];
6797 inspected = inspected || {};
6799 inspected[ dataType ] = true;
6801 var list = structure[ dataType ],
6803 length = list ? list.length : 0,
6804 executeOnly = ( structure === prefilters ),
6807 for(; i < length && ( executeOnly || !selection ); i++ ) {
6808 selection = list[ i ]( options, originalOptions, jqXHR );
6809 // If we got redirected to another dataType
6810 // we try there if executing only and not done already
6811 if ( typeof selection === "string" ) {
6812 if ( !executeOnly || inspected[ selection ] ) {
6813 selection = undefined;
6815 options.dataTypes.unshift( selection );
6816 selection = inspectPrefiltersOrTransports(
6817 structure, options, originalOptions, jqXHR, selection, inspected );
6821 // If we're only executing or nothing was selected
6822 // we try the catchall dataType if not done already
6823 if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
6824 selection = inspectPrefiltersOrTransports(
6825 structure, options, originalOptions, jqXHR, "*", inspected );
6827 // unnecessary when only executing (prefilters)
6828 // but it'll be ignored by the caller in that case
6832 // A special extend for ajax options
6833 // that takes "flat" options (not to be deep extended)
6835 function ajaxExtend( target, src ) {
6837 flatOptions = jQuery.ajaxSettings.flatOptions || {};
6839 if ( src[ key ] !== undefined ) {
6840 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
6844 jQuery.extend( true, target, deep );
6849 load: function( url, params, callback ) {
6850 if ( typeof url !== "string" && _load ) {
6851 return _load.apply( this, arguments );
6853 // Don't do a request if no elements are being requested
6854 } else if ( !this.length ) {
6858 var off = url.indexOf( " " );
6860 var selector = url.slice( off, url.length );
6861 url = url.slice( 0, off );
6864 // Default to a GET request
6867 // If the second parameter was provided
6869 // If it's a function
6870 if ( jQuery.isFunction( params ) ) {
6871 // We assume that it's the callback
6875 // Otherwise, build a param string
6876 } else if ( typeof params === "object" ) {
6877 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
6884 // Request the remote document
6890 // Complete callback (responseText is used internally)
6891 complete: function( jqXHR, status, responseText ) {
6892 // Store the response as specified by the jqXHR object
6893 responseText = jqXHR.responseText;
6894 // If successful, inject the HTML into all the matched elements
6895 if ( jqXHR.isResolved() ) {
6896 // #4825: Get the actual response in case
6897 // a dataFilter is present in ajaxSettings
6898 jqXHR.done(function( r ) {
6901 // See if a selector was specified
6902 self.html( selector ?
6903 // Create a dummy div to hold the results
6905 // inject the contents of the document in, removing the scripts
6906 // to avoid any 'Permission Denied' errors in IE
6907 .append(responseText.replace(rscript, ""))
6909 // Locate the specified elements
6912 // If not, just inject the full result
6917 self.each( callback, [ responseText, status, jqXHR ] );
6925 serialize: function() {
6926 return jQuery.param( this.serializeArray() );
6929 serializeArray: function() {
6930 return this.map(function(){
6931 return this.elements ? jQuery.makeArray( this.elements ) : this;
6934 return this.name && !this.disabled &&
6935 ( this.checked || rselectTextarea.test( this.nodeName ) ||
6936 rinput.test( this.type ) );
6938 .map(function( i, elem ){
6939 var val = jQuery( this ).val();
6941 return val == null ?
6943 jQuery.isArray( val ) ?
6944 jQuery.map( val, function( val, i ){
6945 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
6947 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
6952 // Attach a bunch of functions for handling common AJAX events
6953 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
6954 jQuery.fn[ o ] = function( f ){
6955 return this.bind( o, f );
6959 jQuery.each( [ "get", "post" ], function( i, method ) {
6960 jQuery[ method ] = function( url, data, callback, type ) {
6961 // shift arguments if data argument was omitted
6962 if ( jQuery.isFunction( data ) ) {
6963 type = type || callback;
6968 return jQuery.ajax({
6980 getScript: function( url, callback ) {
6981 return jQuery.get( url, undefined, callback, "script" );
6984 getJSON: function( url, data, callback ) {
6985 return jQuery.get( url, data, callback, "json" );
6988 // Creates a full fledged settings object into target
6989 // with both ajaxSettings and settings fields.
6990 // If target is omitted, writes into ajaxSettings.
6991 ajaxSetup: function( target, settings ) {
6993 // Building a settings object
6994 ajaxExtend( target, jQuery.ajaxSettings );
6996 // Extending ajaxSettings
6998 target = jQuery.ajaxSettings;
7000 ajaxExtend( target, settings );
7006 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7009 contentType: "application/x-www-form-urlencoded",
7024 xml: "application/xml, text/xml",
7027 json: "application/json, text/javascript",
7039 text: "responseText"
7042 // List of data converters
7043 // 1) key format is "source_type destination_type" (a single space in-between)
7044 // 2) the catchall symbol "*" can be used for source_type
7047 // Convert anything to text
7048 "* text": window.String,
7050 // Text to html (true = no transformation)
7053 // Evaluate text as a json expression
7054 "text json": jQuery.parseJSON,
7056 // Parse text as xml
7057 "text xml": jQuery.parseXML
7060 // For options that shouldn't be deep extended:
7061 // you can add your own custom options here if
7062 // and when you create one that shouldn't be
7063 // deep extended (see ajaxExtend)
7070 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7071 ajaxTransport: addToPrefiltersOrTransports( transports ),
7074 ajax: function( url, options ) {
7076 // If url is an object, simulate pre-1.5 signature
7077 if ( typeof url === "object" ) {
7082 // Force options to be an object
7083 options = options || {};
7085 var // Create the final options object
7086 s = jQuery.ajaxSetup( {}, options ),
7087 // Callbacks context
7088 callbackContext = s.context || s,
7089 // Context for global events
7090 // It's the callbackContext if one was provided in the options
7091 // and if it's a DOM node or a jQuery collection
7092 globalEventContext = callbackContext !== s &&
7093 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
7094 jQuery( callbackContext ) : jQuery.event,
7096 deferred = jQuery.Deferred(),
7097 completeDeferred = jQuery._Deferred(),
7098 // Status-dependent callbacks
7099 statusCode = s.statusCode || {},
7102 // Headers (they are sent all at once)
7103 requestHeaders = {},
7104 requestHeadersNames = {},
7106 responseHeadersString,
7112 // Cross-domain detection vars
7116 // To know if global events are to be dispatched
7125 // Caches the header
7126 setRequestHeader: function( name, value ) {
7128 var lname = name.toLowerCase();
7129 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7130 requestHeaders[ name ] = value;
7136 getAllResponseHeaders: function() {
7137 return state === 2 ? responseHeadersString : null;
7140 // Builds headers hashtable if needed
7141 getResponseHeader: function( key ) {
7143 if ( state === 2 ) {
7144 if ( !responseHeaders ) {
7145 responseHeaders = {};
7146 while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7147 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7150 match = responseHeaders[ key.toLowerCase() ];
7152 return match === undefined ? null : match;
7155 // Overrides response content-type header
7156 overrideMimeType: function( type ) {
7163 // Cancel the request
7164 abort: function( statusText ) {
7165 statusText = statusText || "abort";
7167 transport.abort( statusText );
7169 done( 0, statusText );
7174 // Callback for when everything is done
7175 // It is defined here because jslint complains if it is declared
7176 // at the end of the function (which would be more logical and readable)
7177 function done( status, nativeStatusText, responses, headers ) {
7180 if ( state === 2 ) {
7184 // State is "done" now
7187 // Clear timeout if it exists
7188 if ( timeoutTimer ) {
7189 clearTimeout( timeoutTimer );
7192 // Dereference transport for early garbage collection
7193 // (no matter how long the jqXHR object will be used)
7194 transport = undefined;
7196 // Cache response headers
7197 responseHeadersString = headers || "";
7200 jqXHR.readyState = status > 0 ? 4 : 0;
7205 statusText = nativeStatusText,
7206 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
7210 // If successful, handle type chaining
7211 if ( status >= 200 && status < 300 || status === 304 ) {
7213 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7214 if ( s.ifModified ) {
7216 if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
7217 jQuery.lastModified[ ifModifiedKey ] = lastModified;
7219 if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
7220 jQuery.etag[ ifModifiedKey ] = etag;
7225 if ( status === 304 ) {
7227 statusText = "notmodified";
7234 success = ajaxConvert( s, response );
7235 statusText = "success";
7238 // We have a parsererror
7239 statusText = "parsererror";
7244 // We extract error from statusText
7245 // then normalize statusText and status for non-aborts
7247 if( !statusText || status ) {
7248 statusText = "error";
7255 // Set data for the fake xhr object
7256 jqXHR.status = status;
7257 jqXHR.statusText = "" + ( nativeStatusText || statusText );
7261 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
7263 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
7266 // Status-dependent callbacks
7267 jqXHR.statusCode( statusCode );
7268 statusCode = undefined;
7270 if ( fireGlobals ) {
7271 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
7272 [ jqXHR, s, isSuccess ? success : error ] );
7276 completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
7278 if ( fireGlobals ) {
7279 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
7280 // Handle the global AJAX counter
7281 if ( !( --jQuery.active ) ) {
7282 jQuery.event.trigger( "ajaxStop" );
7288 deferred.promise( jqXHR );
7289 jqXHR.success = jqXHR.done;
7290 jqXHR.error = jqXHR.fail;
7291 jqXHR.complete = completeDeferred.done;
7293 // Status-dependent callbacks
7294 jqXHR.statusCode = function( map ) {
7299 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
7302 tmp = map[ jqXHR.status ];
7303 jqXHR.then( tmp, tmp );
7309 // Remove hash character (#7531: and string promotion)
7310 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7311 // We also use the url parameter if available
7312 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7314 // Extract dataTypes list
7315 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
7317 // Determine if a cross-domain request is in order
7318 if ( s.crossDomain == null ) {
7319 parts = rurl.exec( s.url.toLowerCase() );
7320 s.crossDomain = !!( parts &&
7321 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
7322 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7323 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7327 // Convert data if not already a string
7328 if ( s.data && s.processData && typeof s.data !== "string" ) {
7329 s.data = jQuery.param( s.data, s.traditional );
7333 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7335 // If request was aborted inside a prefiler, stop there
7336 if ( state === 2 ) {
7340 // We can fire global events as of now if asked to
7341 fireGlobals = s.global;
7343 // Uppercase the type
7344 s.type = s.type.toUpperCase();
7346 // Determine if request has content
7347 s.hasContent = !rnoContent.test( s.type );
7349 // Watch for a new set of requests
7350 if ( fireGlobals && jQuery.active++ === 0 ) {
7351 jQuery.event.trigger( "ajaxStart" );
7354 // More options handling for requests with no content
7355 if ( !s.hasContent ) {
7357 // If data is available, append data to url
7359 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
7360 // #9682: remove data so that it's not used in an eventual retry
7364 // Get ifModifiedKey before adding the anti-cache parameter
7365 ifModifiedKey = s.url;
7367 // Add anti-cache in url if needed
7368 if ( s.cache === false ) {
7370 var ts = jQuery.now(),
7371 // try replacing _= if it is there
7372 ret = s.url.replace( rts, "$1_=" + ts );
7374 // if nothing was replaced, add timestamp to the end
7375 s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
7379 // Set the correct header, if data is being sent
7380 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7381 jqXHR.setRequestHeader( "Content-Type", s.contentType );
7384 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7385 if ( s.ifModified ) {
7386 ifModifiedKey = ifModifiedKey || s.url;
7387 if ( jQuery.lastModified[ ifModifiedKey ] ) {
7388 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
7390 if ( jQuery.etag[ ifModifiedKey ] ) {
7391 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
7395 // Set the Accepts header for the server, depending on the dataType
7396 jqXHR.setRequestHeader(
7398 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7399 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7403 // Check for headers option
7404 for ( i in s.headers ) {
7405 jqXHR.setRequestHeader( i, s.headers[ i ] );
7408 // Allow custom headers/mimetypes and early abort
7409 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7410 // Abort if not done already
7416 // Install callbacks on deferreds
7417 for ( i in { success: 1, error: 1, complete: 1 } ) {
7418 jqXHR[ i ]( s[ i ] );
7422 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7424 // If no transport, we auto-abort
7426 done( -1, "No Transport" );
7428 jqXHR.readyState = 1;
7429 // Send global event
7430 if ( fireGlobals ) {
7431 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7434 if ( s.async && s.timeout > 0 ) {
7435 timeoutTimer = setTimeout( function(){
7436 jqXHR.abort( "timeout" );
7442 transport.send( requestHeaders, done );
7444 // Propagate exception as error if not done
7447 // Simply rethrow otherwise
7457 // Serialize an array of form elements or a set of
7458 // key/values into a query string
7459 param: function( a, traditional ) {
7461 add = function( key, value ) {
7462 // If value is a function, invoke it and return its value
7463 value = jQuery.isFunction( value ) ? value() : value;
7464 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7467 // Set traditional to true for jQuery <= 1.3.2 behavior.
7468 if ( traditional === undefined ) {
7469 traditional = jQuery.ajaxSettings.traditional;
7472 // If an array was passed in, assume that it is an array of form elements.
7473 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7474 // Serialize the form elements
7475 jQuery.each( a, function() {
7476 add( this.name, this.value );
7480 // If traditional, encode the "old" way (the way 1.3.2 or older
7481 // did it), otherwise encode params recursively.
7482 for ( var prefix in a ) {
7483 buildParams( prefix, a[ prefix ], traditional, add );
7487 // Return the resulting serialization
7488 return s.join( "&" ).replace( r20, "+" );
7492 function buildParams( prefix, obj, traditional, add ) {
7493 if ( jQuery.isArray( obj ) ) {
7494 // Serialize array item.
7495 jQuery.each( obj, function( i, v ) {
7496 if ( traditional || rbracket.test( prefix ) ) {
7497 // Treat each array item as a scalar.
7501 // If array item is non-scalar (array or object), encode its
7502 // numeric index to resolve deserialization ambiguity issues.
7503 // Note that rack (as of 1.0.0) can't currently deserialize
7504 // nested arrays properly, and attempting to do so may cause
7505 // a server error. Possible fixes are to modify rack's
7506 // deserialization algorithm or to provide an option or flag
7507 // to force array serialization to be shallow.
7508 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
7512 } else if ( !traditional && obj != null && typeof obj === "object" ) {
7513 // Serialize object item.
7514 for ( var name in obj ) {
7515 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7519 // Serialize scalar item.
7524 // This is still on the jQuery object... for now
7525 // Want to move this to jQuery.ajax some day
7528 // Counter for holding the number of active queries
7531 // Last-Modified header cache for next request
7537 /* Handles responses to an ajax request:
7538 * - sets all responseXXX fields accordingly
7539 * - finds the right dataType (mediates between content-type and expected dataType)
7540 * - returns the corresponding response
7542 function ajaxHandleResponses( s, jqXHR, responses ) {
7544 var contents = s.contents,
7545 dataTypes = s.dataTypes,
7546 responseFields = s.responseFields,
7552 // Fill responseXXX fields
7553 for( type in responseFields ) {
7554 if ( type in responses ) {
7555 jqXHR[ responseFields[type] ] = responses[ type ];
7559 // Remove auto dataType and get content-type in the process
7560 while( dataTypes[ 0 ] === "*" ) {
7562 if ( ct === undefined ) {
7563 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
7567 // Check if we're dealing with a known content-type
7569 for ( type in contents ) {
7570 if ( contents[ type ] && contents[ type ].test( ct ) ) {
7571 dataTypes.unshift( type );
7577 // Check to see if we have a response for the expected dataType
7578 if ( dataTypes[ 0 ] in responses ) {
7579 finalDataType = dataTypes[ 0 ];
7581 // Try convertible dataTypes
7582 for ( type in responses ) {
7583 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
7584 finalDataType = type;
7587 if ( !firstDataType ) {
7588 firstDataType = type;
7591 // Or just use first one
7592 finalDataType = finalDataType || firstDataType;
7595 // If we found a dataType
7596 // We add the dataType to the list if needed
7597 // and return the corresponding response
7598 if ( finalDataType ) {
7599 if ( finalDataType !== dataTypes[ 0 ] ) {
7600 dataTypes.unshift( finalDataType );
7602 return responses[ finalDataType ];
7606 // Chain conversions given the request and the original response
7607 function ajaxConvert( s, response ) {
7609 // Apply the dataFilter if provided
7610 if ( s.dataFilter ) {
7611 response = s.dataFilter( response, s.dataType );
7614 var dataTypes = s.dataTypes,
7618 length = dataTypes.length,
7620 // Current and previous dataTypes
7621 current = dataTypes[ 0 ],
7623 // Conversion expression
7625 // Conversion function
7627 // Conversion functions (transitive conversion)
7631 // For each dataType in the chain
7632 for( i = 1; i < length; i++ ) {
7634 // Create converters map
7635 // with lowercased keys
7637 for( key in s.converters ) {
7638 if( typeof key === "string" ) {
7639 converters[ key.toLowerCase() ] = s.converters[ key ];
7644 // Get the dataTypes
7646 current = dataTypes[ i ];
7648 // If current is auto dataType, update it to prev
7649 if( current === "*" ) {
7651 // If no auto and dataTypes are actually different
7652 } else if ( prev !== "*" && prev !== current ) {
7654 // Get the converter
7655 conversion = prev + " " + current;
7656 conv = converters[ conversion ] || converters[ "* " + current ];
7658 // If there is no direct converter, search transitively
7661 for( conv1 in converters ) {
7662 tmp = conv1.split( " " );
7663 if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
7664 conv2 = converters[ tmp[1] + " " + current ];
7666 conv1 = converters[ conv1 ];
7667 if ( conv1 === true ) {
7669 } else if ( conv2 === true ) {
7677 // If we found no converter, dispatch an error
7678 if ( !( conv || conv2 ) ) {
7679 jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
7681 // If found converter is not an equivalence
7682 if ( conv !== true ) {
7683 // Convert with 1 or 2 converters accordingly
7684 response = conv ? conv( response ) : conv2( conv1(response) );
7694 var jsc = jQuery.now(),
7695 jsre = /(\=)\?(&|$)|\?\?/i;
7697 // Default jsonp settings
7700 jsonpCallback: function() {
7701 return jQuery.expando + "_" + ( jsc++ );
7705 // Detect, normalize options and install callbacks for jsonp requests
7706 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
7708 var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
7709 ( typeof s.data === "string" );
7711 if ( s.dataTypes[ 0 ] === "jsonp" ||
7712 s.jsonp !== false && ( jsre.test( s.url ) ||
7713 inspectData && jsre.test( s.data ) ) ) {
7715 var responseContainer,
7716 jsonpCallback = s.jsonpCallback =
7717 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
7718 previous = window[ jsonpCallback ],
7721 replace = "$1" + jsonpCallback + "$2";
7723 if ( s.jsonp !== false ) {
7724 url = url.replace( jsre, replace );
7725 if ( s.url === url ) {
7726 if ( inspectData ) {
7727 data = data.replace( jsre, replace );
7729 if ( s.data === data ) {
7730 // Add callback manually
7731 url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
7740 window[ jsonpCallback ] = function( response ) {
7741 responseContainer = [ response ];
7744 // Clean-up function
7745 jqXHR.always(function() {
7746 // Set callback back to previous value
7747 window[ jsonpCallback ] = previous;
7748 // Call if it was a function and we have a response
7749 if ( responseContainer && jQuery.isFunction( previous ) ) {
7750 window[ jsonpCallback ]( responseContainer[ 0 ] );
7754 // Use data converter to retrieve json after script execution
7755 s.converters["script json"] = function() {
7756 if ( !responseContainer ) {
7757 jQuery.error( jsonpCallback + " was not called" );
7759 return responseContainer[ 0 ];
7762 // force json dataType
7763 s.dataTypes[ 0 ] = "json";
7765 // Delegate to script
7773 // Install script dataType
7776 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
7779 script: /javascript|ecmascript/
7782 "text script": function( text ) {
7783 jQuery.globalEval( text );
7789 // Handle cache's special case and global
7790 jQuery.ajaxPrefilter( "script", function( s ) {
7791 if ( s.cache === undefined ) {
7794 if ( s.crossDomain ) {
7800 // Bind script tag hack transport
7801 jQuery.ajaxTransport( "script", function(s) {
7803 // This transport only deals with cross domain requests
7804 if ( s.crossDomain ) {
7807 head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
7811 send: function( _, callback ) {
7813 script = document.createElement( "script" );
7815 script.async = "async";
7817 if ( s.scriptCharset ) {
7818 script.charset = s.scriptCharset;
7823 // Attach handlers for all browsers
7824 script.onload = script.onreadystatechange = function( _, isAbort ) {
7826 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
7828 // Handle memory leak in IE
7829 script.onload = script.onreadystatechange = null;
7831 // Remove the script
7832 if ( head && script.parentNode ) {
7833 head.removeChild( script );
7836 // Dereference the script
7839 // Callback if not abort
7841 callback( 200, "success" );
7845 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
7846 // This arises when a base node is used (#2709 and #4378).
7847 head.insertBefore( script, head.firstChild );
7852 script.onload( 0, 1 );
7862 var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
7863 xhrOnUnloadAbort = window.ActiveXObject ? function() {
7864 // Abort all pending requests
7865 for ( var key in xhrCallbacks ) {
7866 xhrCallbacks[ key ]( 0, 1 );
7872 // Functions to create xhrs
7873 function createStandardXHR() {
7875 return new window.XMLHttpRequest();
7879 function createActiveXHR() {
7881 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
7885 // Create the request object
7886 // (This is still attached to ajaxSettings for backward compatibility)
7887 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
7888 /* Microsoft failed to properly
7889 * implement the XMLHttpRequest in IE7 (can't request local files),
7890 * so we use the ActiveXObject when it is available
7891 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
7892 * we need a fallback.
7895 return !this.isLocal && createStandardXHR() || createActiveXHR();
7897 // For all other browsers, use the standard XMLHttpRequest object
7900 // Determine support properties
7902 jQuery.extend( jQuery.support, {
7904 cors: !!xhr && ( "withCredentials" in xhr )
7906 })( jQuery.ajaxSettings.xhr() );
7908 // Create transport if the browser can provide an xhr
7909 if ( jQuery.support.ajax ) {
7911 jQuery.ajaxTransport(function( s ) {
7912 // Cross domain only allowed if supported through XMLHttpRequest
7913 if ( !s.crossDomain || jQuery.support.cors ) {
7918 send: function( headers, complete ) {
7926 // Passing null username, generates a login popup on Opera (#2865)
7928 xhr.open( s.type, s.url, s.async, s.username, s.password );
7930 xhr.open( s.type, s.url, s.async );
7933 // Apply custom fields if provided
7934 if ( s.xhrFields ) {
7935 for ( i in s.xhrFields ) {
7936 xhr[ i ] = s.xhrFields[ i ];
7940 // Override mime type if needed
7941 if ( s.mimeType && xhr.overrideMimeType ) {
7942 xhr.overrideMimeType( s.mimeType );
7945 // X-Requested-With header
7946 // For cross-domain requests, seeing as conditions for a preflight are
7947 // akin to a jigsaw puzzle, we simply never set it to be sure.
7948 // (it can always be set on a per-request basis or even using ajaxSetup)
7949 // For same-domain requests, won't change header if already provided.
7950 if ( !s.crossDomain && !headers["X-Requested-With"] ) {
7951 headers[ "X-Requested-With" ] = "XMLHttpRequest";
7954 // Need an extra try/catch for cross domain requests in Firefox 3
7956 for ( i in headers ) {
7957 xhr.setRequestHeader( i, headers[ i ] );
7961 // Do send the request
7962 // This may raise an exception which is actually
7963 // handled in jQuery.ajax (so no try/catch here)
7964 xhr.send( ( s.hasContent && s.data ) || null );
7967 callback = function( _, isAbort ) {
7975 // Firefox throws exceptions when accessing properties
7976 // of an xhr when a network error occured
7977 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
7980 // Was never called and is aborted or complete
7981 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
7984 callback = undefined;
7986 // Do not keep as active anymore
7988 xhr.onreadystatechange = jQuery.noop;
7989 if ( xhrOnUnloadAbort ) {
7990 delete xhrCallbacks[ handle ];
7996 // Abort it manually if needed
7997 if ( xhr.readyState !== 4 ) {
8001 status = xhr.status;
8002 responseHeaders = xhr.getAllResponseHeaders();
8004 xml = xhr.responseXML;
8006 // Construct response list
8007 if ( xml && xml.documentElement /* #4958 */ ) {
8008 responses.xml = xml;
8010 responses.text = xhr.responseText;
8012 // Firefox throws an exception when accessing
8013 // statusText for faulty cross-domain requests
8015 statusText = xhr.statusText;
8017 // We normalize with Webkit giving an empty statusText
8021 // Filter status for non standard behaviors
8023 // If the request is local and we have data: assume a success
8024 // (success with no data won't get notified, that's the best we
8025 // can do given current implementations)
8026 if ( !status && s.isLocal && !s.crossDomain ) {
8027 status = responses.text ? 200 : 404;
8028 // IE - #1450: sometimes returns 1223 when it should be 204
8029 } else if ( status === 1223 ) {
8034 } catch( firefoxAccessException ) {
8036 complete( -1, firefoxAccessException );
8040 // Call complete if needed
8042 complete( status, statusText, responses, responseHeaders );
8046 // if we're in sync mode or it's in cache
8047 // and has been retrieved directly (IE6 & IE7)
8048 // we need to manually fire the callback
8049 if ( !s.async || xhr.readyState === 4 ) {
8053 if ( xhrOnUnloadAbort ) {
8054 // Create the active xhrs callbacks list if needed
8055 // and attach the unload handler
8056 if ( !xhrCallbacks ) {
8058 jQuery( window ).unload( xhrOnUnloadAbort );
8060 // Add to list of active xhrs callbacks
8061 xhrCallbacks[ handle ] = callback;
8063 xhr.onreadystatechange = callback;
8080 var elemdisplay = {},
8082 rfxtypes = /^(?:toggle|show|hide)$/,
8083 rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
8086 // height animations
8087 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
8089 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
8090 // opacity animations
8096 show: function( speed, easing, callback ) {
8099 if ( speed || speed === 0 ) {
8100 return this.animate( genFx("show", 3), speed, easing, callback);
8103 for ( var i = 0, j = this.length; i < j; i++ ) {
8107 display = elem.style.display;
8109 // Reset the inline display of this element to learn if it is
8110 // being hidden by cascaded rules or not
8111 if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
8112 display = elem.style.display = "";
8115 // Set elements which have been overridden with display: none
8116 // in a stylesheet to whatever the default browser style is
8117 // for such an element
8118 if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
8119 jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
8124 // Set the display of most of the elements in a second loop
8125 // to avoid the constant reflow
8126 for ( i = 0; i < j; i++ ) {
8130 display = elem.style.display;
8132 if ( display === "" || display === "none" ) {
8133 elem.style.display = jQuery._data(elem, "olddisplay") || "";
8142 hide: function( speed, easing, callback ) {
8143 if ( speed || speed === 0 ) {
8144 return this.animate( genFx("hide", 3), speed, easing, callback);
8147 for ( var i = 0, j = this.length; i < j; i++ ) {
8148 if ( this[i].style ) {
8149 var display = jQuery.css( this[i], "display" );
8151 if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
8152 jQuery._data( this[i], "olddisplay", display );
8157 // Set the display of the elements in a second loop
8158 // to avoid the constant reflow
8159 for ( i = 0; i < j; i++ ) {
8160 if ( this[i].style ) {
8161 this[i].style.display = "none";
8169 // Save the old toggle function
8170 _toggle: jQuery.fn.toggle,
8172 toggle: function( fn, fn2, callback ) {
8173 var bool = typeof fn === "boolean";
8175 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
8176 this._toggle.apply( this, arguments );
8178 } else if ( fn == null || bool ) {
8179 this.each(function() {
8180 var state = bool ? fn : jQuery(this).is(":hidden");
8181 jQuery(this)[ state ? "show" : "hide" ]();
8185 this.animate(genFx("toggle", 3), fn, fn2, callback);
8191 fadeTo: function( speed, to, easing, callback ) {
8192 return this.filter(":hidden").css("opacity", 0).show().end()
8193 .animate({opacity: to}, speed, easing, callback);
8196 animate: function( prop, speed, easing, callback ) {
8197 var optall = jQuery.speed(speed, easing, callback);
8199 if ( jQuery.isEmptyObject( prop ) ) {
8200 return this.each( optall.complete, [ false ] );
8203 // Do not change referenced properties as per-property easing will be lost
8204 prop = jQuery.extend( {}, prop );
8206 return this[ optall.queue === false ? "each" : "queue" ](function() {
8207 // XXX 'this' does not always have a nodeName when running the
8210 if ( optall.queue === false ) {
8211 jQuery._mark( this );
8214 var opt = jQuery.extend( {}, optall ),
8215 isElement = this.nodeType === 1,
8216 hidden = isElement && jQuery(this).is(":hidden"),
8219 parts, start, end, unit;
8221 // will store per property easing and be used to determine when an animation is complete
8222 opt.animatedProperties = {};
8226 // property name normalization
8227 name = jQuery.camelCase( p );
8229 prop[ name ] = prop[ p ];
8235 // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
8236 if ( jQuery.isArray( val ) ) {
8237 opt.animatedProperties[ name ] = val[ 1 ];
8238 val = prop[ name ] = val[ 0 ];
8240 opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
8243 if ( val === "hide" && hidden || val === "show" && !hidden ) {
8244 return opt.complete.call( this );
8247 if ( isElement && ( name === "height" || name === "width" ) ) {
8248 // Make sure that nothing sneaks out
8249 // Record all 3 overflow attributes because IE does not
8250 // change the overflow attribute when overflowX and
8251 // overflowY are set to the same value
8252 opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
8254 // Set display property to inline-block for height/width
8255 // animations on inline elements that are having width/height
8257 if ( jQuery.css( this, "display" ) === "inline" &&
8258 jQuery.css( this, "float" ) === "none" ) {
8259 if ( !jQuery.support.inlineBlockNeedsLayout ) {
8260 this.style.display = "inline-block";
8263 display = defaultDisplay( this.nodeName );
8265 // inline-level elements accept inline-block;
8266 // block-level elements need to be inline with layout
8267 if ( display === "inline" ) {
8268 this.style.display = "inline-block";
8271 this.style.display = "inline";
8272 this.style.zoom = 1;
8279 if ( opt.overflow != null ) {
8280 this.style.overflow = "hidden";
8284 e = new jQuery.fx( this, opt, p );
8287 if ( rfxtypes.test(val) ) {
8288 e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
8291 parts = rfxnum.exec( val );
8295 end = parseFloat( parts[2] );
8296 unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
8298 // We need to compute starting value
8299 if ( unit !== "px" ) {
8300 jQuery.style( this, p, (end || 1) + unit);
8301 start = ((end || 1) / e.cur()) * start;
8302 jQuery.style( this, p, start + unit);
8305 // If a +=/-= token was provided, we're doing a relative animation
8307 end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
8310 e.custom( start, end, unit );
8313 e.custom( start, val, "" );
8318 // For JS strict compliance
8323 stop: function( clearQueue, gotoEnd ) {
8328 this.each(function() {
8329 var timers = jQuery.timers,
8331 // clear marker counters if we know they won't be
8333 jQuery._unmark( true, this );
8336 if ( timers[i].elem === this ) {
8338 // force the next step to be the last
8342 timers.splice(i, 1);
8347 // start the next in the queue if the last step wasn't forced
8357 // Animations created synchronously will run synchronously
8358 function createFxNow() {
8359 setTimeout( clearFxNow, 0 );
8360 return ( fxNow = jQuery.now() );
8363 function clearFxNow() {
8367 // Generate parameters to create a standard animation
8368 function genFx( type, num ) {
8371 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
8378 // Generate shortcuts for custom animations
8380 slideDown: genFx("show", 1),
8381 slideUp: genFx("hide", 1),
8382 slideToggle: genFx("toggle", 1),
8383 fadeIn: { opacity: "show" },
8384 fadeOut: { opacity: "hide" },
8385 fadeToggle: { opacity: "toggle" }
8386 }, function( name, props ) {
8387 jQuery.fn[ name ] = function( speed, easing, callback ) {
8388 return this.animate( props, speed, easing, callback );
8393 speed: function( speed, easing, fn ) {
8394 var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
8395 complete: fn || !fn && easing ||
8396 jQuery.isFunction( speed ) && speed,
8398 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
8401 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
8402 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
8405 opt.old = opt.complete;
8406 opt.complete = function( noUnmark ) {
8407 if ( jQuery.isFunction( opt.old ) ) {
8408 opt.old.call( this );
8411 if ( opt.queue !== false ) {
8412 jQuery.dequeue( this );
8413 } else if ( noUnmark !== false ) {
8414 jQuery._unmark( this );
8422 linear: function( p, n, firstNum, diff ) {
8423 return firstNum + diff * p;
8425 swing: function( p, n, firstNum, diff ) {
8426 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
8432 fx: function( elem, options, prop ) {
8433 this.options = options;
8437 options.orig = options.orig || {};
8442 jQuery.fx.prototype = {
8443 // Simple function for setting a style value
8444 update: function() {
8445 if ( this.options.step ) {
8446 this.options.step.call( this.elem, this.now, this );
8449 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
8452 // Get the current size
8454 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
8455 return this.elem[ this.prop ];
8459 r = jQuery.css( this.elem, this.prop );
8460 // Empty strings, null, undefined and "auto" are converted to 0,
8461 // complex values such as "rotate(1rad)" are returned as is,
8462 // simple values such as "10px" are parsed to Float.
8463 return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
8466 // Start an animation from one number to another
8467 custom: function( from, to, unit ) {
8471 this.startTime = fxNow || createFxNow();
8474 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
8475 this.now = this.start;
8476 this.pos = this.state = 0;
8478 function t( gotoEnd ) {
8479 return self.step(gotoEnd);
8484 if ( t() && jQuery.timers.push(t) && !timerId ) {
8485 timerId = setInterval( fx.tick, fx.interval );
8489 // Simple 'show' function
8491 // Remember where we started, so that we can go back to it later
8492 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
8493 this.options.show = true;
8495 // Begin the animation
8496 // Make sure that we start at a small width/height to avoid any
8498 this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
8500 // Start by showing the element
8501 jQuery( this.elem ).show();
8504 // Simple 'hide' function
8506 // Remember where we started, so that we can go back to it later
8507 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
8508 this.options.hide = true;
8510 // Begin the animation
8511 this.custom(this.cur(), 0);
8514 // Each step of an animation
8515 step: function( gotoEnd ) {
8516 var t = fxNow || createFxNow(),
8519 options = this.options,
8522 if ( gotoEnd || t >= options.duration + this.startTime ) {
8523 this.now = this.end;
8524 this.pos = this.state = 1;
8527 options.animatedProperties[ this.prop ] = true;
8529 for ( i in options.animatedProperties ) {
8530 if ( options.animatedProperties[i] !== true ) {
8536 // Reset the overflow
8537 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
8539 jQuery.each( [ "", "X", "Y" ], function (index, value) {
8540 elem.style[ "overflow" + value ] = options.overflow[index];
8544 // Hide the element if the "hide" operation was done
8545 if ( options.hide ) {
8546 jQuery(elem).hide();
8549 // Reset the properties, if the item has been hidden or shown
8550 if ( options.hide || options.show ) {
8551 for ( var p in options.animatedProperties ) {
8552 jQuery.style( elem, p, options.orig[p] );
8556 // Execute the complete function
8557 options.complete.call( elem );
8563 // classical easing cannot be used with an Infinity duration
8564 if ( options.duration == Infinity ) {
8567 n = t - this.startTime;
8568 this.state = n / options.duration;
8570 // Perform the easing function, defaults to swing
8571 this.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );
8572 this.now = this.start + ((this.end - this.start) * this.pos);
8574 // Perform the next step of the animation
8582 jQuery.extend( jQuery.fx, {
8584 for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {
8585 if ( !timers[i]() ) {
8586 timers.splice(i--, 1);
8590 if ( !timers.length ) {
8598 clearInterval( timerId );
8610 opacity: function( fx ) {
8611 jQuery.style( fx.elem, "opacity", fx.now );
8614 _default: function( fx ) {
8615 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
8616 fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
8618 fx.elem[ fx.prop ] = fx.now;
8624 if ( jQuery.expr && jQuery.expr.filters ) {
8625 jQuery.expr.filters.animated = function( elem ) {
8626 return jQuery.grep(jQuery.timers, function( fn ) {
8627 return elem === fn.elem;
8632 // Try to restore the default display value of an element
8633 function defaultDisplay( nodeName ) {
8635 if ( !elemdisplay[ nodeName ] ) {
8637 var body = document.body,
8638 elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
8639 display = elem.css( "display" );
8643 // If the simple way fails,
8644 // get element's real default display by attaching it to a temp iframe
8645 if ( display === "none" || display === "" ) {
8646 // No iframe to use yet, so create it
8648 iframe = document.createElement( "iframe" );
8649 iframe.frameBorder = iframe.width = iframe.height = 0;
8652 body.appendChild( iframe );
8654 // Create a cacheable copy of the iframe document on first call.
8655 // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
8656 // document to it; WebKit & Firefox won't allow reusing the iframe document.
8657 if ( !iframeDoc || !iframe.createElement ) {
8658 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
8659 iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
8663 elem = iframeDoc.createElement( nodeName );
8665 iframeDoc.body.appendChild( elem );
8667 display = jQuery.css( elem, "display" );
8669 body.removeChild( iframe );
8672 // Store the correct default display
8673 elemdisplay[ nodeName ] = display;
8676 return elemdisplay[ nodeName ];
8682 var rtable = /^t(?:able|d|h)$/i,
8683 rroot = /^(?:body|html)$/i;
8685 if ( "getBoundingClientRect" in document.documentElement ) {
8686 jQuery.fn.offset = function( options ) {
8687 var elem = this[0], box;
8690 return this.each(function( i ) {
8691 jQuery.offset.setOffset( this, options, i );
8695 if ( !elem || !elem.ownerDocument ) {
8699 if ( elem === elem.ownerDocument.body ) {
8700 return jQuery.offset.bodyOffset( elem );
8704 box = elem.getBoundingClientRect();
8707 var doc = elem.ownerDocument,
8708 docElem = doc.documentElement;
8710 // Make sure we're not dealing with a disconnected DOM node
8711 if ( !box || !jQuery.contains( docElem, elem ) ) {
8712 return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
8715 var body = doc.body,
8716 win = getWindow(doc),
8717 clientTop = docElem.clientTop || body.clientTop || 0,
8718 clientLeft = docElem.clientLeft || body.clientLeft || 0,
8719 scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
8720 scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
8721 top = box.top + scrollTop - clientTop,
8722 left = box.left + scrollLeft - clientLeft;
8724 return { top: top, left: left };
8728 jQuery.fn.offset = function( options ) {
8732 return this.each(function( i ) {
8733 jQuery.offset.setOffset( this, options, i );
8737 if ( !elem || !elem.ownerDocument ) {
8741 if ( elem === elem.ownerDocument.body ) {
8742 return jQuery.offset.bodyOffset( elem );
8745 jQuery.offset.initialize();
8748 offsetParent = elem.offsetParent,
8749 prevOffsetParent = elem,
8750 doc = elem.ownerDocument,
8751 docElem = doc.documentElement,
8753 defaultView = doc.defaultView,
8754 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
8755 top = elem.offsetTop,
8756 left = elem.offsetLeft;
8758 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
8759 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
8763 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
8764 top -= elem.scrollTop;
8765 left -= elem.scrollLeft;
8767 if ( elem === offsetParent ) {
8768 top += elem.offsetTop;
8769 left += elem.offsetLeft;
8771 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
8772 top += parseFloat( computedStyle.borderTopWidth ) || 0;
8773 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
8776 prevOffsetParent = offsetParent;
8777 offsetParent = elem.offsetParent;
8780 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
8781 top += parseFloat( computedStyle.borderTopWidth ) || 0;
8782 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
8785 prevComputedStyle = computedStyle;
8788 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
8789 top += body.offsetTop;
8790 left += body.offsetLeft;
8793 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
8794 top += Math.max( docElem.scrollTop, body.scrollTop );
8795 left += Math.max( docElem.scrollLeft, body.scrollLeft );
8798 return { top: top, left: left };
8803 initialize: function() {
8804 var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
8805 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>";
8807 jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
8809 container.innerHTML = html;
8810 body.insertBefore( container, body.firstChild );
8811 innerDiv = container.firstChild;
8812 checkDiv = innerDiv.firstChild;
8813 td = innerDiv.nextSibling.firstChild.firstChild;
8815 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
8816 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
8818 checkDiv.style.position = "fixed";
8819 checkDiv.style.top = "20px";
8821 // safari subtracts parent border width here which is 5px
8822 this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
8823 checkDiv.style.position = checkDiv.style.top = "";
8825 innerDiv.style.overflow = "hidden";
8826 innerDiv.style.position = "relative";
8828 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
8830 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
8832 body.removeChild( container );
8833 jQuery.offset.initialize = jQuery.noop;
8836 bodyOffset: function( body ) {
8837 var top = body.offsetTop,
8838 left = body.offsetLeft;
8840 jQuery.offset.initialize();
8842 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
8843 top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
8844 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
8847 return { top: top, left: left };
8850 setOffset: function( elem, options, i ) {
8851 var position = jQuery.css( elem, "position" );
8853 // set position first, in-case top/left are set even on static elem
8854 if ( position === "static" ) {
8855 elem.style.position = "relative";
8858 var curElem = jQuery( elem ),
8859 curOffset = curElem.offset(),
8860 curCSSTop = jQuery.css( elem, "top" ),
8861 curCSSLeft = jQuery.css( elem, "left" ),
8862 calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
8863 props = {}, curPosition = {}, curTop, curLeft;
8865 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
8866 if ( calculatePosition ) {
8867 curPosition = curElem.position();
8868 curTop = curPosition.top;
8869 curLeft = curPosition.left;
8871 curTop = parseFloat( curCSSTop ) || 0;
8872 curLeft = parseFloat( curCSSLeft ) || 0;
8875 if ( jQuery.isFunction( options ) ) {
8876 options = options.call( elem, i, curOffset );
8879 if (options.top != null) {
8880 props.top = (options.top - curOffset.top) + curTop;
8882 if (options.left != null) {
8883 props.left = (options.left - curOffset.left) + curLeft;
8886 if ( "using" in options ) {
8887 options.using.call( elem, props );
8889 curElem.css( props );
8896 position: function() {
8903 // Get *real* offsetParent
8904 offsetParent = this.offsetParent(),
8906 // Get correct offsets
8907 offset = this.offset(),
8908 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
8910 // Subtract element margins
8911 // note: when an element has margin: auto the offsetLeft and marginLeft
8912 // are the same in Safari causing offset.left to incorrectly be 0
8913 offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
8914 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
8916 // Add offsetParent borders
8917 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
8918 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
8920 // Subtract the two offsets
8922 top: offset.top - parentOffset.top,
8923 left: offset.left - parentOffset.left
8927 offsetParent: function() {
8928 return this.map(function() {
8929 var offsetParent = this.offsetParent || document.body;
8930 while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
8931 offsetParent = offsetParent.offsetParent;
8933 return offsetParent;
8939 // Create scrollLeft and scrollTop methods
8940 jQuery.each( ["Left", "Top"], function( i, name ) {
8941 var method = "scroll" + name;
8943 jQuery.fn[ method ] = function( val ) {
8946 if ( val === undefined ) {
8953 win = getWindow( elem );
8955 // Return the scroll offset
8956 return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
8957 jQuery.support.boxModel && win.document.documentElement[ method ] ||
8958 win.document.body[ method ] :
8962 // Set the scroll offset
8963 return this.each(function() {
8964 win = getWindow( this );
8968 !i ? val : jQuery( win ).scrollLeft(),
8969 i ? val : jQuery( win ).scrollTop()
8973 this[ method ] = val;
8979 function getWindow( elem ) {
8980 return jQuery.isWindow( elem ) ?
8982 elem.nodeType === 9 ?
8983 elem.defaultView || elem.parentWindow :
8990 // Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
8991 jQuery.each([ "Height", "Width" ], function( i, name ) {
8993 var type = name.toLowerCase();
8995 // innerHeight and innerWidth
8996 jQuery.fn[ "inner" + name ] = function() {
8998 return elem && elem.style ?
8999 parseFloat( jQuery.css( elem, type, "padding" ) ) :
9003 // outerHeight and outerWidth
9004 jQuery.fn[ "outer" + name ] = function( margin ) {
9006 return elem && elem.style ?
9007 parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
9011 jQuery.fn[ type ] = function( size ) {
9012 // Get window width or height
9015 return size == null ? null : this;
9018 if ( jQuery.isFunction( size ) ) {
9019 return this.each(function( i ) {
9020 var self = jQuery( this );
9021 self[ type ]( size.call( this, i, self[ type ]() ) );
9025 if ( jQuery.isWindow( elem ) ) {
9026 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
9027 // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
9028 var docElemProp = elem.document.documentElement[ "client" + name ],
9029 body = elem.document.body;
9030 return elem.document.compatMode === "CSS1Compat" && docElemProp ||
9031 body && body[ "client" + name ] || docElemProp;
9033 // Get document width or height
9034 } else if ( elem.nodeType === 9 ) {
9035 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
9037 elem.documentElement["client" + name],
9038 elem.body["scroll" + name], elem.documentElement["scroll" + name],
9039 elem.body["offset" + name], elem.documentElement["offset" + name]
9042 // Get or set width or height on the element
9043 } else if ( size === undefined ) {
9044 var orig = jQuery.css( elem, type ),
9045 ret = parseFloat( orig );
9047 return jQuery.isNaN( ret ) ? orig : ret;
9049 // Set the width or height on the element (default to pixels if value is unitless)
9051 return this.css( type, typeof size === "string" ? size : size + "px" );
9058 // Expose jQuery to the global object
9059 window.jQuery = window.$ = jQuery;
9061 // Underscore.js 1.1.7
9062 // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
9063 // Underscore is freely distributable under the MIT license.
9064 // Portions of Underscore are inspired or borrowed from Prototype,
9065 // Oliver Steele's Functional, and John Resig's Micro-Templating.
9066 // For all details and documentation:
9067 // http://documentcloud.github.com/underscore
9074 // Establish the root object, `window` in the browser, or `global` on the server.
9077 // Save the previous value of the `_` variable.
9078 var previousUnderscore = root._;
9080 // Establish the object that gets returned to break out of a loop iteration.
9083 // Save bytes in the minified (but not gzipped) version:
9084 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
9086 // Create quick reference variables for speed access to core prototypes.
9087 var slice = ArrayProto.slice,
9088 unshift = ArrayProto.unshift,
9089 toString = ObjProto.toString,
9090 hasOwnProperty = ObjProto.hasOwnProperty;
9092 // All **ECMAScript 5** native function implementations that we hope to use
9093 // are declared here.
9095 nativeForEach = ArrayProto.forEach,
9096 nativeMap = ArrayProto.map,
9097 nativeReduce = ArrayProto.reduce,
9098 nativeReduceRight = ArrayProto.reduceRight,
9099 nativeFilter = ArrayProto.filter,
9100 nativeEvery = ArrayProto.every,
9101 nativeSome = ArrayProto.some,
9102 nativeIndexOf = ArrayProto.indexOf,
9103 nativeLastIndexOf = ArrayProto.lastIndexOf,
9104 nativeIsArray = Array.isArray,
9105 nativeKeys = Object.keys,
9106 nativeBind = FuncProto.bind;
9108 // Create a safe reference to the Underscore object for use below.
9109 var _ = function(obj) { return new wrapper(obj); };
9111 // Export the Underscore object for **CommonJS**, with backwards-compatibility
9112 // for the old `require()` API. If we're not in CommonJS, add `_` to the
9114 if (typeof module !== 'undefined' && module.exports) {
9118 // Exported as a string, for Closure Compiler "advanced" mode.
9123 _.VERSION = '1.1.7';
9125 // Collection Functions
9126 // --------------------
9128 // The cornerstone, an `each` implementation, aka `forEach`.
9129 // Handles objects with the built-in `forEach`, arrays, and raw objects.
9130 // Delegates to **ECMAScript 5**'s native `forEach` if available.
9131 var each = _.each = _.forEach = function(obj, iterator, context) {
9132 if (obj == null) return;
9133 if (nativeForEach && obj.forEach === nativeForEach) {
9134 obj.forEach(iterator, context);
9135 } else if (obj.length === +obj.length) {
9136 for (var i = 0, l = obj.length; i < l; i++) {
9137 if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
9140 for (var key in obj) {
9141 if (hasOwnProperty.call(obj, key)) {
9142 if (iterator.call(context, obj[key], key, obj) === breaker) return;
9148 // Return the results of applying the iterator to each element.
9149 // Delegates to **ECMAScript 5**'s native `map` if available.
9150 _.map = function(obj, iterator, context) {
9152 if (obj == null) return results;
9153 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
9154 each(obj, function(value, index, list) {
9155 results[results.length] = iterator.call(context, value, index, list);
9160 // **Reduce** builds up a single result from a list of values, aka `inject`,
9161 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
9162 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
9163 var initial = memo !== void 0;
9164 if (obj == null) obj = [];
9165 if (nativeReduce && obj.reduce === nativeReduce) {
9166 if (context) iterator = _.bind(iterator, context);
9167 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
9169 each(obj, function(value, index, list) {
9174 memo = iterator.call(context, memo, value, index, list);
9177 if (!initial) throw new TypeError("Reduce of empty array with no initial value");
9181 // The right-associative version of reduce, also known as `foldr`.
9182 // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
9183 _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
9184 if (obj == null) obj = [];
9185 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
9186 if (context) iterator = _.bind(iterator, context);
9187 return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
9189 var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
9190 return _.reduce(reversed, iterator, memo, context);
9193 // Return the first value which passes a truth test. Aliased as `detect`.
9194 _.find = _.detect = function(obj, iterator, context) {
9196 any(obj, function(value, index, list) {
9197 if (iterator.call(context, value, index, list)) {
9205 // Return all the elements that pass a truth test.
9206 // Delegates to **ECMAScript 5**'s native `filter` if available.
9207 // Aliased as `select`.
9208 _.filter = _.select = function(obj, iterator, context) {
9210 if (obj == null) return results;
9211 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
9212 each(obj, function(value, index, list) {
9213 if (iterator.call(context, value, index, list)) results[results.length] = value;
9218 // Return all the elements for which a truth test fails.
9219 _.reject = function(obj, iterator, context) {
9221 if (obj == null) return results;
9222 each(obj, function(value, index, list) {
9223 if (!iterator.call(context, value, index, list)) results[results.length] = value;
9228 // Determine whether all of the elements match a truth test.
9229 // Delegates to **ECMAScript 5**'s native `every` if available.
9230 // Aliased as `all`.
9231 _.every = _.all = function(obj, iterator, context) {
9233 if (obj == null) return result;
9234 if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
9235 each(obj, function(value, index, list) {
9236 if (!(result = result && iterator.call(context, value, index, list))) return breaker;
9241 // Determine if at least one element in the object matches a truth test.
9242 // Delegates to **ECMAScript 5**'s native `some` if available.
9243 // Aliased as `any`.
9244 var any = _.some = _.any = function(obj, iterator, context) {
9245 iterator = iterator || _.identity;
9247 if (obj == null) return result;
9248 if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
9249 each(obj, function(value, index, list) {
9250 if (result |= iterator.call(context, value, index, list)) return breaker;
9255 // Determine if a given value is included in the array or object using `===`.
9256 // Aliased as `contains`.
9257 _.include = _.contains = function(obj, target) {
9259 if (obj == null) return found;
9260 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
9261 any(obj, function(value) {
9262 if (found = value === target) return true;
9267 // Invoke a method (with arguments) on every item in a collection.
9268 _.invoke = function(obj, method) {
9269 var args = slice.call(arguments, 2);
9270 return _.map(obj, function(value) {
9271 return (method.call ? method || value : value[method]).apply(value, args);
9275 // Convenience version of a common use case of `map`: fetching a property.
9276 _.pluck = function(obj, key) {
9277 return _.map(obj, function(value){ return value[key]; });
9280 // Return the maximum element or (element-based computation).
9281 _.max = function(obj, iterator, context) {
9282 if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
9283 var result = {computed : -Infinity};
9284 each(obj, function(value, index, list) {
9285 var computed = iterator ? iterator.call(context, value, index, list) : value;
9286 computed >= result.computed && (result = {value : value, computed : computed});
9288 return result.value;
9291 // Return the minimum element (or element-based computation).
9292 _.min = function(obj, iterator, context) {
9293 if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
9294 var result = {computed : Infinity};
9295 each(obj, function(value, index, list) {
9296 var computed = iterator ? iterator.call(context, value, index, list) : value;
9297 computed < result.computed && (result = {value : value, computed : computed});
9299 return result.value;
9302 // Sort the object's values by a criterion produced by an iterator.
9303 _.sortBy = function(obj, iterator, context) {
9304 return _.pluck(_.map(obj, function(value, index, list) {
9307 criteria : iterator.call(context, value, index, list)
9309 }).sort(function(left, right) {
9310 var a = left.criteria, b = right.criteria;
9311 return a < b ? -1 : a > b ? 1 : 0;
9315 // Groups the object's values by a criterion produced by an iterator
9316 _.groupBy = function(obj, iterator) {
9318 each(obj, function(value, index) {
9319 var key = iterator(value, index);
9320 (result[key] || (result[key] = [])).push(value);
9325 // Use a comparator function to figure out at what index an object should
9326 // be inserted so as to maintain order. Uses binary search.
9327 _.sortedIndex = function(array, obj, iterator) {
9328 iterator || (iterator = _.identity);
9329 var low = 0, high = array.length;
9330 while (low < high) {
9331 var mid = (low + high) >> 1;
9332 iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
9337 // Safely convert anything iterable into a real, live array.
9338 _.toArray = function(iterable) {
9339 if (!iterable) return [];
9340 if (iterable.toArray) return iterable.toArray();
9341 if (_.isArray(iterable)) return slice.call(iterable);
9342 if (_.isArguments(iterable)) return slice.call(iterable);
9343 return _.values(iterable);
9346 // Return the number of elements in an object.
9347 _.size = function(obj) {
9348 return _.toArray(obj).length;
9354 // Get the first element of an array. Passing **n** will return the first N
9355 // values in the array. Aliased as `head`. The **guard** check allows it to work
9357 _.first = _.head = function(array, n, guard) {
9358 return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
9361 // Returns everything but the first entry of the array. Aliased as `tail`.
9362 // Especially useful on the arguments object. Passing an **index** will return
9363 // the rest of the values in the array from that index onward. The **guard**
9364 // check allows it to work with `_.map`.
9365 _.rest = _.tail = function(array, index, guard) {
9366 return slice.call(array, (index == null) || guard ? 1 : index);
9369 // Get the last element of an array.
9370 _.last = function(array) {
9371 return array[array.length - 1];
9374 // Trim out all falsy values from an array.
9375 _.compact = function(array) {
9376 return _.filter(array, function(value){ return !!value; });
9379 // Return a completely flattened version of an array.
9380 _.flatten = function(array) {
9381 return _.reduce(array, function(memo, value) {
9382 if (_.isArray(value)) return memo.concat(_.flatten(value));
9383 memo[memo.length] = value;
9388 // Return a version of the array that does not contain the specified value(s).
9389 _.without = function(array) {
9390 return _.difference(array, slice.call(arguments, 1));
9393 // Produce a duplicate-free version of the array. If the array has already
9394 // been sorted, you have the option of using a faster algorithm.
9395 // Aliased as `unique`.
9396 _.uniq = _.unique = function(array, isSorted) {
9397 return _.reduce(array, function(memo, el, i) {
9398 if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
9403 // Produce an array that contains the union: each distinct element from all of
9404 // the passed-in arrays.
9405 _.union = function() {
9406 return _.uniq(_.flatten(arguments));
9409 // Produce an array that contains every item shared between all the
9410 // passed-in arrays. (Aliased as "intersect" for back-compat.)
9411 _.intersection = _.intersect = function(array) {
9412 var rest = slice.call(arguments, 1);
9413 return _.filter(_.uniq(array), function(item) {
9414 return _.every(rest, function(other) {
9415 return _.indexOf(other, item) >= 0;
9420 // Take the difference between one array and another.
9421 // Only the elements present in just the first array will remain.
9422 _.difference = function(array, other) {
9423 return _.filter(array, function(value){ return !_.include(other, value); });
9426 // Zip together multiple lists into a single array -- elements that share
9427 // an index go together.
9428 _.zip = function() {
9429 var args = slice.call(arguments);
9430 var length = _.max(_.pluck(args, 'length'));
9431 var results = new Array(length);
9432 for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
9436 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
9437 // we need this function. Return the position of the first occurrence of an
9438 // item in an array, or -1 if the item is not included in the array.
9439 // Delegates to **ECMAScript 5**'s native `indexOf` if available.
9440 // If the array is large and already in sort order, pass `true`
9441 // for **isSorted** to use binary search.
9442 _.indexOf = function(array, item, isSorted) {
9443 if (array == null) return -1;
9446 i = _.sortedIndex(array, item);
9447 return array[i] === item ? i : -1;
9449 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
9450 for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
9455 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
9456 _.lastIndexOf = function(array, item) {
9457 if (array == null) return -1;
9458 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
9459 var i = array.length;
9460 while (i--) if (array[i] === item) return i;
9464 // Generate an integer Array containing an arithmetic progression. A port of
9465 // the native Python `range()` function. See
9466 // [the Python documentation](http://docs.python.org/library/functions.html#range).
9467 _.range = function(start, stop, step) {
9468 if (arguments.length <= 1) {
9472 step = arguments[2] || 1;
9474 var len = Math.max(Math.ceil((stop - start) / step), 0);
9476 var range = new Array(len);
9479 range[idx++] = start;
9486 // Function (ahem) Functions
9487 // ------------------
9489 // Create a function bound to a given object (assigning `this`, and arguments,
9490 // optionally). Binding with arguments is also known as `curry`.
9491 // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
9492 // We check for `func.bind` first, to fail fast when `func` is undefined.
9493 _.bind = function(func, obj) {
9494 if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
9495 var args = slice.call(arguments, 2);
9497 return func.apply(obj, args.concat(slice.call(arguments)));
9501 // Bind all of an object's methods to that object. Useful for ensuring that
9502 // all callbacks defined on an object belong to it.
9503 _.bindAll = function(obj) {
9504 var funcs = slice.call(arguments, 1);
9505 if (funcs.length == 0) funcs = _.functions(obj);
9506 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
9510 // Memoize an expensive function by storing its results.
9511 _.memoize = function(func, hasher) {
9513 hasher || (hasher = _.identity);
9515 var key = hasher.apply(this, arguments);
9516 return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
9520 // Delays a function for the given number of milliseconds, and then calls
9521 // it with the arguments supplied.
9522 _.delay = function(func, wait) {
9523 var args = slice.call(arguments, 2);
9524 return setTimeout(function(){ return func.apply(func, args); }, wait);
9527 // Defers a function, scheduling it to run after the current call stack has
9529 _.defer = function(func) {
9530 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
9533 // Internal function used to implement `_.throttle` and `_.debounce`.
9534 var limit = function(func, wait, debounce) {
9537 var context = this, args = arguments;
9538 var throttler = function() {
9540 func.apply(context, args);
9542 if (debounce) clearTimeout(timeout);
9543 if (debounce || !timeout) timeout = setTimeout(throttler, wait);
9547 // Returns a function, that, when invoked, will only be triggered at most once
9548 // during a given window of time.
9549 _.throttle = function(func, wait) {
9550 return limit(func, wait, false);
9553 // Returns a function, that, as long as it continues to be invoked, will not
9554 // be triggered. The function will be called after it stops being called for
9556 _.debounce = function(func, wait) {
9557 return limit(func, wait, true);
9560 // Returns a function that will be executed at most one time, no matter how
9561 // often you call it. Useful for lazy initialization.
9562 _.once = function(func) {
9563 var ran = false, memo;
9565 if (ran) return memo;
9567 return memo = func.apply(this, arguments);
9571 // Returns the first function passed as an argument to the second,
9572 // allowing you to adjust arguments, run code before and after, and
9573 // conditionally execute the original function.
9574 _.wrap = function(func, wrapper) {
9576 var args = [func].concat(slice.call(arguments));
9577 return wrapper.apply(this, args);
9581 // Returns a function that is the composition of a list of functions, each
9582 // consuming the return value of the function that follows.
9583 _.compose = function() {
9584 var funcs = slice.call(arguments);
9586 var args = slice.call(arguments);
9587 for (var i = funcs.length - 1; i >= 0; i--) {
9588 args = [funcs[i].apply(this, args)];
9594 // Returns a function that will only be executed after being called N times.
9595 _.after = function(times, func) {
9597 if (--times < 1) { return func.apply(this, arguments); }
9605 // Retrieve the names of an object's properties.
9606 // Delegates to **ECMAScript 5**'s native `Object.keys`
9607 _.keys = nativeKeys || function(obj) {
9608 if (obj !== Object(obj)) throw new TypeError('Invalid object');
9610 for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
9614 // Retrieve the values of an object's properties.
9615 _.values = function(obj) {
9616 return _.map(obj, _.identity);
9619 // Return a sorted list of the function names available on the object.
9620 // Aliased as `methods`
9621 _.functions = _.methods = function(obj) {
9623 for (var key in obj) {
9624 if (_.isFunction(obj[key])) names.push(key);
9626 return names.sort();
9629 // Extend a given object with all the properties in passed-in object(s).
9630 _.extend = function(obj) {
9631 each(slice.call(arguments, 1), function(source) {
9632 for (var prop in source) {
9633 if (source[prop] !== void 0) obj[prop] = source[prop];
9639 // Fill in a given object with default properties.
9640 _.defaults = function(obj) {
9641 each(slice.call(arguments, 1), function(source) {
9642 for (var prop in source) {
9643 if (obj[prop] == null) obj[prop] = source[prop];
9649 // Create a (shallow-cloned) duplicate of an object.
9650 _.clone = function(obj) {
9651 return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
9654 // Invokes interceptor with the obj, and then returns obj.
9655 // The primary purpose of this method is to "tap into" a method chain, in
9656 // order to perform operations on intermediate results within the chain.
9657 _.tap = function(obj, interceptor) {
9662 // Perform a deep comparison to check if two objects are equal.
9663 _.isEqual = function(a, b) {
9664 // Check object identity.
9665 if (a === b) return true;
9667 var atype = typeof(a), btype = typeof(b);
9668 if (atype != btype) return false;
9669 // Basic equality test (watch out for coercions).
9670 if (a == b) return true;
9671 // One is falsy and the other truthy.
9672 if ((!a && b) || (a && !b)) return false;
9673 // Unwrap any wrapped objects.
9674 if (a._chain) a = a._wrapped;
9675 if (b._chain) b = b._wrapped;
9676 // One of them implements an isEqual()?
9677 if (a.isEqual) return a.isEqual(b);
9678 if (b.isEqual) return b.isEqual(a);
9679 // Check dates' integer values.
9680 if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
9682 if (_.isNaN(a) && _.isNaN(b)) return false;
9683 // Compare regular expressions.
9684 if (_.isRegExp(a) && _.isRegExp(b))
9685 return a.source === b.source &&
9686 a.global === b.global &&
9687 a.ignoreCase === b.ignoreCase &&
9688 a.multiline === b.multiline;
9689 // If a is not an object by this point, we can't handle it.
9690 if (atype !== 'object') return false;
9691 // Check for different array lengths before comparing contents.
9692 if (a.length && (a.length !== b.length)) return false;
9693 // Nothing else worked, deep compare the contents.
9694 var aKeys = _.keys(a), bKeys = _.keys(b);
9695 // Different object sizes?
9696 if (aKeys.length != bKeys.length) return false;
9697 // Recursive comparison of contents.
9698 for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
9702 // Is a given array or object empty?
9703 _.isEmpty = function(obj) {
9704 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
9705 for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
9709 // Is a given value a DOM element?
9710 _.isElement = function(obj) {
9711 return !!(obj && obj.nodeType == 1);
9714 // Is a given value an array?
9715 // Delegates to ECMA5's native Array.isArray
9716 _.isArray = nativeIsArray || function(obj) {
9717 return toString.call(obj) === '[object Array]';
9720 // Is a given variable an object?
9721 _.isObject = function(obj) {
9722 return obj === Object(obj);
9725 // Is a given variable an arguments object?
9726 _.isArguments = function(obj) {
9727 return !!(obj && hasOwnProperty.call(obj, 'callee'));
9730 // Is a given value a function?
9731 _.isFunction = function(obj) {
9732 return !!(obj && obj.constructor && obj.call && obj.apply);
9735 // Is a given value a string?
9736 _.isString = function(obj) {
9737 return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
9740 // Is a given value a number?
9741 _.isNumber = function(obj) {
9742 return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
9745 // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
9746 // that does not equal itself.
9747 _.isNaN = function(obj) {
9751 // Is a given value a boolean?
9752 _.isBoolean = function(obj) {
9753 return obj === true || obj === false;
9756 // Is a given value a date?
9757 _.isDate = function(obj) {
9758 return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
9761 // Is the given value a regular expression?
9762 _.isRegExp = function(obj) {
9763 return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
9766 // Is a given value equal to null?
9767 _.isNull = function(obj) {
9768 return obj === null;
9771 // Is a given variable undefined?
9772 _.isUndefined = function(obj) {
9773 return obj === void 0;
9776 // Utility Functions
9777 // -----------------
9779 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
9780 // previous owner. Returns a reference to the Underscore object.
9781 _.noConflict = function() {
9782 root._ = previousUnderscore;
9786 // Keep the identity function around for default iterators.
9787 _.identity = function(value) {
9791 // Run a function **n** times.
9792 _.times = function (n, iterator, context) {
9793 for (var i = 0; i < n; i++) iterator.call(context, i);
9796 // Add your own custom functions to the Underscore object, ensuring that
9797 // they're correctly added to the OOP wrapper as well.
9798 _.mixin = function(obj) {
9799 each(_.functions(obj), function(name){
9800 addToWrapper(name, _[name] = obj[name]);
9804 // Generate a unique integer id (unique within the entire client session).
9805 // Useful for temporary DOM ids.
9807 _.uniqueId = function(prefix) {
9808 var id = idCounter++;
9809 return prefix ? prefix + id : id;
9812 // By default, Underscore uses ERB-style template delimiters, change the
9813 // following template settings to use alternative delimiters.
9814 _.templateSettings = {
9815 evaluate : /<%([\s\S]+?)%>/g,
9816 interpolate : /<%=([\s\S]+?)%>/g
9819 // JavaScript micro-templating, similar to John Resig's implementation.
9820 // Underscore templating handles arbitrary delimiters, preserves whitespace,
9821 // and correctly escapes quotes within interpolated code.
9822 _.template = function(str, data) {
9823 var c = _.templateSettings;
9824 var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
9825 'with(obj||{}){__p.push(\'' +
9826 str.replace(/\\/g, '\\\\')
9827 .replace(/'/g, "\\'")
9828 .replace(c.interpolate, function(match, code) {
9829 return "'," + code.replace(/\\'/g, "'") + ",'";
9831 .replace(c.evaluate || null, function(match, code) {
9832 return "');" + code.replace(/\\'/g, "'")
9833 .replace(/[\r\n\t]/g, ' ') + "__p.push('";
9835 .replace(/\r/g, '\\r')
9836 .replace(/\n/g, '\\n')
9837 .replace(/\t/g, '\\t')
9838 + "');}return __p.join('');";
9839 var func = new Function('obj', tmpl);
9840 return data ? func(data) : func;
9846 // If Underscore is called as a function, it returns a wrapped object that
9847 // can be used OO-style. This wrapper holds altered versions of all the
9848 // underscore functions. Wrapped objects may be chained.
9849 var wrapper = function(obj) { this._wrapped = obj; };
9851 // Expose `wrapper.prototype` as `_.prototype`
9852 _.prototype = wrapper.prototype;
9854 // Helper function to continue chaining intermediate results.
9855 var result = function(obj, chain) {
9856 return chain ? _(obj).chain() : obj;
9859 // A method to easily add functions to the OOP wrapper.
9860 var addToWrapper = function(name, func) {
9861 wrapper.prototype[name] = function() {
9862 var args = slice.call(arguments);
9863 unshift.call(args, this._wrapped);
9864 return result(func.apply(_, args), this._chain);
9868 // Add all of the Underscore functions to the wrapper object.
9871 // Add all mutator Array functions to the wrapper.
9872 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
9873 var method = ArrayProto[name];
9874 wrapper.prototype[name] = function() {
9875 method.apply(this._wrapped, arguments);
9876 return result(this._wrapped, this._chain);
9880 // Add all accessor Array functions to the wrapper.
9881 each(['concat', 'join', 'slice'], function(name) {
9882 var method = ArrayProto[name];
9883 wrapper.prototype[name] = function() {
9884 return result(method.apply(this._wrapped, arguments), this._chain);
9888 // Start chaining a wrapped Underscore object.
9889 wrapper.prototype.chain = function() {
9894 // Extracts the result from a wrapped and chained object.
9895 wrapper.prototype.value = function() {
9896 return this._wrapped;
9900 // Backbone.js 0.5.3
9901 // (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
9902 // Backbone may be freely distributed under the MIT license.
9903 // For all details and documentation:
9904 // http://documentcloud.github.com/backbone
9911 // Save a reference to the global object.
9914 // Save the previous value of the `Backbone` variable.
9915 var previousBackbone = root.Backbone;
9917 // The top-level namespace. All public Backbone classes and modules will
9918 // be attached to this. Exported for both CommonJS and the browser.
9920 if (typeof exports !== 'undefined') {
9923 Backbone = root.Backbone = {};
9926 // Current version of the library. Keep in sync with `package.json`.
9927 Backbone.VERSION = '0.5.3';
9929 // Require Underscore, if we're on the server, and it's not already present.
9931 if (!_ && (typeof require !== 'undefined')) _ = require('underscore')._;
9933 // For Backbone's purposes, jQuery or Zepto owns the `$` variable.
9934 var $ = root.jQuery || root.Zepto;
9936 // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
9937 // to its previous owner. Returns a reference to this Backbone object.
9938 Backbone.noConflict = function() {
9939 root.Backbone = previousBackbone;
9943 // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option will
9944 // fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and set a
9945 // `X-Http-Method-Override` header.
9946 Backbone.emulateHTTP = false;
9948 // Turn on `emulateJSON` to support legacy servers that can't deal with direct
9949 // `application/json` requests ... will encode the body as
9950 // `application/x-www-form-urlencoded` instead and will send the model in a
9951 // form param named `model`.
9952 Backbone.emulateJSON = false;
9955 // -----------------
9957 // A module that can be mixed in to *any object* in order to provide it with
9958 // custom events. You may `bind` or `unbind` a callback function to an event;
9959 // `trigger`-ing an event fires all callbacks in succession.
9962 // _.extend(object, Backbone.Events);
9963 // object.bind('expand', function(){ alert('expanded'); });
9964 // object.trigger('expand');
9968 // Bind an event, specified by a string name, `ev`, to a `callback` function.
9969 // Passing `"all"` will bind the callback to all events fired.
9970 bind : function(ev, callback, context) {
9971 var calls = this._callbacks || (this._callbacks = {});
9972 var list = calls[ev] || (calls[ev] = []);
9973 list.push([callback, context]);
9977 // Remove one or many callbacks. If `callback` is null, removes all
9978 // callbacks for the event. If `ev` is null, removes all bound callbacks
9980 unbind : function(ev, callback) {
9983 this._callbacks = {};
9984 } else if (calls = this._callbacks) {
9988 var list = calls[ev];
9989 if (!list) return this;
9990 for (var i = 0, l = list.length; i < l; i++) {
9991 if (list[i] && callback === list[i][0]) {
10001 // Trigger an event, firing all bound callbacks. Callbacks are passed the
10002 // same arguments as `trigger` is, apart from the event name.
10003 // Listening for `"all"` passes the true event name as the first argument.
10004 trigger : function(eventName) {
10005 var list, calls, ev, callback, args;
10007 if (!(calls = this._callbacks)) return this;
10009 ev = both ? eventName : 'all';
10010 if (list = calls[ev]) {
10011 for (var i = 0, l = list.length; i < l; i++) {
10012 if (!(callback = list[i])) {
10013 list.splice(i, 1); i--; l--;
10015 args = both ? Array.prototype.slice.call(arguments, 1) : arguments;
10016 callback[0].apply(callback[1] || this, args);
10029 // Create a new model, with defined attributes. A client id (`cid`)
10030 // is automatically generated and assigned for you.
10031 Backbone.Model = function(attributes, options) {
10033 attributes || (attributes = {});
10034 if (defaults = this.defaults) {
10035 if (_.isFunction(defaults)) defaults = defaults.call(this);
10036 attributes = _.extend({}, defaults, attributes);
10038 this.attributes = {};
10039 this._escapedAttributes = {};
10040 this.cid = _.uniqueId('c');
10041 this.set(attributes, {silent : true});
10042 this._changed = false;
10043 this._previousAttributes = _.clone(this.attributes);
10044 if (options && options.collection) this.collection = options.collection;
10045 this.initialize(attributes, options);
10048 // Attach all inheritable methods to the Model prototype.
10049 _.extend(Backbone.Model.prototype, Backbone.Events, {
10051 // A snapshot of the model's previous attributes, taken immediately
10052 // after the last `"change"` event was fired.
10053 _previousAttributes : null,
10055 // Has the item been changed since the last `"change"` event?
10058 // The default name for the JSON `id` attribute is `"id"`. MongoDB and
10059 // CouchDB users may want to set this to `"_id"`.
10060 idAttribute : 'id',
10062 // Initialize is an empty function by default. Override it with your own
10063 // initialization logic.
10064 initialize : function(){},
10066 // Return a copy of the model's `attributes` object.
10067 toJSON : function() {
10068 return _.clone(this.attributes);
10071 // Get the value of an attribute.
10072 get : function(attr) {
10073 return this.attributes[attr];
10076 // Get the HTML-escaped value of an attribute.
10077 escape : function(attr) {
10079 if (html = this._escapedAttributes[attr]) return html;
10080 var val = this.attributes[attr];
10081 return this._escapedAttributes[attr] = escapeHTML(val == null ? '' : '' + val);
10084 // Returns `true` if the attribute contains a value that is not null
10086 has : function(attr) {
10087 return this.attributes[attr] != null;
10090 // Set a hash of model attributes on the object, firing `"change"` unless you
10091 // choose to silence it.
10092 set : function(attrs, options) {
10094 // Extract attributes and options.
10095 options || (options = {});
10096 if (!attrs) return this;
10097 if (attrs.attributes) attrs = attrs.attributes;
10098 var now = this.attributes, escaped = this._escapedAttributes;
10101 if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false;
10103 // Check for changes of `id`.
10104 if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
10106 // We're about to start triggering change events.
10107 var alreadyChanging = this._changing;
10108 this._changing = true;
10110 // Update attributes.
10111 for (var attr in attrs) {
10112 var val = attrs[attr];
10113 if (!_.isEqual(now[attr], val)) {
10115 delete escaped[attr];
10116 this._changed = true;
10117 if (!options.silent) this.trigger('change:' + attr, this, val, options);
10121 // Fire the `"change"` event, if the model has been changed.
10122 if (!alreadyChanging && !options.silent && this._changed) this.change(options);
10123 this._changing = false;
10127 // Remove an attribute from the model, firing `"change"` unless you choose
10128 // to silence it. `unset` is a noop if the attribute doesn't exist.
10129 unset : function(attr, options) {
10130 if (!(attr in this.attributes)) return this;
10131 options || (options = {});
10132 var value = this.attributes[attr];
10136 validObj[attr] = void 0;
10137 if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;
10139 // Remove the attribute.
10140 delete this.attributes[attr];
10141 delete this._escapedAttributes[attr];
10142 if (attr == this.idAttribute) delete this.id;
10143 this._changed = true;
10144 if (!options.silent) {
10145 this.trigger('change:' + attr, this, void 0, options);
10146 this.change(options);
10151 // Clear all attributes on the model, firing `"change"` unless you choose
10153 clear : function(options) {
10154 options || (options = {});
10156 var old = this.attributes;
10160 for (attr in old) validObj[attr] = void 0;
10161 if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;
10163 this.attributes = {};
10164 this._escapedAttributes = {};
10165 this._changed = true;
10166 if (!options.silent) {
10167 for (attr in old) {
10168 this.trigger('change:' + attr, this, void 0, options);
10170 this.change(options);
10175 // Fetch the model from the server. If the server's representation of the
10176 // model differs from its current attributes, they will be overriden,
10177 // triggering a `"change"` event.
10178 fetch : function(options) {
10179 options || (options = {});
10181 var success = options.success;
10182 options.success = function(resp, status, xhr) {
10183 if (!model.set(model.parse(resp, xhr), options)) return false;
10184 if (success) success(model, resp);
10186 options.error = wrapError(options.error, model, options);
10187 return (this.sync || Backbone.sync).call(this, 'read', this, options);
10190 // Set a hash of model attributes, and sync the model to the server.
10191 // If the server returns an attributes hash that differs, the model's
10192 // state will be `set` again.
10193 save : function(attrs, options) {
10194 options || (options = {});
10195 if (attrs && !this.set(attrs, options)) return false;
10197 var success = options.success;
10198 options.success = function(resp, status, xhr) {
10199 if (!model.set(model.parse(resp, xhr), options)) return false;
10200 if (success) success(model, resp, xhr);
10202 options.error = wrapError(options.error, model, options);
10203 var method = this.isNew() ? 'create' : 'update';
10204 return (this.sync || Backbone.sync).call(this, method, this, options);
10207 // Destroy this model on the server if it was already persisted. Upon success, the model is removed
10208 // from its collection, if it has one.
10209 destroy : function(options) {
10210 options || (options = {});
10211 if (this.isNew()) return this.trigger('destroy', this, this.collection, options);
10213 var success = options.success;
10214 options.success = function(resp) {
10215 model.trigger('destroy', model, model.collection, options);
10216 if (success) success(model, resp);
10218 options.error = wrapError(options.error, model, options);
10219 return (this.sync || Backbone.sync).call(this, 'delete', this, options);
10222 // Default URL for the model's representation on the server -- if you're
10223 // using Backbone's restful methods, override this to change the endpoint
10224 // that will be called.
10226 var base = getUrl(this.collection) || this.urlRoot || urlError();
10227 if (this.isNew()) return base;
10228 return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
10231 // **parse** converts a response into the hash of attributes to be `set` on
10232 // the model. The default implementation is just to pass the response along.
10233 parse : function(resp, xhr) {
10237 // Create a new model with identical attributes to this one.
10238 clone : function() {
10239 return new this.constructor(this);
10242 // A model is new if it has never been saved to the server, and lacks an id.
10243 isNew : function() {
10244 return this.id == null;
10247 // Call this method to manually fire a `change` event for this model.
10248 // Calling this will cause all objects observing the model to update.
10249 change : function(options) {
10250 this.trigger('change', this, options);
10251 this._previousAttributes = _.clone(this.attributes);
10252 this._changed = false;
10255 // Determine if the model has changed since the last `"change"` event.
10256 // If you specify an attribute name, determine if that attribute has changed.
10257 hasChanged : function(attr) {
10258 if (attr) return this._previousAttributes[attr] != this.attributes[attr];
10259 return this._changed;
10262 // Return an object containing all the attributes that have changed, or false
10263 // if there are no changed attributes. Useful for determining what parts of a
10264 // view need to be updated and/or what attributes need to be persisted to
10266 changedAttributes : function(now) {
10267 now || (now = this.attributes);
10268 var old = this._previousAttributes;
10269 var changed = false;
10270 for (var attr in now) {
10271 if (!_.isEqual(old[attr], now[attr])) {
10272 changed = changed || {};
10273 changed[attr] = now[attr];
10279 // Get the previous value of an attribute, recorded at the time the last
10280 // `"change"` event was fired.
10281 previous : function(attr) {
10282 if (!attr || !this._previousAttributes) return null;
10283 return this._previousAttributes[attr];
10286 // Get all of the attributes of the model at the time of the previous
10287 // `"change"` event.
10288 previousAttributes : function() {
10289 return _.clone(this._previousAttributes);
10292 // Run validation against a set of incoming attributes, returning `true`
10293 // if all is well. If a specific `error` callback has been passed,
10294 // call that instead of firing the general `"error"` event.
10295 _performValidation : function(attrs, options) {
10296 var error = this.validate(attrs);
10298 if (options.error) {
10299 options.error(this, error, options);
10301 this.trigger('error', this, error, options);
10310 // Backbone.Collection
10311 // -------------------
10313 // Provides a standard collection class for our sets of models, ordered
10314 // or unordered. If a `comparator` is specified, the Collection will maintain
10315 // its models in sort order, as they're added and removed.
10316 Backbone.Collection = function(models, options) {
10317 options || (options = {});
10318 if (options.comparator) this.comparator = options.comparator;
10319 _.bindAll(this, '_onModelEvent', '_removeReference');
10321 if (models) this.reset(models, {silent: true});
10322 this.initialize.apply(this, arguments);
10325 // Define the Collection's inheritable methods.
10326 _.extend(Backbone.Collection.prototype, Backbone.Events, {
10328 // The default model for a collection is just a **Backbone.Model**.
10329 // This should be overridden in most cases.
10330 model : Backbone.Model,
10332 // Initialize is an empty function by default. Override it with your own
10333 // initialization logic.
10334 initialize : function(){},
10336 // The JSON representation of a Collection is an array of the
10337 // models' attributes.
10338 toJSON : function() {
10339 return this.map(function(model){ return model.toJSON(); });
10342 // Add a model, or list of models to the set. Pass **silent** to avoid
10343 // firing the `added` event for every new model.
10344 add : function(models, options) {
10345 if (_.isArray(models)) {
10346 for (var i = 0, l = models.length; i < l; i++) {
10347 this._add(models[i], options);
10350 this._add(models, options);
10355 // Remove a model, or a list of models from the set. Pass silent to avoid
10356 // firing the `removed` event for every model removed.
10357 remove : function(models, options) {
10358 if (_.isArray(models)) {
10359 for (var i = 0, l = models.length; i < l; i++) {
10360 this._remove(models[i], options);
10363 this._remove(models, options);
10368 // Get a model from the set by id.
10369 get : function(id) {
10370 if (id == null) return null;
10371 return this._byId[id.id != null ? id.id : id];
10374 // Get a model from the set by client id.
10375 getByCid : function(cid) {
10376 return cid && this._byCid[cid.cid || cid];
10379 // Get the model at the given index.
10380 at: function(index) {
10381 return this.models[index];
10384 // Force the collection to re-sort itself. You don't need to call this under normal
10385 // circumstances, as the set will maintain sort order as each item is added.
10386 sort : function(options) {
10387 options || (options = {});
10388 if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
10389 this.models = this.sortBy(this.comparator);
10390 if (!options.silent) this.trigger('reset', this, options);
10394 // Pluck an attribute from each model in the collection.
10395 pluck : function(attr) {
10396 return _.map(this.models, function(model){ return model.get(attr); });
10399 // When you have more items than you want to add or remove individually,
10400 // you can reset the entire set with a new list of models, without firing
10401 // any `added` or `removed` events. Fires `reset` when finished.
10402 reset : function(models, options) {
10403 models || (models = []);
10404 options || (options = {});
10405 this.each(this._removeReference);
10407 this.add(models, {silent: true});
10408 if (!options.silent) this.trigger('reset', this, options);
10412 // Fetch the default set of models for this collection, resetting the
10413 // collection when they arrive. If `add: true` is passed, appends the
10414 // models to the collection instead of resetting.
10415 fetch : function(options) {
10416 options || (options = {});
10417 var collection = this;
10418 var success = options.success;
10419 options.success = function(resp, status, xhr) {
10420 collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
10421 if (success) success(collection, resp);
10423 options.error = wrapError(options.error, collection, options);
10424 return (this.sync || Backbone.sync).call(this, 'read', this, options);
10427 // Create a new instance of a model in this collection. After the model
10428 // has been created on the server, it will be added to the collection.
10429 // Returns the model, or 'false' if validation on a new model fails.
10430 create : function(model, options) {
10432 options || (options = {});
10433 model = this._prepareModel(model, options);
10434 if (!model) return false;
10435 var success = options.success;
10436 options.success = function(nextModel, resp, xhr) {
10437 coll.add(nextModel, options);
10438 if (success) success(nextModel, resp, xhr);
10440 model.save(null, options);
10444 // **parse** converts a response into a list of models to be added to the
10445 // collection. The default implementation is just to pass it through.
10446 parse : function(resp, xhr) {
10450 // Proxy to _'s chain. Can't be proxied the same way the rest of the
10451 // underscore methods are proxied because it relies on the underscore
10453 chain: function () {
10454 return _(this.models).chain();
10457 // Reset all internal state. Called when the collection is reset.
10458 _reset : function(options) {
10465 // Prepare a model to be added to this collection
10466 _prepareModel: function(model, options) {
10467 if (!(model instanceof Backbone.Model)) {
10469 model = new this.model(attrs, {collection: this});
10470 if (model.validate && !model._performValidation(attrs, options)) model = false;
10471 } else if (!model.collection) {
10472 model.collection = this;
10477 // Internal implementation of adding a single model to the set, updating
10478 // hash indexes for `id` and `cid` lookups.
10479 // Returns the model, or 'false' if validation on a new model fails.
10480 _add : function(model, options) {
10481 options || (options = {});
10482 model = this._prepareModel(model, options);
10483 if (!model) return false;
10484 var already = this.getByCid(model);
10485 if (already) throw new Error(["Can't add the same model to a set twice", already.id]);
10486 this._byId[model.id] = model;
10487 this._byCid[model.cid] = model;
10488 var index = options.at != null ? options.at :
10489 this.comparator ? this.sortedIndex(model, this.comparator) :
10491 this.models.splice(index, 0, model);
10492 model.bind('all', this._onModelEvent);
10494 if (!options.silent) model.trigger('add', model, this, options);
10498 // Internal implementation of removing a single model from the set, updating
10499 // hash indexes for `id` and `cid` lookups.
10500 _remove : function(model, options) {
10501 options || (options = {});
10502 model = this.getByCid(model) || this.get(model);
10503 if (!model) return null;
10504 delete this._byId[model.id];
10505 delete this._byCid[model.cid];
10506 this.models.splice(this.indexOf(model), 1);
10508 if (!options.silent) model.trigger('remove', model, this, options);
10509 this._removeReference(model);
10513 // Internal method to remove a model's ties to a collection.
10514 _removeReference : function(model) {
10515 if (this == model.collection) {
10516 delete model.collection;
10518 model.unbind('all', this._onModelEvent);
10521 // Internal method called every time a model in the set fires an event.
10522 // Sets need to update their indexes when models change ids. All other
10523 // events simply proxy through. "add" and "remove" events that originate
10524 // in other collections are ignored.
10525 _onModelEvent : function(ev, model, collection, options) {
10526 if ((ev == 'add' || ev == 'remove') && collection != this) return;
10527 if (ev == 'destroy') {
10528 this._remove(model, options);
10530 if (model && ev === 'change:' + model.idAttribute) {
10531 delete this._byId[model.previous(model.idAttribute)];
10532 this._byId[model.id] = model;
10534 this.trigger.apply(this, arguments);
10539 // Underscore methods that we want to implement on the Collection.
10540 var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', 'detect',
10541 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
10542 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size',
10543 'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty', 'groupBy'];
10545 // Mix in each Underscore method as a proxy to `Collection#models`.
10546 _.each(methods, function(method) {
10547 Backbone.Collection.prototype[method] = function() {
10548 return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
10553 // -------------------
10555 // Routers map faux-URLs to actions, and fire events when routes are
10556 // matched. Creating a new one sets its `routes` hash, if not set statically.
10557 Backbone.Router = function(options) {
10558 options || (options = {});
10559 if (options.routes) this.routes = options.routes;
10560 this._bindRoutes();
10561 this.initialize.apply(this, arguments);
10564 // Cached regular expressions for matching named param parts and splatted
10565 // parts of route strings.
10566 var namedParam = /:([\w\d]+)/g;
10567 var splatParam = /\*([\w\d]+)/g;
10568 var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
10570 // Set up all inheritable **Backbone.Router** properties and methods.
10571 _.extend(Backbone.Router.prototype, Backbone.Events, {
10573 // Initialize is an empty function by default. Override it with your own
10574 // initialization logic.
10575 initialize : function(){},
10577 // Manually bind a single named route to a callback. For example:
10579 // this.route('search/:query/p:num', 'search', function(query, num) {
10583 route : function(route, name, callback) {
10584 Backbone.history || (Backbone.history = new Backbone.History);
10585 if (!_.isRegExp(route)) route = this._routeToRegExp(route);
10586 Backbone.history.route(route, _.bind(function(fragment) {
10587 var args = this._extractParameters(route, fragment);
10588 callback.apply(this, args);
10589 this.trigger.apply(this, ['route:' + name].concat(args));
10593 // Simple proxy to `Backbone.history` to save a fragment into the history.
10594 navigate : function(fragment, triggerRoute) {
10595 Backbone.history.navigate(fragment, triggerRoute);
10598 // Bind all defined routes to `Backbone.history`. We have to reverse the
10599 // order of the routes here to support behavior where the most general
10600 // routes can be defined at the bottom of the route map.
10601 _bindRoutes : function() {
10602 if (!this.routes) return;
10604 for (var route in this.routes) {
10605 routes.unshift([route, this.routes[route]]);
10607 for (var i = 0, l = routes.length; i < l; i++) {
10608 this.route(routes[i][0], routes[i][1], this[routes[i][1]]);
10612 // Convert a route string into a regular expression, suitable for matching
10613 // against the current location hash.
10614 _routeToRegExp : function(route) {
10615 route = route.replace(escapeRegExp, "\\$&")
10616 .replace(namedParam, "([^\/]*)")
10617 .replace(splatParam, "(.*?)");
10618 return new RegExp('^' + route + '$');
10621 // Given a route, and a URL fragment that it matches, return the array of
10622 // extracted parameters.
10623 _extractParameters : function(route, fragment) {
10624 return route.exec(fragment).slice(1);
10629 // Backbone.History
10630 // ----------------
10632 // Handles cross-browser history management, based on URL fragments. If the
10633 // browser does not support `onhashchange`, falls back to polling.
10634 Backbone.History = function() {
10635 this.handlers = [];
10636 _.bindAll(this, 'checkUrl');
10639 // Cached regex for cleaning hashes.
10640 var hashStrip = /^#*/;
10642 // Cached regex for detecting MSIE.
10643 var isExplorer = /msie [\w.]+/;
10645 // Has the history handling already been started?
10646 var historyStarted = false;
10648 // Set up all inheritable **Backbone.History** properties and methods.
10649 _.extend(Backbone.History.prototype, {
10651 // The default interval to poll for hash changes, if necessary, is
10652 // twenty times a second.
10655 // Get the cross-browser normalized URL fragment, either from the URL,
10656 // the hash, or the override.
10657 getFragment : function(fragment, forcePushState) {
10658 if (fragment == null) {
10659 if (this._hasPushState || forcePushState) {
10660 fragment = window.location.pathname;
10661 var search = window.location.search;
10662 if (search) fragment += search;
10663 if (fragment.indexOf(this.options.root) == 0) fragment = fragment.substr(this.options.root.length);
10665 fragment = window.location.hash;
10668 return decodeURIComponent(fragment.replace(hashStrip, ''));
10671 // Start the hash change handling, returning `true` if the current URL matches
10672 // an existing route, and `false` otherwise.
10673 start : function(options) {
10675 // Figure out the initial configuration. Do we need an iframe?
10676 // Is pushState desired ... is it available?
10677 if (historyStarted) throw new Error("Backbone.history has already been started");
10678 this.options = _.extend({}, {root: '/'}, this.options, options);
10679 this._wantsPushState = !!this.options.pushState;
10680 this._hasPushState = !!(this.options.pushState && window.history && window.history.pushState);
10681 var fragment = this.getFragment();
10682 var docMode = document.documentMode;
10683 var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
10685 this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
10686 this.navigate(fragment);
10689 // Depending on whether we're using pushState or hashes, and whether
10690 // 'onhashchange' is supported, determine how we check the URL state.
10691 if (this._hasPushState) {
10692 $(window).bind('popstate', this.checkUrl);
10693 } else if ('onhashchange' in window && !oldIE) {
10694 $(window).bind('hashchange', this.checkUrl);
10696 setInterval(this.checkUrl, this.interval);
10699 // Determine if we need to change the base url, for a pushState link
10700 // opened by a non-pushState browser.
10701 this.fragment = fragment;
10702 historyStarted = true;
10703 var loc = window.location;
10704 var atRoot = loc.pathname == this.options.root;
10705 if (this._wantsPushState && !this._hasPushState && !atRoot) {
10706 this.fragment = this.getFragment(null, true);
10707 window.location.replace(this.options.root + '#' + this.fragment);
10708 // Return immediately as browser will do redirect to new url
10710 } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
10711 this.fragment = loc.hash.replace(hashStrip, '');
10712 window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
10715 if (!this.options.silent) {
10716 return this.loadUrl();
10720 // Add a route to be tested when the fragment changes. Routes added later may
10721 // override previous routes.
10722 route : function(route, callback) {
10723 this.handlers.unshift({route : route, callback : callback});
10726 // Checks the current URL to see if it has changed, and if it has,
10727 // calls `loadUrl`, normalizing across the hidden iframe.
10728 checkUrl : function(e) {
10729 var current = this.getFragment();
10730 if (current == this.fragment && this.iframe) current = this.getFragment(this.iframe.location.hash);
10731 if (current == this.fragment || current == decodeURIComponent(this.fragment)) return false;
10732 if (this.iframe) this.navigate(current);
10733 this.loadUrl() || this.loadUrl(window.location.hash);
10736 // Attempt to load the current URL fragment. If a route succeeds with a
10737 // match, returns `true`. If no defined routes matches the fragment,
10738 // returns `false`.
10739 loadUrl : function(fragmentOverride) {
10740 var fragment = this.fragment = this.getFragment(fragmentOverride);
10741 var matched = _.any(this.handlers, function(handler) {
10742 if (handler.route.test(fragment)) {
10743 handler.callback(fragment);
10750 // Save a fragment into the hash history. You are responsible for properly
10751 // URL-encoding the fragment in advance. This does not trigger
10752 // a `hashchange` event.
10753 navigate : function(fragment, triggerRoute) {
10754 var frag = (fragment || '').replace(hashStrip, '');
10755 if (this.fragment == frag || this.fragment == decodeURIComponent(frag)) return;
10756 if (this._hasPushState) {
10757 var loc = window.location;
10758 if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag;
10759 this.fragment = frag;
10760 window.history.pushState({}, document.title, loc.protocol + '//' + loc.host + frag);
10762 window.location.hash = this.fragment = frag;
10763 if (this.iframe && (frag != this.getFragment(this.iframe.location.hash))) {
10764 this.iframe.document.open().close();
10765 this.iframe.location.hash = frag;
10768 if (triggerRoute) this.loadUrl(fragment);
10776 // Creating a Backbone.View creates its initial element outside of the DOM,
10777 // if an existing element is not provided...
10778 Backbone.View = function(options) {
10779 this.cid = _.uniqueId('view');
10780 this._configure(options || {});
10781 this._ensureElement();
10782 this.delegateEvents();
10783 this.initialize.apply(this, arguments);
10786 // Element lookup, scoped to DOM elements within the current view.
10787 // This should be prefered to global lookups, if you're dealing with
10788 // a specific view.
10789 var selectorDelegate = function(selector) {
10790 return $(selector, this.el);
10793 // Cached regex to split keys for `delegate`.
10794 var eventSplitter = /^(\S+)\s*(.*)$/;
10796 // List of view options to be merged as properties.
10797 var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'];
10799 // Set up all inheritable **Backbone.View** properties and methods.
10800 _.extend(Backbone.View.prototype, Backbone.Events, {
10802 // The default `tagName` of a View's element is `"div"`.
10805 // Attach the `selectorDelegate` function as the `$` property.
10806 $ : selectorDelegate,
10808 // Initialize is an empty function by default. Override it with your own
10809 // initialization logic.
10810 initialize : function(){},
10812 // **render** is the core function that your view should override, in order
10813 // to populate its element (`this.el`), with the appropriate HTML. The
10814 // convention is for **render** to always return `this`.
10815 render : function() {
10819 // Remove this view from the DOM. Note that the view isn't present in the
10820 // DOM by default, so calling this method may be a no-op.
10821 remove : function() {
10822 $(this.el).remove();
10826 // For small amounts of DOM Elements, where a full-blown template isn't
10827 // needed, use **make** to manufacture elements, one at a time.
10829 // var el = this.make('li', {'class': 'row'}, this.model.escape('title'));
10831 make : function(tagName, attributes, content) {
10832 var el = document.createElement(tagName);
10833 if (attributes) $(el).attr(attributes);
10834 if (content) $(el).html(content);
10838 // Set callbacks, where `this.callbacks` is a hash of
10840 // *{"event selector": "callback"}*
10843 // 'mousedown .title': 'edit',
10844 // 'click .button': 'save'
10847 // pairs. Callbacks will be bound to the view, with `this` set properly.
10848 // Uses event delegation for efficiency.
10849 // Omitting the selector binds the event to `this.el`.
10850 // This only works for delegate-able events: not `focus`, `blur`, and
10851 // not `change`, `submit`, and `reset` in Internet Explorer.
10852 delegateEvents : function(events) {
10853 if (!(events || (events = this.events))) return;
10854 if (_.isFunction(events)) events = events.call(this);
10855 $(this.el).unbind('.delegateEvents' + this.cid);
10856 for (var key in events) {
10857 var method = this[events[key]];
10858 if (!method) throw new Error('Event "' + events[key] + '" does not exist');
10859 var match = key.match(eventSplitter);
10860 var eventName = match[1], selector = match[2];
10861 method = _.bind(method, this);
10862 eventName += '.delegateEvents' + this.cid;
10863 if (selector === '') {
10864 $(this.el).bind(eventName, method);
10866 $(this.el).delegate(selector, eventName, method);
10871 // Performs the initial configuration of a View with a set of options.
10872 // Keys with special meaning *(model, collection, id, className)*, are
10873 // attached directly to the view.
10874 _configure : function(options) {
10875 if (this.options) options = _.extend({}, this.options, options);
10876 for (var i = 0, l = viewOptions.length; i < l; i++) {
10877 var attr = viewOptions[i];
10878 if (options[attr]) this[attr] = options[attr];
10880 this.options = options;
10883 // Ensure that the View has a DOM element to render into.
10884 // If `this.el` is a string, pass it through `$()`, take the first
10885 // matching element, and re-assign it to `el`. Otherwise, create
10886 // an element from the `id`, `className` and `tagName` proeprties.
10887 _ensureElement : function() {
10889 var attrs = this.attributes || {};
10890 if (this.id) attrs.id = this.id;
10891 if (this.className) attrs['class'] = this.className;
10892 this.el = this.make(this.tagName, attrs);
10893 } else if (_.isString(this.el)) {
10894 this.el = $(this.el).get(0);
10900 // The self-propagating extend function that Backbone classes use.
10901 var extend = function (protoProps, classProps) {
10902 var child = inherits(this, protoProps, classProps);
10903 child.extend = this.extend;
10907 // Set up inheritance for the model, collection, and view.
10908 Backbone.Model.extend = Backbone.Collection.extend =
10909 Backbone.Router.extend = Backbone.View.extend = extend;
10911 // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
10915 'delete': 'DELETE',
10922 // Override this function to change the manner in which Backbone persists
10923 // models to the server. You will be passed the type of request, and the
10924 // model in question. By default, uses makes a RESTful Ajax request
10925 // to the model's `url()`. Some possible customizations could be:
10927 // * Use `setTimeout` to batch rapid-fire updates into a single request.
10928 // * Send up the models as XML instead of JSON.
10929 // * Persist models via WebSockets instead of Ajax.
10931 // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
10932 // as `POST`, with a `_method` parameter containing the true HTTP method,
10933 // as well as all requests with the body as `application/x-www-form-urlencoded` instead of
10934 // `application/json` with the model in a param named `model`.
10935 // Useful when interfacing with server-side languages like **PHP** that make
10936 // it difficult to read the body of `PUT` requests.
10937 Backbone.sync = function(method, model, options) {
10938 var type = methodMap[method];
10940 // Default JSON-request options.
10941 var params = _.extend({
10946 // Ensure that we have a URL.
10948 params.url = getUrl(model) || urlError();
10951 // Ensure that we have the appropriate request data.
10952 if (!params.data && model && (method == 'create' || method == 'update')) {
10953 params.contentType = 'application/json';
10954 params.data = JSON.stringify(model.toJSON());
10957 // For older servers, emulate JSON by encoding the request into an HTML-form.
10958 if (Backbone.emulateJSON) {
10959 params.contentType = 'application/x-www-form-urlencoded';
10960 params.data = params.data ? {model : params.data} : {};
10963 // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
10964 // And an `X-HTTP-Method-Override` header.
10965 if (Backbone.emulateHTTP) {
10966 if (type === 'PUT' || type === 'DELETE') {
10967 if (Backbone.emulateJSON) params.data._method = type;
10968 params.type = 'POST';
10969 params.beforeSend = function(xhr) {
10970 xhr.setRequestHeader('X-HTTP-Method-Override', type);
10975 // Don't process data on a non-GET request.
10976 if (params.type !== 'GET' && !Backbone.emulateJSON) {
10977 params.processData = false;
10980 // Make the request.
10981 return $.ajax(params);
10987 // Shared empty constructor function to aid in prototype-chain creation.
10988 var ctor = function(){};
10990 // Helper function to correctly set up the prototype chain, for subclasses.
10991 // Similar to `goog.inherits`, but uses a hash of prototype properties and
10992 // class properties to be extended.
10993 var inherits = function(parent, protoProps, staticProps) {
10996 // The constructor function for the new subclass is either defined by you
10997 // (the "constructor" property in your `extend` definition), or defaulted
10998 // by us to simply call `super()`.
10999 if (protoProps && protoProps.hasOwnProperty('constructor')) {
11000 child = protoProps.constructor;
11002 child = function(){ return parent.apply(this, arguments); };
11005 // Inherit class (static) properties from parent.
11006 _.extend(child, parent);
11008 // Set the prototype chain to inherit from `parent`, without calling
11009 // `parent`'s constructor function.
11010 ctor.prototype = parent.prototype;
11011 child.prototype = new ctor();
11013 // Add prototype properties (instance properties) to the subclass,
11015 if (protoProps) _.extend(child.prototype, protoProps);
11017 // Add static properties to the constructor function, if supplied.
11018 if (staticProps) _.extend(child, staticProps);
11020 // Correctly set child's `prototype.constructor`.
11021 child.prototype.constructor = child;
11023 // Set a convenience property in case the parent's prototype is needed later.
11024 child.__super__ = parent.prototype;
11029 // Helper function to get a URL from a Model or Collection as a property
11030 // or as a function.
11031 var getUrl = function(object) {
11032 if (!(object && object.url)) return null;
11033 return _.isFunction(object.url) ? object.url() : object.url;
11036 // Throw an error when a URL is needed, and none is supplied.
11037 var urlError = function() {
11038 throw new Error('A "url" property or function must be specified');
11041 // Wrap an optional error callback with a fallback error event.
11042 var wrapError = function(onError, model, options) {
11043 return function(resp) {
11045 onError(model, resp, options);
11047 model.trigger('error', model, resp, options);
11052 // Helper function to escape a string for HTML rendering.
11053 var escapeHTML = function(string) {
11054 return string.replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
11059 * Castor - a cross site POSTing JavaScript logging library for Loggly
11061 * Copyright (c) 2011 Loggly, Inc.
11062 * All rights reserved.
11064 * Author: Kord Campbell <kord@loggly.com>
11065 * Date: May 2, 2011
11067 * Uses methods from janky.post, copyright(c) 2011 Thomas Rampelberg <thomas@saunter.org>
11069 * Sample usage (replace with your own Loggly HTTP input URL):
11071 <script src="/js/loggly.js" type="text/javascript"></script>
11072 <script type="text/javascript">
11073 window.onload=function(){
11074 castor = new loggly({ url: 'http://logs.loggly.com/inputs/a4e839e9-4227-49aa-9d28-e18e5ba5a818?rt=1', level: 'WARN'});
11075 castor.log("url="+window.location.href + " browser=" + castor.user_agent + " height=" + castor.browser_size.height);
11082 this.loggly = function(opts) {
11083 this.user_agent = get_agent();
11084 this.browser_size = get_size();
11085 log_methods = {'error': 5, 'warn': 4, 'info': 3, 'debug': 2, 'log': 1};
11086 if (!opts.url) throw new Error("Please include a Loggly HTTP URL.");
11088 this.level = log_methods['info'];
11090 this.level = log_methods[opts.level];
11092 this.log = function(data) {
11093 if (log_methods['log'] == this.level) {
11098 this.debug = function(data) {
11099 if (log_methods['debug'] >= this.level) {
11104 this.info = function(data) {
11105 if (log_methods['info'] >= this.level) {
11110 this.warn = function(data) {
11111 if (log_methods['warn'] >= this.level) {
11116 this.error = function(data) {
11117 if (log_methods['error'] >= this.level) {
11123 this.janky = function(opts) {
11124 janky._form(function(iframe, form) {
11125 form.setAttribute("action", opts.url);
11126 form.setAttribute("method", "post");
11127 janky._input(iframe, form, opts.data);
11129 setTimeout(function(){
11130 document.body.removeChild(iframe);
11134 this.janky._form = function(cb) {
11135 var iframe = document.createElement("iframe");
11136 document.body.appendChild(iframe);
11137 iframe.style.display = "none";
11138 setTimeout(function() {
11139 var form = iframe.contentWindow.document.createElement("form");
11140 iframe.contentWindow.document.body.appendChild(form);
11144 this.janky._input = function(iframe, form, data) {
11145 var inp = iframe.contentWindow.document.createElement("input");
11146 inp.setAttribute("type", "hidden");
11147 inp.setAttribute("name", "source");
11148 inp.value = "castor " + data;
11149 form.appendChild(inp);
11151 this.get_agent = function () {
11152 return navigator.appCodeName + navigator.appName + navigator.appVersion;
11154 this.get_size = function () {
11155 var width = 0; var height = 0;
11156 if( typeof( window.innerWidth ) == 'number' ) {
11157 width = window.innerWidth; height = window.innerHeight;
11158 } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
11159 width = document.documentElement.clientWidth; height = document.documentElement.clientHeight;
11160 } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
11161 width = document.body.clientWidth; height = document.body.clientHeight;
11163 return {'height': height, 'width': width};
11168 jsworld={};jsworld.formatIsoDateTime=function(a,b){if(typeof a==="undefined")a=new Date;if(typeof b==="undefined")b=false;var c=jsworld.formatIsoDate(a)+" "+jsworld.formatIsoTime(a);if(b){var d=a.getHours()-a.getUTCHours();var e=Math.abs(d);var f=a.getUTCMinutes();var g=a.getMinutes();if(g!=f&&f<30&&d<0)e--;if(g!=f&&f>30&&d>0)e--;var h;if(g!=f)h=":30";else h=":00";var i;if(e<10)i="0"+e+h;else i=""+e+h;if(d<0)i="-"+i;else i="+"+i;c=c+i}return c};jsworld.formatIsoDate=function(a){if(typeof a==="undefined")a=new Date;var b=a.getFullYear();var c=a.getMonth()+1;var d=a.getDate();return b+"-"+jsworld._zeroPad(c,2)+"-"+jsworld._zeroPad(d,2)};jsworld.formatIsoTime=function(a){if(typeof a==="undefined")a=new Date;var b=a.getHours();var c=a.getMinutes();var d=a.getSeconds();return jsworld._zeroPad(b,2)+":"+jsworld._zeroPad(c,2)+":"+jsworld._zeroPad(d,2)};jsworld.parseIsoDateTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);var f=parseInt(b[4],10);var g=parseInt(b[5],10);var h=parseInt(b[6],10);if(d<1||d>12||e<1||e>31||f<0||f>23||g<0||g>59||h<0||h>59)throw"Error: Invalid ISO-8601 date/time value";var i=new Date(c,d-1,e,f,g,h);if(i.getDate()!=e||i.getMonth()+1!=d)throw"Error: Invalid date";return i};jsworld.parseIsoDate=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(d<1||d>12||e<1||e>31)throw"Error: Invalid ISO-8601 date value";var f=new Date(c,d-1,e);if(f.getDate()!=e||f.getMonth()+1!=d)throw"Error: Invalid date";return f};jsworld.parseIsoTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(c<0||c>23||d<0||d>59||e<0||e>59)throw"Error: Invalid ISO-8601 time value";return new Date(0,0,0,c,d,e)};jsworld._trim=function(a){var b=" \n\r\t\f \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";for(var c=0;c<a.length;c++){if(b.indexOf(a.charAt(c))===-1){a=a.substring(c);break}}for(c=a.length-1;c>=0;c--){if(b.indexOf(a.charAt(c))===-1){a=a.substring(0,c+1);break}}return b.indexOf(a.charAt(0))===-1?a:""};jsworld._isNumber=function(a){if(typeof a=="number")return true;if(typeof a!="string")return false;var b=a+"";return/^-?(\d+|\d*\.\d+)$/.test(b)};jsworld._isInteger=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\d+$/.test(b)};jsworld._isFloat=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\.\d+?$/.test(b)};jsworld._hasOption=function(a,b){if(typeof a!="string"||typeof b!="string")return false;if(b.indexOf(a)!=-1)return true;else return false};jsworld._stringReplaceAll=function(a,b,c){var d;if(b.length==1&&c.length==1){d="";for(var e=0;e<a.length;e++){if(a.charAt(e)==b.charAt(0))d=d+c.charAt(0);else d=d+a.charAt(e)}return d}else{d=a;var f=d.indexOf(b);while(f!=-1){d=d.replace(b,c);f=d.indexOf(b)}return d}};jsworld._stringStartsWith=function(a,b){if(a.length<b.length)return false;for(var c=0;c<b.length;c++){if(a.charAt(c)!=b.charAt(c))return false}return true};jsworld._getPrecision=function(a){if(typeof a!="string")return-1;var b=a.match(/\.(\d)/);if(b)return parseInt(b[1],10);else return-1};jsworld._splitNumber=function(a){if(typeof a=="number")a=a+"";var b={};if(a.charAt(0)=="-")a=a.substring(1);var c=a.split(".");if(!c[1])c[1]="";b.integer=c[0];b.fraction=c[1];return b};jsworld._formatIntegerPart=function(a,b,c){if(c==""||b=="-1")return a;var d=b.split(";");var e="";var f=a.length;var g;while(f>0){if(d.length>0)g=parseInt(d.shift(),10);if(isNaN(g))throw"Error: Invalid grouping";if(g==-1){e=a.substring(0,f)+e;break}f-=g;if(f<1){e=a.substring(0,f+g)+e;break}e=c+a.substring(f,f+g)+e}return e};jsworld._formatFractionPart=function(a,b){for(var c=0;a.length<b;c++)a=a+"0";return a};jsworld._zeroPad=function(a,b){var c=a+"";while(c.length<b)c="0"+c;return c};jsworld._spacePad=function(a,b){var c=a+"";while(c.length<b)c=" "+c;return c};jsworld.Locale=function(a){this._className="jsworld.Locale";this._parseList=function(a,b){var c=[];if(a==null){throw"Names not defined"}else if(typeof a=="object"){c=a}else if(typeof a=="string"){c=a.split(";",b);for(var d=0;d<c.length;d++){if(c[d][0]=='"'&&c[d][c[d].length-1]=='"')c[d]=c[d].slice(1,-1);else throw"Missing double quotes"}}else{throw"Names must be an array or a string"}if(c.length!=b)throw"Expected "+b+" items, got "+c.length;return c};this._validateFormatString=function(a){if(typeof a=="string"&&a.length>0)return a;else throw"Empty or no string"};if(a==null||typeof a!="object")throw"Error: Invalid/missing locale properties";if(typeof a.decimal_point!="string")throw"Error: Invalid/missing decimal_point property";this.decimal_point=a.decimal_point;if(typeof a.thousands_sep!="string")throw"Error: Invalid/missing thousands_sep property";this.thousands_sep=a.thousands_sep;if(typeof a.grouping!="string")throw"Error: Invalid/missing grouping property";this.grouping=a.grouping;if(typeof a.int_curr_symbol!="string")throw"Error: Invalid/missing int_curr_symbol property";if(!/[A-Za-z]{3}.?/.test(a.int_curr_symbol))throw"Error: Invalid int_curr_symbol property";this.int_curr_symbol=a.int_curr_symbol;if(typeof a.currency_symbol!="string")throw"Error: Invalid/missing currency_symbol property";this.currency_symbol=a.currency_symbol;if(typeof a.frac_digits!="number"&&a.frac_digits<0)throw"Error: Invalid/missing frac_digits property";this.frac_digits=a.frac_digits;if(a.mon_decimal_point===null||a.mon_decimal_point==""){if(this.frac_digits>0)throw"Error: Undefined mon_decimal_point property";else a.mon_decimal_point=""}if(typeof a.mon_decimal_point!="string")throw"Error: Invalid/missing mon_decimal_point property";this.mon_decimal_point=a.mon_decimal_point;if(typeof a.mon_thousands_sep!="string")throw"Error: Invalid/missing mon_thousands_sep property";this.mon_thousands_sep=a.mon_thousands_sep;if(typeof a.mon_grouping!="string")throw"Error: Invalid/missing mon_grouping property";this.mon_grouping=a.mon_grouping;if(typeof a.positive_sign!="string")throw"Error: Invalid/missing positive_sign property";this.positive_sign=a.positive_sign;if(typeof a.negative_sign!="string")throw"Error: Invalid/missing negative_sign property";this.negative_sign=a.negative_sign;if(a.p_cs_precedes!==0&&a.p_cs_precedes!==1)throw"Error: Invalid/missing p_cs_precedes property, must be 0 or 1";this.p_cs_precedes=a.p_cs_precedes;if(a.n_cs_precedes!==0&&a.n_cs_precedes!==1)throw"Error: Invalid/missing n_cs_precedes, must be 0 or 1";this.n_cs_precedes=a.n_cs_precedes;if(a.p_sep_by_space!==0&&a.p_sep_by_space!==1&&a.p_sep_by_space!==2)throw"Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2";this.p_sep_by_space=a.p_sep_by_space;if(a.n_sep_by_space!==0&&a.n_sep_by_space!==1&&a.n_sep_by_space!==2)throw"Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2";this.n_sep_by_space=a.n_sep_by_space;if(a.p_sign_posn!==0&&a.p_sign_posn!==1&&a.p_sign_posn!==2&&a.p_sign_posn!==3&&a.p_sign_posn!==4)throw"Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4";this.p_sign_posn=a.p_sign_posn;if(a.n_sign_posn!==0&&a.n_sign_posn!==1&&a.n_sign_posn!==2&&a.n_sign_posn!==3&&a.n_sign_posn!==4)throw"Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4";this.n_sign_posn=a.n_sign_posn;if(typeof a.int_frac_digits!="number"&&a.int_frac_digits<0)throw"Error: Invalid/missing int_frac_digits property";this.int_frac_digits=a.int_frac_digits;if(a.int_p_cs_precedes!==0&&a.int_p_cs_precedes!==1)throw"Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1";this.int_p_cs_precedes=a.int_p_cs_precedes;if(a.int_n_cs_precedes!==0&&a.int_n_cs_precedes!==1)throw"Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1";this.int_n_cs_precedes=a.int_n_cs_precedes;if(a.int_p_sep_by_space!==0&&a.int_p_sep_by_space!==1&&a.int_p_sep_by_space!==2)throw"Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2";this.int_p_sep_by_space=a.int_p_sep_by_space;if(a.int_n_sep_by_space!==0&&a.int_n_sep_by_space!==1&&a.int_n_sep_by_space!==2)throw"Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2";this.int_n_sep_by_space=a.int_n_sep_by_space;if(a.int_p_sign_posn!==0&&a.int_p_sign_posn!==1&&a.int_p_sign_posn!==2&&a.int_p_sign_posn!==3&&a.int_p_sign_posn!==4)throw"Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_p_sign_posn=a.int_p_sign_posn;if(a.int_n_sign_posn!==0&&a.int_n_sign_posn!==1&&a.int_n_sign_posn!==2&&a.int_n_sign_posn!==3&&a.int_n_sign_posn!==4)throw"Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_n_sign_posn=a.int_n_sign_posn;if(a==null||typeof a!="object")throw"Error: Invalid/missing time locale properties";try{this.abday=this._parseList(a.abday,7)}catch(b){throw"Error: Invalid abday property: "+b}try{this.day=this._parseList(a.day,7)}catch(b){throw"Error: Invalid day property: "+b}try{this.abmon=this._parseList(a.abmon,12)}catch(b){throw"Error: Invalid abmon property: "+b}try{this.mon=this._parseList(a.mon,12)}catch(b){throw"Error: Invalid mon property: "+b}try{this.d_fmt=this._validateFormatString(a.d_fmt)}catch(b){throw"Error: Invalid d_fmt property: "+b}try{this.t_fmt=this._validateFormatString(a.t_fmt)}catch(b){throw"Error: Invalid t_fmt property: "+b}try{this.d_t_fmt=this._validateFormatString(a.d_t_fmt)}catch(b){throw"Error: Invalid d_t_fmt property: "+b}try{var c=this._parseList(a.am_pm,2);this.am=c[0];this.pm=c[1]}catch(b){this.am="";this.pm=""}this.getAbbreviatedWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.abday;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.abday[a]};this.getWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.day;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.day[a]};this.getAbbreviatedMonthName=function(a){if(typeof a=="undefined"||a===null)return this.abmon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.abmon[a]};this.getMonthName=function(a){if(typeof a=="undefined"||a===null)return this.mon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.mon[a]};this.getDecimalPoint=function(){return this.decimal_point};this.getCurrencySymbol=function(){return this.currency_symbol};this.getIntCurrencySymbol=function(){return this.int_curr_symbol.substring(0,3)};this.currencySymbolPrecedes=function(){if(this.p_cs_precedes==1)return true;else return false};this.intCurrencySymbolPrecedes=function(){if(this.int_p_cs_precedes==1)return true;else return false};this.getMonetaryDecimalPoint=function(){return this.mon_decimal_point};this.getFractionalDigits=function(){return this.frac_digits};this.getIntFractionalDigits=function(){return this.int_frac_digits}};jsworld.NumericFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.format=function(a,b){if(typeof a=="string")a=jsworld._trim(a);if(!jsworld._isNumber(a))throw"Error: The input is not a number";var c=parseFloat(a,10);var d=jsworld._getPrecision(b);if(d!=-1)c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.grouping,this.lc.thousands_sep);var g=d!=-1?jsworld._formatFractionPart(e.fraction,d):e.fraction;var h=g.length?f+this.lc.decimal_point+g:f;if(jsworld._hasOption("~",b)||c===0){return h}else{if(jsworld._hasOption("+",b)||c<0){if(c>0)return"+"+h;else if(c<0)return"-"+h;else return h}else{return h}}}};jsworld.DateTimeFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.formatDate=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoDate(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_fmt)};this.formatTime=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoTime(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.t_fmt)};this.formatDateTime=function(a){var b=null;if(typeof a=="string"){b=jsworld.parseIsoDateTime(a)}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_t_fmt)};this._applyFormatting=function(a,b){b=b.replace(/%%/g,"%");b=b.replace(/%a/g,this.lc.abday[a.getDay()]);b=b.replace(/%A/g,this.lc.day[a.getDay()]);b=b.replace(/%b/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%B/g,this.lc.mon[a.getMonth()]);b=b.replace(/%d/g,jsworld._zeroPad(a.getDate(),2));b=b.replace(/%e/g,jsworld._spacePad(a.getDate(),2));b=b.replace(/%F/g,a.getFullYear()+"-"+jsworld._zeroPad(a.getMonth()+1,2)+"-"+jsworld._zeroPad(a.getDate(),2));b=b.replace(/%h/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%H/g,jsworld._zeroPad(a.getHours(),2));b=b.replace(/%I/g,jsworld._zeroPad(this._hours12(a.getHours()),2));b=b.replace(/%k/g,a.getHours());b=b.replace(/%l/g,this._hours12(a.getHours()));b=b.replace(/%m/g,jsworld._zeroPad(a.getMonth()+1,2));b=b.replace(/%n/g,"\n");b=b.replace(/%M/g,jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%p/g,this._getAmPm(a.getHours()));b=b.replace(/%P/g,this._getAmPm(a.getHours()).toLocaleLowerCase());b=b.replace(/%R/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%S/g,jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%T/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2)+":"+jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%w/g,this.lc.day[a.getDay()]);b=b.replace(/%y/g,(new String(a.getFullYear())).substring(2));b=b.replace(/%Y/g,a.getFullYear());b=b.replace(/%Z/g,"");b=b.replace(/%[a-zA-Z]/g,"");return b};this._hours12=function(a){if(a===0)return 12;else if(a>12)return a-12;else return a};this._getAmPm=function(a){if(a===0||a>12)return this.lc.pm;else return this.lc.am}};jsworld.MonetaryFormatter=function(a,b,c){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.currencyFractionDigits={AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,COP:0,CRC:0,DJF:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,IRR:0,ISK:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LAK:0,LBP:0,LYD:3,MGA:0,MMK:0,MNT:0,MRO:0,MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,SYP:0,TND:3,TWD:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,XAF:0,XOF:0,XPF:0,YER:0,ZMK:0};if(typeof b=="string"){this.currencyCode=b.toUpperCase();var d=this.currencyFractionDigits[this.currencyCode];if(typeof d!="number")d=2;this.lc.frac_digits=d;this.lc.int_frac_digits=d}else{this.currencyCode=this.lc.int_curr_symbol.substring(0,3).toUpperCase()}this.intSep=this.lc.int_curr_symbol.charAt(3);if(this.currencyCode==this.lc.int_curr_symbol.substring(0,3)){this.internationalFormatting=false;this.curSym=this.lc.currency_symbol}else{if(typeof c=="string"){this.curSym=c;this.internationalFormatting=false}else{this.internationalFormatting=true}}this.getCurrencySymbol=function(){return this.curSym};this.currencySymbolPrecedes=function(a){if(typeof a=="string"&&a=="i"){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.internationalFormatting){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.lc.p_cs_precedes==1)return true;else return false}}};this.getDecimalPoint=function(){return this.lc.mon_decimal_point};this.getFractionalDigits=function(a){if(typeof a=="string"&&a=="i"){return this.lc.int_frac_digits}else{if(this.internationalFormatting)return this.lc.int_frac_digits;else return this.lc.frac_digits}};this.format=function(a,b){var c;if(typeof a=="string"){a=jsworld._trim(a);c=parseFloat(a);if(typeof c!="number"||isNaN(c))throw"Error: Amount string not a number"}else if(typeof a=="number"){c=a}else{throw"Error: Amount not a number"}var d=jsworld._getPrecision(b);if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))d=this.lc.int_frac_digits;else d=this.lc.frac_digits}c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.mon_grouping,this.lc.mon_thousands_sep);var g;if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))g=jsworld._formatFractionPart(e.fraction,this.lc.int_frac_digits);else g=jsworld._formatFractionPart(e.fraction,this.lc.frac_digits)}else{g=jsworld._formatFractionPart(e.fraction,d)}var h;if(this.lc.frac_digits>0||g.length)h=f+this.lc.mon_decimal_point+g;else h=f;if(jsworld._hasOption("~",b)){return h}else{var i=jsworld._hasOption("!",b)?true:false;var j=c<0?"-":"+";if(this.internationalFormatting||jsworld._hasOption("i",b)){if(i)return this._formatAsInternationalCurrencyWithNoSym(j,h);else return this._formatAsInternationalCurrency(j,h)}else{if(i)return this._formatAsLocalCurrencyWithNoSym(j,h);else return this._formatAsLocalCurrency(j,h)}}};this._formatAsLocalCurrency=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+" "+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+" "+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+" "+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+" "+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+" "+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+" "+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+" "+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+" "+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrency=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsLocalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0){return"("+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0){return"("+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0){return"("+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0){return"("+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC_MONETARY definition"}};jsworld.NumericParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=jsworld._trim(a);b=jsworld._stringReplaceAll(a,this.lc.thousands_sep,"");b=jsworld._stringReplaceAll(b,this.lc.decimal_point,".");if(jsworld._isNumber(b))return parseFloat(b,10);else throw"Parse error: Invalid number string"}};jsworld.DateTimeParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.parseTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.t_fmt,a);var c=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(c)return jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous time string"};this.parseDate=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_fmt,a);var c=false;if(b.year!==null&&b.month!==null&&b.day!==null){c=true}if(c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2);else throw"Parse error: Invalid date string"};this.parseDateTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_t_fmt,a);var c=false;var d=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(b.year!==null&&b.month!==null&&b.day!==null){d=true}if(d&&c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2)+" "+jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous date/time string"};this._extractTokens=function(a,b){var c={year:null,month:null,day:null,hour:null,hourAmPm:null,am:null,minute:null,second:null,weekday:null};while(a.length>0){if(a.charAt(0)=="%"&&a.charAt(1)!=""){var d=a.substring(0,2);if(d=="%%"){b=b.substring(1)}else if(d=="%a"){for(var e=0;e<this.lc.abday.length;e++){if(jsworld._stringStartsWith(b,this.lc.abday[e])){c.weekday=e;b=b.substring(this.lc.abday[e].length);break}}if(c.weekday===null)throw"Parse error: Unrecognised abbreviated weekday name (%a)"}else if(d=="%A"){for(var e=0;e<this.lc.day.length;e++){if(jsworld._stringStartsWith(b,this.lc.day[e])){c.weekday=e;b=b.substring(this.lc.day[e].length);break}}if(c.weekday===null)throw"Parse error: Unrecognised weekday name (%A)"}else if(d=="%b"||d=="%h"){for(var e=0;e<this.lc.abmon.length;e++){if(jsworld._stringStartsWith(b,this.lc.abmon[e])){c.month=e+1;b=b.substring(this.lc.abmon[e].length);break}}if(c.month===null)throw"Parse error: Unrecognised abbreviated month name (%b)"}else if(d=="%B"){for(var e=0;e<this.lc.mon.length;e++){if(jsworld._stringStartsWith(b,this.lc.mon[e])){c.month=e+1;b=b.substring(this.lc.mon[e].length);break}}if(c.month===null)throw"Parse error: Unrecognised month name (%B)"}else if(d=="%d"){if(/^0[1-9]|[1-2][0-9]|3[0-1]/.test(b)){c.day=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised day of the month (%d)"}else if(d=="%e"){var f=b.match(/^\s?(\d{1,2})/);c.day=parseInt(f,10);if(isNaN(c.day)||c.day<1||c.day>31)throw"Parse error: Unrecognised day of the month (%e)";b=b.substring(f.length)}else if(d=="%F"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else{throw"Parse error: Unrecognised date (%F)"}if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)";if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|[1-2][0-9]|3[0-1]/.test(b)){c.day=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)"}else if(d=="%H"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%H)"}else if(d=="%I"){if(/^0[1-9]|1[0-2]/.test(b)){c.hourAmPm=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%I)"}else if(d=="%k"){var g=b.match(/^(\d{1,2})/);c.hour=parseInt(g,10);if(isNaN(c.hour)||c.hour<0||c.hour>23)throw"Parse error: Unrecognised hour (%k)";b=b.substring(g.length)}else if(d=="%l"){var g=b.match(/^(\d{1,2})/);c.hourAmPm=parseInt(g,10);if(isNaN(c.hourAmPm)||c.hourAmPm<1||c.hourAmPm>12)throw"Parse error: Unrecognised hour (%l)";b=b.substring(g.length)}else if(d=="%m"){if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised month (%m)"}else if(d=="%M"){if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised minute (%M)"}else if(d=="%n"){if(b.charAt(0)=="\n")b=b.substring(1);else throw"Parse error: Unrecognised new line (%n)"}else if(d=="%p"){if(jsworld._stringStartsWith(b,this.lc.am)){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm)){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%p)"}else if(d=="%P"){if(jsworld._stringStartsWith(b,this.lc.am.toLowerCase())){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm.toLowerCase())){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%P)"}else if(d=="%R"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%R)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)"}else if(d=="%S"){if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised second (%S)"}else if(d=="%T"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)"}else if(d=="%w"){if(/^\d/.test(b)){c.weekday=parseInt(b.substring(0,1),10);b=b.substring(1)}else throw"Parse error: Unrecognised weekday number (%w)"}else if(d=="%y"){if(/^\d\d/.test(b)){var h=parseInt(b.substring(0,2),10);if(h>50)c.year=1900+h;else c.year=2e3+h;b=b.substring(2)}else throw"Parse error: Unrecognised year (%y)"}else if(d=="%Y"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else throw"Parse error: Unrecognised year (%Y)"}else if(d=="%Z"){if(a.length===0)break}a=a.substring(2)}else{if(a.charAt(0)!=b.charAt(0))throw'Parse error: Unexpected symbol "'+b.charAt(0)+'" in date/time string';a=a.substring(1);b=b.substring(1)}}return c}};jsworld.MonetaryParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._detectCurrencySymbolType(a);var c,d;if(b=="local"){c="local";d=a.replace(this.lc.getCurrencySymbol(),"")}else if(b=="int"){c="int";d=a.replace(this.lc.getIntCurrencySymbol(),"")}else if(b=="none"){c="local";d=a}else throw"Parse error: Internal assert failure";d=jsworld._stringReplaceAll(d,this.lc.mon_thousands_sep,"");d=d.replace(this.lc.mon_decimal_point,".");d=d.replace(/\s*/g,"");d=this._removeLocalNonNegativeSign(d,c);d=this._normaliseNegativeSign(d,c);if(jsworld._isNumber(d))return parseFloat(d,10);else throw"Parse error: Invalid currency amount string"};this._detectCurrencySymbolType=function(a){if(this.lc.getCurrencySymbol().length>this.lc.getIntCurrencySymbol().length){if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else return"none"}else{if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else return"none"}};this._removeLocalNonNegativeSign=function(a,b){a=a.replace(this.lc.positive_sign,"");if((b=="local"&&this.lc.p_sign_posn===0||b=="int"&&this.lc.int_p_sign_posn===0)&&/\(\d+\.?\d*\)/.test(a)){a=a.replace("(","");a=a.replace(")","")}return a};this._normaliseNegativeSign=function(a,b){a=a.replace(this.lc.negative_sign,"-");if(b=="local"&&this.lc.n_sign_posn===0||b=="int"&&this.lc.int_n_sign_posn===0){if(/^\(\d+\.?\d*\)$/.test(a)){a=a.replace("(","");a=a.replace(")","");return"-"+a}}if(b=="local"&&this.lc.n_sign_posn==2||b=="int"&&this.lc.int_n_sign_posn==2){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}if(b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==3||b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==4||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==3||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==4){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}return a}}
11171 if(typeof POSIX_LC == "undefined") var POSIX_LC = {};
11174 "decimal_point" : ".",
11175 "thousands_sep" : ",",
11177 "abday" : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
11178 "day" : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
11179 "abmon" : ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
11180 "mon" : ["January","February","March","April","May","June","July","August","September","October","November","December"],
11181 "d_fmt" : "%m/%e/%y",
11182 "t_fmt" : "%I:%M:%S %p",
11183 "d_t_fmt" : "%B %e, %Y %I:%M:%S %p %Z",
11184 "am_pm" : ["AM","PM"],
11185 "int_curr_symbol" : "USD ",
11186 "currency_symbol" : "\u0024",
11187 "mon_decimal_point" : ".",
11188 "mon_thousands_sep" : ",",
11189 "mon_grouping" : "3",
11190 "positive_sign" : "",
11191 "negative_sign" : "-",
11192 "int_frac_digits" : 2,
11194 "p_cs_precedes" : 1,
11195 "n_cs_precedes" : 1,
11196 "p_sep_by_space" : 0,
11197 "n_sep_by_space" : 0,
11200 "int_p_cs_precedes" : 1,
11201 "int_n_cs_precedes" : 1,
11202 "int_p_sep_by_space" : 0,
11203 "int_n_sep_by_space" : 0,
11204 "int_p_sign_posn" : 1,
11205 "int_n_sign_posn" : 1
11208 if(typeof POSIX_LC == "undefined") var POSIX_LC = {};
11211 "decimal_point" : ",",
11212 "thousands_sep" : "\u00a0",
11214 "abday" : ["dim.","lun.","mar.",
11215 "mer.","jeu.","ven.",
11217 "day" : ["dimanche","lundi","mardi",
11218 "mercredi","jeudi","vendredi",
11220 "abmon" : ["janv.","f\u00e9vr.","mars",
11221 "avr.","mai","juin",
11222 "juil.","ao\u00fbt","sept.",
11223 "oct.","nov.","d\u00e9c."],
11224 "mon" : ["janvier","f\u00e9vrier","mars",
11225 "avril","mai","juin",
11226 "juillet","ao\u00fbt","septembre",
11227 "octobre","novembre","d\u00e9cembre"],
11228 "d_fmt" : "%d/%m/%y",
11229 "t_fmt" : "%H:%M:%S",
11230 "d_t_fmt" : "%e %B %Y %H:%M:%S %Z",
11231 "am_pm" : ["AM","PM"],
11232 "int_curr_symbol" : "EUR ",
11233 "currency_symbol" : "\u20ac",
11234 "mon_decimal_point" : ",",
11235 "mon_thousands_sep" : "\u00a0",
11236 "mon_grouping" : "3",
11237 "positive_sign" : "",
11238 "negative_sign" : "-",
11239 "int_frac_digits" : 2,
11241 "p_cs_precedes" : 0,
11242 "n_cs_precedes" : 0,
11243 "p_sep_by_space" : 1,
11244 "n_sep_by_space" : 1,
11247 "int_p_cs_precedes" : 0,
11248 "int_n_cs_precedes" : 0,
11249 "int_p_sep_by_space" : 1,
11250 "int_n_sep_by_space" : 1,
11251 "int_p_sign_posn" : 1,
11252 "int_n_sign_posn" : 1
11255 /** https://github.com/csnover/js-iso8601 */(function(n,f){var u=n.parse,c=[1,4,5,6,7,10,11];n.parse=function(t){var i,o,a=0;if(o=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(t)){for(var v=0,r;r=c[v];++v)o[r]=+o[r]||0;o[2]=(+o[2]||1)-1,o[3]=+o[3]||1,o[8]!=="Z"&&o[9]!==f&&(a=o[10]*60+o[11],o[9]==="+"&&(a=0-a)),i=n.UTC(o[1],o[2],o[3],o[4],o[5]+a,o[6],o[7])}else i=u?u(t):NaN;return i}})(Date)
11258 * geo-location-javascript v0.4.3
11259 * http://code.google.com/p/geo-location-javascript/
11261 * Copyright (c) 2009 Stan Wiechers
11262 * Licensed under the MIT licenses.
11264 * Revision: $Rev: 68 $:
11265 * Author: $Author: whoisstan $:
11266 * Date: $Date: 2010-02-15 13:42:19 +0100 (Mon, 15 Feb 2010) $:
11268 var geo_position_js=function() {
11273 pub.getCurrentPosition = function(successCallback,errorCallback,options)
11275 provider.getCurrentPosition(successCallback, errorCallback,options);
11278 pub.init = function()
11282 if (typeof(geo_position_js_simulator)!="undefined")
11284 provider=geo_position_js_simulator;
11286 else if (typeof(bondi)!="undefined" && typeof(bondi.geolocation)!="undefined")
11288 provider=bondi.geolocation;
11290 else if (typeof(navigator.geolocation)!="undefined")
11292 provider=navigator.geolocation;
11293 pub.getCurrentPosition = function(successCallback, errorCallback, options)
11295 function _successCallback(p)
11297 //for mozilla geode,it returns the coordinates slightly differently
11298 if(typeof(p.latitude)!="undefined")
11300 successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude,longitude:p.longitude}});
11304 successCallback(p);
11307 provider.getCurrentPosition(_successCallback,errorCallback,options);
11310 else if(typeof(window.google)!="undefined" && typeof(google.gears)!="undefined")
11312 provider=google.gears.factory.create('beta.geolocation');
11314 else if ( typeof(Mojo) !="undefined" && typeof(Mojo.Service.Request)!="Mojo.Service.Request")
11317 pub.getCurrentPosition = function(successCallback, errorCallback, options)
11323 //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition
11324 if (options.enableHighAccuracy && options.enableHighAccuracy==true)
11326 parameters.accuracy=1;
11328 if (options.maximumAge)
11330 parameters.maximumAge=options.maximumAge;
11332 if (options.responseTime)
11334 if(options.responseTime<5)
11336 parameters.responseTime=1;
11338 else if (options.responseTime<20)
11340 parameters.responseTime=2;
11344 parameters.timeout=3;
11350 r=new Mojo.Service.Request('palm://com.palm.location', {
11351 method:"getCurrentPosition",
11352 parameters:parameters,
11353 onSuccess: function(p){successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude, longitude:p.longitude,heading:p.heading}});},
11354 onFailure: function(e){
11355 if (e.errorCode==1)
11357 errorCallback({code:3,message:"Timeout"});
11359 else if (e.errorCode==2)
11361 errorCallback({code:2,message:"Position Unavailable"});
11365 errorCallback({code:0,message:"Unknown Error: webOS-code"+errorCode});
11372 else if (typeof(device)!="undefined" && typeof(device.getServiceObject)!="undefined")
11374 provider=device.getServiceObject("Service.Location", "ILocation");
11376 //override default method implementation
11377 pub.getCurrentPosition = function(successCallback, errorCallback, options)
11379 function callback(transId, eventCode, result) {
11380 if (eventCode == 4)
11382 errorCallback({message:"Position unavailable", code:2});
11386 //no timestamp of location given?
11387 successCallback({timestamp:null, coords: {latitude:result.ReturnValue.Latitude, longitude:result.ReturnValue.Longitude, altitude:result.ReturnValue.Altitude,heading:result.ReturnValue.Heading}});
11390 //location criteria
11391 var criteria = new Object();
11392 criteria.LocationInformationClass = "BasicLocationInformation";
11394 provider.ILocation.GetLocation(criteria,callback);
11400 if(typeof(console)!="undefined")
11406 return provider!=null;
11412 // Couldn't get unminified version to work , go here for docs => https://github.com/iamnoah/writeCapture
11413 (function(E,a){var j=a.document;function A(Q){var Z=j.createElement("div");j.body.insertBefore(Z,null);E.replaceWith(Z,'<script type="text/javascript">'+Q+"<\/script>")}E=E||(function(Q){return{ajax:Q.ajax,$:function(Z){return Q(Z)[0]},replaceWith:function(Z,ad){var ac=Q(Z)[0];var ab=ac.nextSibling,aa=ac.parentNode;Q(ac).remove();if(ab){Q(ab).before(ad)}else{Q(aa).append(ad)}},onLoad:function(Z){Q(Z)},copyAttrs:function(af,ab){var ad=Q(ab),aa=af.attributes;for(var ac=0,Z=aa.length;ac<Z;ac++){if(aa[ac]&&aa[ac].value){try{ad.attr(aa[ac].name,aa[ac].value)}catch(ae){}}}}}})(a.jQuery);E.copyAttrs=E.copyAttrs||function(){};E.onLoad=E.onLoad||function(){throw"error: autoAsync cannot be used without jQuery or defining writeCaptureSupport.onLoad"};function P(ab,aa){for(var Z=0,Q=ab.length;Z<Q;Z++){if(aa(ab[Z])===false){return}}}function v(Q){return Object.prototype.toString.call(Q)==="[object Function]"}function p(Q){return Object.prototype.toString.call(Q)==="[object String]"}function u(aa,Z,Q){return Array.prototype.slice.call(aa,Z||0,Q||aa&&aa.length)}function D(ab,aa){var Q=false;P(ab,Z);function Z(ac){return !(Q=aa(ac))}return Q}function L(Q){this._queue=[];this._children=[];this._parent=Q;if(Q){Q._addChild(this)}}L.prototype={_addChild:function(Q){this._children.push(Q)},push:function(Q){this._queue.push(Q);this._bubble("_doRun")},pause:function(){this._bubble("_doPause")},resume:function(){this._bubble("_doResume")},_bubble:function(Z){var Q=this;while(!Q[Z]){Q=Q._parent}return Q[Z]()},_next:function(){if(D(this._children,Q)){return true}function Q(aa){return aa._next()}var Z=this._queue.shift();if(Z){Z()}return !!Z}};function i(Q){if(Q){return new L(Q)}L.call(this);this.paused=0}i.prototype=(function(){function Q(){}Q.prototype=L.prototype;return new Q()})();i.prototype._doRun=function(){if(!this.running){this.running=true;try{while(this.paused<1&&this._next()){}}finally{this.running=false}}};i.prototype._doPause=function(){this.paused++};i.prototype._doResume=function(){this.paused--;this._doRun()};function M(){}M.prototype={_html:"",open:function(){this._opened=true;if(this._delegate){this._delegate.open()}},write:function(Q){if(this._closed){return}this._written=true;if(this._delegate){this._delegate.write(Q)}else{this._html+=Q}},writeln:function(Q){this.write(Q+"\n")},close:function(){this._closed=true;if(this._delegate){this._delegate.close()}},copyTo:function(Q){this._delegate=Q;Q.foobar=true;if(this._opened){Q.open()}if(this._written){Q.write(this._html)}if(this._closed){Q.close()}}};var e=(function(){var Q={f:j.getElementById};try{Q.f.call(j,"abc");return true}catch(Z){return false}})();function I(Q){P(Q,function(Z){var aa=j.getElementById(Z.id);if(!aa){l("<proxyGetElementById - finish>","no element in writen markup with id "+Z.id);return}P(Z.el.childNodes,function(ab){aa.appendChild(ab)});if(aa.contentWindow){a.setTimeout(function(){Z.el.contentWindow.document.copyTo(aa.contentWindow.document)},1)}E.copyAttrs(Z.el,aa)})}function s(Z,Q){if(Q&&Q[Z]===false){return false}return Q&&Q[Z]||o[Z]}function x(Z,ai){var ae=[],ad=s("proxyGetElementById",ai),ag=s("writeOnGetElementById",ai),Q={write:j.write,writeln:j.writeln,finish:function(){},out:""};Z.state=Q;j.write=ah;j.writeln=aa;if(ad||ag){Q.getEl=j.getElementById;j.getElementById=ab;if(ag){findEl=af}else{findEl=ac;Q.finish=function(){I(ae)}}}function ah(aj){Q.out+=aj}function aa(aj){Q.out+=aj+"\n"}function ac(ak){var aj=j.createElement("div");ae.push({id:ak,el:aj});aj.contentWindow={document:new M()};return aj}function af(al){var aj=E.$(Z.target);var ak=j.createElement("div");aj.parentNode.insertBefore(ak,aj);E.replaceWith(ak,Q.out);Q.out="";return e?Q.getEl.call(j,al):Q.getEl(al)}function ab(ak){var aj=e?Q.getEl.call(j,ak):Q.getEl(ak);return aj||findEl(ak)}return Q}function V(Q){j.write=Q.write;j.writeln=Q.writeln;if(Q.getEl){j.getElementById=Q.getEl}return Q.out}function N(Q){return Q&&Q.replace(/^\s*<!(\[CDATA\[|--)/,"").replace(/(\]\]|--)>\s*$/,"")}function b(){}function d(Z,Q){console.error("Error",Q,"executing code:",Z)}var l=v(a.console&&console.error)?d:b;function S(aa,Z,Q){var ab=x(Z,Q);try{A(N(aa))}catch(ac){l(aa,ac)}finally{V(ab)}return ab}function O(Z){var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(Z);return Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)}function T(Q){return new RegExp(Q+"=(?:([\"'])([\\s\\S]*?)\\1|([^\\s>]+))","i")}function k(Q){var Z=T(Q);return function(aa){var ab=Z.exec(aa)||[];return ab[2]||ab[3]}}var r=/(<script[\s\S]*?>)([\s\S]*?)<\/script>/ig,n=T("src"),X=k("src"),q=k("type"),Y=k("language"),C="__document_write_ajax_callbacks__",B="__document_write_ajax_div-",g="window['"+C+"']['%d']();",m=a[C]={},w='<script type="text/javascript">'+g+"<\/script>",H=0;function c(){return(++H).toString()}function G(Z,aa){var Q;if(v(Z)){Q=Z;Z=null}Z=Z||{};Q=Q||Z&&Z.done;Z.done=aa?function(){aa(Q)}:Q;return Z}var z=new i();var y=[];var f=window._debugWriteCapture?function(){}:function(Q,aa,Z){y.push({type:Q,src:aa,data:Z})};var K=window._debugWriteCapture?function(){}:function(){y.push(arguments)};function W(Q){var Z=c();m[Z]=function(){Q();delete m[Z]};return Z}function J(Q){return w.replace(/%d/,W(Q))}function R(ac,ag,aa,ae){var ad=aa&&new i(aa)||z;ag=G(ag);var ab=s("done",ag);var Q="";var Z=s("fixUrls",ag);if(!v(Z)){Z=function(ah){return ah}}if(v(ab)){Q=J(function(){ad.push(ab)})}return ac.replace(r,af)+Q;function af(aj,av,ai){var an=X(av),am=q(av)||"",aB=Y(av)||"",aA=(!am&&!aB)||am.toLowerCase().indexOf("javascript")!==-1||aB.toLowerCase().indexOf("javascript")!==-1;f("replace",an,aj);if(!aA){return aj}var aw=W(ap),ao=B+aw,au,al={target:"#"+ao,parent:ae};function ap(){ad.push(au)}if(an){an=Z(an);av=av.replace(n,"");if(O(an)){au=az}else{if(s("asyncAll",ag)){au=ay()}else{au=at}}}else{au=ax}function ax(){ah(ai)}function at(){E.ajax({url:an,type:"GET",dataType:"text",async:false,success:function(aC){ah(aC)}})}function ak(aE,aC,aD){l("<XHR for "+an+">",aD);ad.resume()}function aq(){return J(function(){ad.resume()})}function ay(){var aE,aD;function aC(aG,aF){if(!aE){aD=aG;return}try{ah(aG,aq())}catch(aH){l(aG,aH)}}E.ajax({url:an,type:"GET",dataType:"text",async:true,success:aC,error:ak});return function(){aE=true;if(aD){ah(aD)}else{ad.pause()}}}function az(aC){var aE=x(al,ag);ad.pause();f("pause",an);E.ajax({url:an,type:"GET",dataType:"script",success:aD,error:ak});function aD(aH,aG,aF){f("out",an,aE.out);ar(V(aE),J(aE.finish)+aq());f("resume",an)}}function ah(aD,aC){var aE=S(aD,al,ag);aC=J(aE.finish)+(aC||"");ar(aE.out,aC)}function ar(aD,aC){E.replaceWith(al.target,R(aD,null,ad,al)+(aC||""))}return'<div style="display: none" id="'+ao+'"></div>'+av+g.replace(/%d/,aw)+"<\/script>"}}function F(Z,aa){var Q=z;P(Z,function(ab){Q.push(ac);function ac(){ab.action(R(ab.html,ab.options,Q),ab)}});if(aa){Q.push(aa)}}function U(Q){var Z=Q;while(Z&&Z.nodeType===1){Q=Z;Z=Z.lastChild;while(Z&&Z.nodeType!==1){Z=Z.previousSibling}}return Q}function h(Q){var aa=j.write,ad=j.writeln,Z,ab=[];j.writeln=function(ae){j.write(ae+"\n")};var ac;j.write=function(af){var ae=U(j.body);if(ae!==Z){Z=ae;ab.push(ac={el:ae,out:[]})}ac.out.push(af)};E.onLoad(function(){var ah,ak,af,aj,ai;Q=G(Q);ai=Q.done;Q.done=function(){j.write=aa;j.writeln=ad;if(ai){ai()}};for(var ag=0,ae=ab.length;ag<ae;ag++){ah=ab[ag].el;ak=j.createElement("div");ah.parentNode.insertBefore(ak,ah.nextSibling);af=ab[ag].out.join("");aj=ae-ag===1?R(af,Q):R(af);E.replaceWith(ak,aj)}})}var t="writeCapture";var o=a[t]={_original:a[t],fixUrls:function(Q){return Q.replace(/&/g,"&")},noConflict:function(){a[t]=this._original;return this},debug:y,proxyGetElementById:false,_forTest:{Q:i,GLOBAL_Q:z,$:E,matchAttr:k,slice:u,capture:x,uncapture:V,captureWrite:S},replaceWith:function(Q,aa,Z){E.replaceWith(Q,R(aa,Z))},html:function(Q,ab,Z){var aa=E.$(Q);aa.innerHTML="<span/>";E.replaceWith(aa.firstChild,R(ab,Z))},load:function(Q,aa,Z){E.ajax({url:aa,dataType:"text",type:"GET",success:function(ab){o.html(Q,ab,Z)}})},autoAsync:h,sanitize:R,sanitizeSerial:F}})(this.writeCaptureSupport,this);(function(g,d,n){var c={html:h};g.each(["append","prepend","after","before","wrap","wrapAll","replaceWith","wrapInner"],function(){c[this]=i(this)});function a(q){return Object.prototype.toString.call(q)=="[object String]"}function p(u,t,s,r){if(arguments.length==0){return o.call(this)}var q=c[u];if(u=="load"){return l.call(this,t,s,r)}if(!q){j(u)}return b.call(this,t,s,q)}g.fn.writeCapture=p;var k="__writeCaptureJsProxied-fghebd__";function o(){if(this[k]){return this}var r=this;function q(){var t=this,s=false;this[k]=true;g.each(c,function(v){var u=r[v];if(!u){return}t[v]=function(y,x,w){if(!s&&a(y)){try{s=true;return p.call(t,v,y,x,w)}finally{s=false}}return u.apply(t,arguments)}});this.pushStack=function(){return o.call(r.pushStack.apply(t,arguments))};this.endCapture=function(){return r}}q.prototype=r;return new q()}function b(t,s,u){var q,r=this;if(s&&s.done){q=s.done;delete s.done}else{if(g.isFunction(s)){q=s;s=null}}d.sanitizeSerial(g.map(this,function(v){return{html:t,options:s,action:function(w){u.call(v,w)}}}),q&&function(){q.call(r)}||q);return this}function h(q){g(this).html(q)}function i(q){return function(r){g(this)[q](r)}}function l(t,s,v){var r=this,q,u=t.indexOf(" ");if(u>=0){q=t.slice(u,t.length);t=t.slice(0,u)}if(g.isFunction(v)){s=s||{};s.done=v}return g.ajax({url:t,type:s&&s.type||"GET",dataType:"html",data:s&&s.params,complete:f(r,s,q)})}function f(r,s,q){return function(u,t){if(t=="success"||t=="notmodified"){var v=m(u.responseText,q);b.call(r,v,s,h)}}}var e=/jquery-writeCapture-script-placeholder-(\d+)-wc/g;function m(s,r){if(!r||!s){return s}var t=0,q={};return g("<div/>").append(s.replace(/<script(.|\s)*?\/script>/g,function(u){q[t]=u;return"jquery-writeCapture-script-placeholder-"+(t++)+"-wc"})).find(r).html().replace(e,function(u,v){return q[v]})}function j(q){throw"invalid method parameter "+q}g.writeCapture=d})(jQuery,writeCapture.noConflict());
11416 * Amplify Store - Persistent Client-Side Storage 1.0.0
11418 * Copyright 2011 appendTo LLC. (http://appendto.com/team)
11419 * Dual licensed under the MIT or GPL licenses.
11420 * http://appendto.com/open-source-licenses
11422 * http://amplifyjs.com
11424 (function( amplify, undefined ) {
11426 var store = amplify.store = function( key, value, options, type ) {
11427 var type = store.type;
11428 if ( options && options.type && options.type in store.types ) {
11429 type = options.type;
11431 return store.types[ type ]( key, value, options || {} );
11436 store.addType = function( type, storage ) {
11437 if ( !store.type ) {
11441 store.types[ type ] = storage;
11442 store[ type ] = function( key, value, options ) {
11443 options = options || {};
11444 options.type = type;
11445 return store( key, value, options );
11448 store.error = function() {
11449 return "amplify.store quota exceeded";
11452 var rprefix = /^__amplify__/;
11453 function createFromStorageInterface( storageType, storage ) {
11454 store.addType( storageType, function( key, value, options ) {
11455 var storedValue, parsed, i, remove,
11457 now = (new Date()).getTime();
11464 // accessing the length property works around a localStorage bug
11465 // in Firefox 4.0 where the keys don't update cross-page
11466 // we assign to key just to avoid Closure Compiler from removing
11467 // the access as "useless code"
11468 // https://bugzilla.mozilla.org/show_bug.cgi?id=662511
11469 key = storage.length;
11471 while ( key = storage.key( i++ ) ) {
11472 if ( rprefix.test( key ) ) {
11473 parsed = JSON.parse( storage.getItem( key ) );
11474 if ( parsed.expires && parsed.expires <= now ) {
11475 remove.push( key );
11477 ret[ key.replace( rprefix, "" ) ] = parsed.data;
11481 while ( key = remove.pop() ) {
11482 storage.removeItem( key );
11484 } catch ( error ) {}
11488 // protect against name collisions with direct storage
11489 key = "__amplify__" + key;
11491 if ( value === undefined ) {
11492 storedValue = storage.getItem( key );
11493 parsed = storedValue ? JSON.parse( storedValue ) : { expires: -1 };
11494 if ( parsed.expires && parsed.expires <= now ) {
11495 storage.removeItem( key );
11497 return parsed.data;
11500 if ( value === null ) {
11501 storage.removeItem( key );
11503 parsed = JSON.stringify({
11505 expires: options.expires ? now + options.expires : null
11508 storage.setItem( key, parsed );
11511 // expire old data and try again
11512 store[ storageType ]();
11514 storage.setItem( key, parsed );
11516 throw store.error();
11526 // localStorage + sessionStorage
11527 // IE 8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+, iPhone 2+, Android 2+
11528 for ( var webStorageType in { localStorage: 1, sessionStorage: 1 } ) {
11529 // try/catch for file protocol in Firefox
11531 if ( window[ webStorageType ].getItem ) {
11532 createFromStorageInterface( webStorageType, window[ webStorageType ] );
11538 // non-standard: Firefox 2+
11539 // https://developer.mozilla.org/en/dom/storage#globalStorage
11540 if ( window.globalStorage ) {
11541 // try/catch for file protocol in Firefox
11543 createFromStorageInterface( "globalStorage",
11544 window.globalStorage[ window.location.hostname ] );
11545 // Firefox 2.0 and 3.0 have sessionStorage and globalStorage
11546 // make sure we default to globalStorage
11547 // but don't default to globalStorage in 3.5+ which also has localStorage
11548 if ( store.type === "sessionStorage" ) {
11549 store.type = "globalStorage";
11555 // non-standard: IE 5+
11556 // http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx
11558 // IE 9 has quirks in userData that are a huge pain
11559 // rather than finding a way to detect these quirks
11560 // we just don't register userData if we have localStorage
11561 if ( store.types.localStorage ) {
11565 // append to html instead of body so we can do this from the head
11566 var div = document.createElement( "div" ),
11567 attrKey = "amplify";
11568 div.style.display = "none";
11569 document.getElementsByTagName( "head" )[ 0 ].appendChild( div );
11570 if ( div.addBehavior ) {
11571 div.addBehavior( "#default#userdata" );
11573 store.addType( "userData", function( key, value, options ) {
11574 div.load( attrKey );
11575 var attr, parsed, prevValue, i, remove,
11577 now = (new Date()).getTime();
11583 while ( attr = div.XMLDocument.documentElement.attributes[ i++ ] ) {
11584 parsed = JSON.parse( attr.value );
11585 if ( parsed.expires && parsed.expires <= now ) {
11586 remove.push( attr.name );
11588 ret[ attr.name ] = parsed.data;
11591 while ( key = remove.pop() ) {
11592 div.removeAttribute( key );
11594 div.save( attrKey );
11598 // convert invalid characters to dashes
11599 // http://www.w3.org/TR/REC-xml/#NT-Name
11600 // simplified to assume the starting character is valid
11601 // also removed colon as it is invalid in HTML attribute names
11602 //key = key.replace( /[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g, "-" );
11604 if ( value === undefined ) {
11605 attr = div.getAttribute( key );
11606 parsed = attr ? JSON.parse( attr ) : { expires: -1 };
11607 if ( parsed.expires && parsed.expires <= now ) {
11608 div.removeAttribute( key );
11610 return parsed.data;
11613 if ( value === null ) {
11614 div.removeAttribute( key );
11616 // we need to get the previous value in case we need to rollback
11617 prevValue = div.getAttribute( key );
11618 parsed = JSON.stringify({
11620 expires: (options.expires ? (now + options.expires) : null)
11622 div.setAttribute( key, parsed );
11627 div.save( attrKey );
11629 } catch ( error ) {
11630 // roll the value back to the previous value
11631 if ( prevValue === null ) {
11632 div.removeAttribute( key );
11634 div.setAttribute( key, prevValue );
11637 // expire old data and try again
11640 div.setAttribute( key, parsed );
11641 div.save( attrKey );
11642 } catch ( error ) {
11643 // roll the value back to the previous value
11644 if ( prevValue === null ) {
11645 div.removeAttribute( key );
11647 div.setAttribute( key, prevValue );
11649 throw store.error();
11657 // in-memory storage
11658 // fallback for all browsers to enable the API even if we can't persist data
11662 function copy( obj ) {
11663 return obj === undefined ? undefined : JSON.parse( JSON.stringify( obj ) );
11666 store.addType( "memory", function( key, value, options ) {
11668 return copy( memory );
11671 if ( value === undefined ) {
11672 return copy( memory[ key ] );
11675 if ( value === null ) {
11676 delete memory[ key ];
11680 memory[ key ] = value;
11681 if ( options.expires ) {
11682 setTimeout(function() {
11683 delete memory[ key ];
11684 }, options.expires );
11691 }( this.amplify = this.amplify || {} ) );
11695 * http://www.modernizr.com
11697 * Copyright (c) 2009-2011 Faruk Ates, Paul Irish, Alex Sexton
11698 * Dual-licensed under the BSD or MIT licenses: www.modernizr.com/license/
11702 * Modernizr tests which native CSS3 and HTML5 features are available in
11703 * the current UA and makes the results available to you in two ways:
11704 * as properties on a global Modernizr object, and as classes on the
11705 * <html> element. This information allows you to progressively enhance
11706 * your pages with a granular level of control over the experience.
11708 * Modernizr has an optional (not included) conditional resource loader
11709 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
11710 * To get a build that includes Modernizr.load(), as well as choosing
11711 * which tests to include, go to www.modernizr.com/download/
11713 * Authors Faruk Ates, Paul Irish, Alex Sexton,
11714 * Contributors Ryan Seddon, Ben Alman
11717 window.Modernizr = (function( window, document, undefined ) {
11719 var version = '2.0.6',
11723 // option for enabling the HTML classes to be added
11724 enableClasses = true,
11726 docElement = document.documentElement,
11727 docHead = document.head || document.getElementsByTagName('head')[0],
11730 * Create our "modernizr" element that we do most feature tests on.
11733 modElem = document.createElement(mod),
11734 mStyle = modElem.style,
11737 * Create the input element for various Web Forms feature tests.
11739 inputElem = document.createElement('input'),
11743 toString = Object.prototype.toString,
11745 // List of property values to set for css tests. See ticket #21
11746 prefixes = ' -webkit- -moz- -o- -ms- -khtml- '.split(' '),
11748 // Following spec is to expose vendor-specific style properties as:
11749 // elem.style.WebkitBorderRadius
11750 // and the following would be incorrect:
11751 // elem.style.webkitBorderRadius
11753 // Webkit ghosts their properties in lowercase but Opera & Moz do not.
11754 // Microsoft foregoes prefixes entirely <= IE8, but appears to
11755 // use a lowercase `ms` instead of the correct `Ms` in IE9
11757 // More here: http://github.com/Modernizr/Modernizr/issues/issue/21
11758 domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
11760 ns = {'svg': 'http://www.w3.org/2000/svg'},
11768 featureName, // used in testing loop
11771 // Inject element with style element and some CSS rules
11772 injectElementWithStyles = function( rule, callback, nodes, testnames ) {
11774 var style, ret, node,
11775 div = document.createElement('div');
11777 if ( parseInt(nodes, 10) ) {
11778 // In order not to give false positives we create a node for each test
11779 // This also allows the method to scale for unspecified uses
11780 while ( nodes-- ) {
11781 node = document.createElement('div');
11782 node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
11783 div.appendChild(node);
11787 // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed
11788 // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element
11789 // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.
11790 // http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
11791 style = ['­', '<style>', rule, '</style>'].join('');
11793 div.innerHTML += style;
11794 docElement.appendChild(div);
11796 ret = callback(div, rule);
11797 div.parentNode.removeChild(div);
11804 // adapted from matchMedia polyfill
11805 // by Scott Jehl and Paul Irish
11806 // gist.github.com/786768
11807 testMediaQuery = function( mq ) {
11809 if ( window.matchMedia ) {
11810 return matchMedia(mq).matches;
11815 injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
11816 bool = (window.getComputedStyle ?
11817 getComputedStyle(node, null) :
11818 node.currentStyle)['position'] == 'absolute';
11827 * isEventSupported determines if a given element supports the given event
11828 * function from http://yura.thinkweb2.com/isEventSupported/
11830 isEventSupported = (function() {
11833 'select': 'input', 'change': 'input',
11834 'submit': 'form', 'reset': 'form',
11835 'error': 'img', 'load': 'img', 'abort': 'img'
11838 function isEventSupported( eventName, element ) {
11840 element = element || document.createElement(TAGNAMES[eventName] || 'div');
11841 eventName = 'on' + eventName;
11843 // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
11844 var isSupported = eventName in element;
11846 if ( !isSupported ) {
11847 // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
11848 if ( !element.setAttribute ) {
11849 element = document.createElement('div');
11851 if ( element.setAttribute && element.removeAttribute ) {
11852 element.setAttribute(eventName, '');
11853 isSupported = is(element[eventName], 'function');
11855 // If property was created, "remove it" (by setting value to `undefined`)
11856 if ( !is(element[eventName], undefined) ) {
11857 element[eventName] = undefined;
11859 element.removeAttribute(eventName);
11864 return isSupported;
11866 return isEventSupported;
11869 // hasOwnProperty shim by kangax needed for Safari 2.0 support
11870 var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty;
11871 if ( !is(_hasOwnProperty, undefined) && !is(_hasOwnProperty.call, undefined) ) {
11872 hasOwnProperty = function (object, property) {
11873 return _hasOwnProperty.call(object, property);
11877 hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
11878 return ((property in object) && is(object.constructor.prototype[property], undefined));
11883 * setCss applies given styles to the Modernizr DOM node.
11885 function setCss( str ) {
11886 mStyle.cssText = str;
11890 * setCssAll extrapolates all vendor-specific css strings.
11892 function setCssAll( str1, str2 ) {
11893 return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
11897 * is returns a boolean for if typeof obj is exactly type.
11899 function is( obj, type ) {
11900 return typeof obj === type;
11904 * contains returns a boolean for if substr is found within str.
11906 function contains( str, substr ) {
11907 return !!~('' + str).indexOf(substr);
11911 * testProps is a generic CSS / DOM property test; if a browser supports
11912 * a certain property, it won't return undefined for it.
11913 * A supported CSS property returns empty string when its not yet set.
11915 function testProps( props, prefixed ) {
11916 for ( var i in props ) {
11917 if ( mStyle[ props[i] ] !== undefined ) {
11918 return prefixed == 'pfx' ? props[i] : true;
11925 * testPropsAll tests a list of DOM properties we want to check against.
11926 * We specify literally ALL possible (known and/or likely) properties on
11927 * the element including the non-vendor prefixed one, for forward-
11930 function testPropsAll( prop, prefixed ) {
11932 var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1),
11933 props = (prop + ' ' + domPrefixes.join(ucProp + ' ') + ucProp).split(' ');
11935 return testProps(props, prefixed);
11939 * testBundle tests a list of CSS features that require element and style injection.
11940 * By bundling them together we can reduce the need to touch the DOM multiple times.
11943 var testBundle = (function( styles, tests ) {
11944 var style = styles.join(''),
11945 len = tests.length;
11947 injectElementWithStyles(style, function( node, rule ) {
11948 var style = document.styleSheets[document.styleSheets.length - 1],
11949 // IE8 will bork if you create a custom build that excludes both fontface and generatedcontent tests.
11950 // So we check for cssRules and that there is a rule available
11951 // More here: https://github.com/Modernizr/Modernizr/issues/288 & https://github.com/Modernizr/Modernizr/issues/293
11952 cssText = style.cssRules && style.cssRules[0] ? style.cssRules[0].cssText : style.cssText || "",
11953 children = node.childNodes, hash = {};
11956 hash[children[len].id] = children[len];
11959 /*>>touch*/ Modernizr['touch'] = ('ontouchstart' in window) || hash['touch'].offsetTop === 9; /*>>touch*/
11960 /*>>csstransforms3d*/ Modernizr['csstransforms3d'] = hash['csstransforms3d'].offsetLeft === 9; /*>>csstransforms3d*/
11961 /*>>generatedcontent*/Modernizr['generatedcontent'] = hash['generatedcontent'].offsetHeight >= 1; /*>>generatedcontent*/
11962 /*>>fontface*/ Modernizr['fontface'] = /src/i.test(cssText) &&
11963 cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/
11967 // Pass in styles to be injected into document
11968 /*>>fontface*/ '@font-face {font-family:"font";src:url("https://")}' /*>>fontface*/
11970 /*>>touch*/ ,['@media (',prefixes.join('touch-enabled),('),mod,')',
11971 '{#touch{top:9px;position:absolute}}'].join('') /*>>touch*/
11973 /*>>csstransforms3d*/ ,['@media (',prefixes.join('transform-3d),('),mod,')',
11974 '{#csstransforms3d{left:9px;position:absolute}}'].join('')/*>>csstransforms3d*/
11976 /*>>generatedcontent*/,['#generatedcontent:after{content:"',smile,'";visibility:hidden}'].join('') /*>>generatedcontent*/
11979 /*>>fontface*/ 'fontface' /*>>fontface*/
11980 /*>>touch*/ ,'touch' /*>>touch*/
11981 /*>>csstransforms3d*/ ,'csstransforms3d' /*>>csstransforms3d*/
11982 /*>>generatedcontent*/,'generatedcontent' /*>>generatedcontent*/
11984 ]);/*>>testBundle*/
11992 tests['flexbox'] = function() {
11994 * setPrefixedValueCSS sets the property of a specified element
11995 * adding vendor prefixes to the VALUE of the property.
11996 * @param {Element} element
11997 * @param {string} property The property name. This will not be prefixed.
11998 * @param {string} value The value of the property. This WILL be prefixed.
11999 * @param {string=} extra Additional CSS to append unmodified to the end of
12002 function setPrefixedValueCSS( element, property, value, extra ) {
12004 element.style.cssText = (property + prefixes.join(value + ';' + property)).slice(0, -property.length) + (extra || '');
12008 * setPrefixedPropertyCSS sets the property of a specified element
12009 * adding vendor prefixes to the NAME of the property.
12010 * @param {Element} element
12011 * @param {string} property The property name. This WILL be prefixed.
12012 * @param {string} value The value of the property. This will not be prefixed.
12013 * @param {string=} extra Additional CSS to append unmodified to the end of
12016 function setPrefixedPropertyCSS( element, property, value, extra ) {
12017 element.style.cssText = prefixes.join(property + ':' + value + ';') + (extra || '');
12020 var c = document.createElement('div'),
12021 elem = document.createElement('div');
12023 setPrefixedValueCSS(c, 'display', 'box', 'width:42px;padding:0;');
12024 setPrefixedPropertyCSS(elem, 'box-flex', '1', 'width:10px;');
12026 c.appendChild(elem);
12027 docElement.appendChild(c);
12029 var ret = elem.offsetWidth === 42;
12031 c.removeChild(elem);
12032 docElement.removeChild(c);
12037 // On the S60 and BB Storm, getContext exists, but always returns undefined
12038 // http://github.com/Modernizr/Modernizr/issues/issue/97/
12040 tests['canvas'] = function() {
12041 var elem = document.createElement('canvas');
12042 return !!(elem.getContext && elem.getContext('2d'));
12045 tests['canvastext'] = function() {
12046 return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
12049 // This WebGL test may false positive.
12050 // But really it's quite impossible to know whether webgl will succeed until after you create the context.
12051 // You might have hardware that can support a 100x100 webgl canvas, but will not support a 1000x1000 webgl
12052 // canvas. So this feature inference is weak, but intentionally so.
12054 // It is known to false positive in FF4 with certain hardware and the iPad 2.
12056 tests['webgl'] = function() {
12057 return !!window.WebGLRenderingContext;
12061 * The Modernizr.touch test only indicates if the browser supports
12062 * touch events, which does not necessarily reflect a touchscreen
12063 * device, as evidenced by tablets running Windows 7 or, alas,
12064 * the Palm Pre / WebOS (touch) phones.
12066 * Additionally, Chrome (desktop) used to lie about its support on this,
12067 * but that has since been rectified: http://crbug.com/36415
12069 * We also test for Firefox 4 Multitouch Support.
12071 * For more info, see: http://modernizr.github.com/Modernizr/touch.html
12074 tests['touch'] = function() {
12075 return Modernizr['touch'];
12079 * geolocation tests for the new Geolocation API specification.
12080 * This test is a standards compliant-only test; for more complete
12081 * testing, including a Google Gears fallback, please see:
12082 * http://code.google.com/p/geo-location-javascript/
12083 * or view a fallback solution using google's geo API:
12084 * http://gist.github.com/366184
12086 tests['geolocation'] = function() {
12087 return !!navigator.geolocation;
12091 // This used to be Modernizr.crosswindowmessaging but the longer
12092 // name has been deprecated in favor of a shorter and property-matching one.
12093 // The old API is still available in 1.6, but as of 2.0 will throw a warning,
12094 // and in the first release thereafter disappear entirely.
12095 tests['postmessage'] = function() {
12096 return !!window.postMessage;
12099 // Web SQL database detection is tricky:
12101 // In chrome incognito mode, openDatabase is truthy, but using it will
12102 // throw an exception: http://crbug.com/42380
12103 // We can create a dummy database, but there is no way to delete it afterwards.
12105 // Meanwhile, Safari users can get prompted on any database creation.
12106 // If they do, any page with Modernizr will give them a prompt:
12107 // http://github.com/Modernizr/Modernizr/issues/closed#issue/113
12109 // We have chosen to allow the Chrome incognito false positive, so that Modernizr
12110 // doesn't litter the web with these test databases. As a developer, you'll have
12111 // to account for this gotcha yourself.
12112 tests['websqldatabase'] = function() {
12113 var result = !!window.openDatabase;
12116 result = !!openDatabase( mod + "testdb", "1.0", mod + "testdb", 2e4);
12123 // Vendors had inconsistent prefixing with the experimental Indexed DB:
12124 // - Webkit's implementation is accessible through webkitIndexedDB
12125 // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
12126 // For speed, we don't test the legacy (and beta-only) indexedDB
12127 tests['indexedDB'] = function() {
12128 for ( var i = -1, len = domPrefixes.length; ++i < len; ){
12129 if ( window[domPrefixes[i].toLowerCase() + 'IndexedDB'] ){
12133 return !!window.indexedDB;
12136 // documentMode logic from YUI to filter out IE8 Compat Mode
12137 // which false positives.
12138 tests['hashchange'] = function() {
12139 return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
12143 // This used to be Modernizr.historymanagement but the longer
12144 // name has been deprecated in favor of a shorter and property-matching one.
12145 // The old API is still available in 1.6, but as of 2.0 will throw a warning,
12146 // and in the first release thereafter disappear entirely.
12147 tests['history'] = function() {
12148 return !!(window.history && history.pushState);
12151 tests['draganddrop'] = function() {
12152 return isEventSupported('dragstart') && isEventSupported('drop');
12155 // Mozilla is targeting to land MozWebSocket for FF6
12156 // bugzil.la/659324
12157 tests['websockets'] = function() {
12158 for ( var i = -1, len = domPrefixes.length; ++i < len; ){
12159 if ( window[domPrefixes[i] + 'WebSocket'] ){
12163 return 'WebSocket' in window;
12167 // http://css-tricks.com/rgba-browser-support/
12168 tests['rgba'] = function() {
12169 // Set an rgba() color and check the returned value
12171 setCss('background-color:rgba(150,255,150,.5)');
12173 return contains(mStyle.backgroundColor, 'rgba');
12176 tests['hsla'] = function() {
12177 // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
12178 // except IE9 who retains it as hsla
12180 setCss('background-color:hsla(120,40%,100%,.5)');
12182 return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
12185 tests['multiplebgs'] = function() {
12186 // Setting multiple images AND a color on the background shorthand property
12187 // and then querying the style.background property value for the number of
12188 // occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
12190 setCss('background:url(https://),url(https://),red url(https://)');
12192 // If the UA supports multiple backgrounds, there should be three occurrences
12193 // of the string "url(" in the return value for elemStyle.background
12195 return /(url\s*\(.*?){3}/.test(mStyle.background);
12199 // In testing support for a given CSS property, it's legit to test:
12200 // `elem.style[styleName] !== undefined`
12201 // If the property is supported it will return an empty string,
12202 // if unsupported it will return undefined.
12204 // We'll take advantage of this quick test and skip setting a style
12205 // on our modernizr element, but instead just testing undefined vs
12209 tests['backgroundsize'] = function() {
12210 return testPropsAll('backgroundSize');
12213 tests['borderimage'] = function() {
12214 return testPropsAll('borderImage');
12218 // Super comprehensive table about all the unique implementations of
12219 // border-radius: http://muddledramblings.com/table-of-css3-border-radius-compliance
12221 tests['borderradius'] = function() {
12222 return testPropsAll('borderRadius');
12225 // WebOS unfortunately false positives on this test.
12226 tests['boxshadow'] = function() {
12227 return testPropsAll('boxShadow');
12230 // FF3.0 will false positive on this test
12231 tests['textshadow'] = function() {
12232 return document.createElement('div').style.textShadow === '';
12236 tests['opacity'] = function() {
12237 // Browsers that actually have CSS Opacity implemented have done so
12238 // according to spec, which means their return values are within the
12239 // range of [0.0,1.0] - including the leading zero.
12241 setCssAll('opacity:.55');
12243 // The non-literal . in this regex is intentional:
12244 // German Chrome returns this value as 0,55
12245 // https://github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
12246 return /^0.55$/.test(mStyle.opacity);
12250 tests['cssanimations'] = function() {
12251 return testPropsAll('animationName');
12255 tests['csscolumns'] = function() {
12256 return testPropsAll('columnCount');
12260 tests['cssgradients'] = function() {
12262 * For CSS Gradients syntax, please see:
12263 * http://webkit.org/blog/175/introducing-css-gradients/
12264 * https://developer.mozilla.org/en/CSS/-moz-linear-gradient
12265 * https://developer.mozilla.org/en/CSS/-moz-radial-gradient
12266 * http://dev.w3.org/csswg/css3-images/#gradients-
12269 var str1 = 'background-image:',
12270 str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
12271 str3 = 'linear-gradient(left top,#9f9, white);';
12274 (str1 + prefixes.join(str2 + str1) + prefixes.join(str3 + str1)).slice(0, -str1.length)
12277 return contains(mStyle.backgroundImage, 'gradient');
12281 tests['cssreflections'] = function() {
12282 return testPropsAll('boxReflect');
12286 tests['csstransforms'] = function() {
12287 return !!testProps(['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']);
12291 tests['csstransforms3d'] = function() {
12293 var ret = !!testProps(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']);
12295 // Webkit’s 3D transforms are passed off to the browser's own graphics renderer.
12296 // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
12297 // some conditions. As a result, Webkit typically recognizes the syntax but
12298 // will sometimes throw a false positive, thus we must do a more thorough check:
12299 if ( ret && 'webkitPerspective' in docElement.style ) {
12301 // Webkit allows this media query to succeed only if the feature is enabled.
12302 // `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }`
12303 ret = Modernizr['csstransforms3d'];
12309 tests['csstransitions'] = function() {
12310 return testPropsAll('transitionProperty');
12315 // @font-face detection routine by Diego Perini
12316 // http://javascript.nwbox.com/CSSSupport/
12317 tests['fontface'] = function() {
12318 return Modernizr['fontface'];
12322 // CSS generated content detection
12323 tests['generatedcontent'] = function() {
12324 return Modernizr['generatedcontent'];
12329 // These tests evaluate support of the video/audio elements, as well as
12330 // testing what types of content they support.
12332 // We're using the Boolean constructor here, so that we can extend the value
12333 // e.g. Modernizr.video // true
12334 // Modernizr.video.ogg // 'probably'
12336 // Codec values from : http://github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
12337 // thx to NielsLeenheer and zcorpan
12339 // Note: in FF 3.5.1 and 3.5.0, "no" was a return value instead of empty string.
12340 // Modernizr does not normalize for that.
12342 tests['video'] = function() {
12343 var elem = document.createElement('video'),
12346 // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
12348 if ( bool = !!elem.canPlayType ) {
12349 bool = new Boolean(bool);
12350 bool.ogg = elem.canPlayType('video/ogg; codecs="theora"');
12352 // Workaround required for IE9, which doesn't report video support without audio codec specified.
12353 // bug 599718 @ msft connect
12354 var h264 = 'video/mp4; codecs="avc1.42E01E';
12355 bool.h264 = elem.canPlayType(h264 + '"') || elem.canPlayType(h264 + ', mp4a.40.2"');
12357 bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"');
12365 tests['audio'] = function() {
12366 var elem = document.createElement('audio'),
12370 if ( bool = !!elem.canPlayType ) {
12371 bool = new Boolean(bool);
12372 bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"');
12373 bool.mp3 = elem.canPlayType('audio/mpeg;');
12375 // Mimetypes accepted:
12376 // https://developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
12377 // http://bit.ly/iphoneoscodecs
12378 bool.wav = elem.canPlayType('audio/wav; codecs="1"');
12379 bool.m4a = elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;');
12387 // Firefox has made these tests rather unfun.
12389 // In FF4, if disabled, window.localStorage should === null.
12391 // Normally, we could not test that directly and need to do a
12392 // `('localStorage' in window) && ` test first because otherwise Firefox will
12393 // throw http://bugzil.la/365772 if cookies are disabled
12395 // However, in Firefox 4 betas, if dom.storage.enabled == false, just mentioning
12396 // the property will throw an exception. http://bugzil.la/599479
12397 // This looks to be fixed for FF4 Final.
12399 // Because we are forced to try/catch this, we'll go aggressive.
12401 // FWIW: IE8 Compat mode supports these features completely:
12402 // http://www.quirksmode.org/dom/html5.html
12403 // But IE8 doesn't support either with local files
12405 tests['localstorage'] = function() {
12407 return !!localStorage.getItem;
12413 tests['sessionstorage'] = function() {
12415 return !!sessionStorage.getItem;
12422 tests['webworkers'] = function() {
12423 return !!window.Worker;
12427 tests['applicationcache'] = function() {
12428 return !!window.applicationCache;
12432 // Thanks to Erik Dahlstrom
12433 tests['svg'] = function() {
12434 return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
12437 // specifically for SVG inline in HTML, not within XHTML
12438 // test page: paulirish.com/demo/inline-svg
12439 tests['inlinesvg'] = function() {
12440 var div = document.createElement('div');
12441 div.innerHTML = '<svg/>';
12442 return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
12445 // Thanks to F1lt3r and lucideer, ticket #35
12446 tests['smil'] = function() {
12447 return !!document.createElementNS && /SVG/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
12450 tests['svgclippaths'] = function() {
12451 // Possibly returns a false positive in Safari 3.2?
12452 return !!document.createElementNS && /SVG/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
12455 // input features and input types go directly onto the ret object, bypassing the tests loop.
12456 // Hold this guy to execute in a moment.
12457 function webforms() {
12458 // Run through HTML5's new input attributes to see if the UA understands any.
12459 // We're using f which is the <input> element created early on
12460 // Mike Taylr has created a comprehensive resource for testing these attributes
12461 // when applied to all input types:
12462 // http://miketaylr.com/code/input-type-attr.html
12463 // spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
12465 // Only input placeholder is tested while textarea's placeholder is not.
12466 // Currently Safari 4 and Opera 11 have support only for the input placeholder
12467 // Both tests are available in feature-detects/forms-placeholder.js
12468 Modernizr['input'] = (function( props ) {
12469 for ( var i = 0, len = props.length; i < len; i++ ) {
12470 attrs[ props[i] ] = !!(props[i] in inputElem);
12473 })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
12475 // Run through HTML5's new input types to see if the UA understands any.
12476 // This is put behind the tests runloop because it doesn't return a
12477 // true/false like all the other tests; instead, it returns an object
12478 // containing each input type with its corresponding true/false value
12480 // Big thanks to @miketaylr for the html5 forms expertise. http://miketaylr.com/
12481 Modernizr['inputtypes'] = (function(props) {
12483 for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
12485 inputElem.setAttribute('type', inputElemType = props[i]);
12486 bool = inputElem.type !== 'text';
12488 // We first check to see if the type we give it sticks..
12489 // If the type does, we feed it a textual value, which shouldn't be valid.
12490 // If the value doesn't stick, we know there's input sanitization which infers a custom UI
12493 inputElem.value = smile;
12494 inputElem.style.cssText = 'position:absolute;visibility:hidden;';
12496 if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
12498 docElement.appendChild(inputElem);
12499 defaultView = document.defaultView;
12501 // Safari 2-4 allows the smiley as a value, despite making a slider
12502 bool = defaultView.getComputedStyle &&
12503 defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
12504 // Mobile android web browser has false positive, so must
12505 // check the height to see if the widget is actually there.
12506 (inputElem.offsetHeight !== 0);
12508 docElement.removeChild(inputElem);
12510 } else if ( /^(search|tel)$/.test(inputElemType) ){
12511 // Spec doesnt define any special parsing or detectable UI
12512 // behaviors so we pass these through as true
12514 // Interestingly, opera fails the earlier test, so it doesn't
12515 // even make it here.
12517 } else if ( /^(url|email)$/.test(inputElemType) ) {
12518 // Real url and email support comes with prebaked validation.
12519 bool = inputElem.checkValidity && inputElem.checkValidity() === false;
12521 } else if ( /^color$/.test(inputElemType) ) {
12522 // chuck into DOM and force reflow for Opera bug in 11.00
12523 // github.com/Modernizr/Modernizr/issues#issue/159
12524 docElement.appendChild(inputElem);
12525 docElement.offsetWidth;
12526 bool = inputElem.value != smile;
12527 docElement.removeChild(inputElem);
12530 // If the upgraded input compontent rejects the :) text, we got a winner
12531 bool = inputElem.value != smile;
12535 inputs[ props[i] ] = !!bool;
12538 })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
12542 // End of test definitions
12543 // -----------------------
12547 // Run through all tests and detect their support in the current UA.
12548 // todo: hypothetically we could be doing an array of tests and use a basic loop here.
12549 for ( var feature in tests ) {
12550 if ( hasOwnProperty(tests, feature) ) {
12551 // run the test, throw the return value into the Modernizr,
12552 // then based on that boolean, define an appropriate className
12553 // and push it into an array of classes we'll join later.
12554 featureName = feature.toLowerCase();
12555 Modernizr[featureName] = tests[feature]();
12557 classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
12561 // input tests need to run.
12562 Modernizr.input || webforms();
12566 * addTest allows the user to define their own feature tests
12567 * the result will be added onto the Modernizr object,
12568 * as well as an appropriate className set on the html element
12570 * @param feature - String naming the feature
12571 * @param test - Function returning true if feature is supported, false if not
12573 Modernizr.addTest = function ( feature, test ) {
12574 if ( typeof feature == "object" ) {
12575 for ( var key in feature ) {
12576 if ( hasOwnProperty( feature, key ) ) {
12577 Modernizr.addTest( key, feature[ key ] );
12582 feature = feature.toLowerCase();
12584 if ( Modernizr[feature] !== undefined ) {
12585 // we're going to quit if you're trying to overwrite an existing test
12586 // if we were to allow it, we'd do this:
12587 // var re = new RegExp("\\b(no-)?" + feature + "\\b");
12588 // docElement.className = docElement.className.replace( re, '' );
12589 // but, no rly, stuff 'em.
12593 test = typeof test == "boolean" ? test : !!test();
12595 docElement.className += ' ' + (test ? '' : 'no-') + feature;
12596 Modernizr[feature] = test;
12600 return Modernizr; // allow chaining.
12604 // Reset modElem.cssText to nothing to reduce memory footprint.
12606 modElem = inputElem = null;
12609 // Enable HTML 5 elements for styling (and printing) in IE.
12610 if ( window.attachEvent && (function(){ var elem = document.createElement('div');
12611 elem.innerHTML = '<elem></elem>';
12612 return elem.childNodes.length !== 1; })() ) {
12614 // iepp v2 by @jon_neal & afarkas : github.com/aFarkas/iepp/
12615 (function(win, doc) {
12616 win.iepp = win.iepp || {};
12617 var iepp = win.iepp,
12618 elems = iepp.html5elements || 'abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video',
12619 elemsArr = elems.split('|'),
12620 elemsArrLen = elemsArr.length,
12621 elemRegExp = new RegExp('(^|\\s)('+elems+')', 'gi'),
12622 tagRegExp = new RegExp('<(\/*)('+elems+')', 'gi'),
12623 filterReg = /^\s*[\{\}]\s*$/,
12624 ruleRegExp = new RegExp('(^|[^\\n]*?\\s)('+elems+')([^\\n]*)({[\\n\\w\\W]*?})', 'gi'),
12625 docFrag = doc.createDocumentFragment(),
12626 html = doc.documentElement,
12627 head = html.firstChild,
12628 bodyElem = doc.createElement('body'),
12629 styleElem = doc.createElement('style'),
12630 printMedias = /print|all/,
12632 function shim(doc) {
12634 while (++a < elemsArrLen)
12635 // Use createElement so IE allows HTML5-named elements in a document
12636 doc.createElement(elemsArr[a]);
12639 iepp.getCSS = function(styleSheetList, mediaType) {
12640 if(styleSheetList+'' === undefined){return '';}
12642 len = styleSheetList.length,
12645 while (++a < len) {
12646 styleSheet = styleSheetList[a];
12647 //currently no test for disabled/alternate stylesheets
12648 if(styleSheet.disabled){continue;}
12649 mediaType = styleSheet.media || mediaType;
12650 // Get css from all non-screen stylesheets and their imports
12651 if (printMedias.test(mediaType)) cssTextArr.push(iepp.getCSS(styleSheet.imports, mediaType), styleSheet.cssText);
12652 //reset mediaType to all with every new *not imported* stylesheet
12655 return cssTextArr.join('');
12658 iepp.parseCSS = function(cssText) {
12659 var cssTextArr = [],
12661 while ((rule = ruleRegExp.exec(cssText)) != null){
12662 // Replace all html5 element references with iepp substitute classnames
12663 cssTextArr.push(( (filterReg.exec(rule[1]) ? '\n' : rule[1]) +rule[2]+rule[3]).replace(elemRegExp, '$1.iepp_$2')+rule[4]);
12665 return cssTextArr.join('\n');
12668 iepp.writeHTML = function() {
12670 body = body || doc.body;
12671 while (++a < elemsArrLen) {
12672 var nodeList = doc.getElementsByTagName(elemsArr[a]),
12673 nodeListLen = nodeList.length,
12675 while (++b < nodeListLen)
12676 if (nodeList[b].className.indexOf('iepp_') < 0)
12677 // Append iepp substitute classnames to all html5 elements
12678 nodeList[b].className += ' iepp_'+elemsArr[a];
12680 docFrag.appendChild(body);
12681 html.appendChild(bodyElem);
12682 // Write iepp substitute print-safe document
12683 bodyElem.className = body.className;
12684 bodyElem.id = body.id;
12685 // Replace HTML5 elements with <font> which is print-safe and shouldn't conflict since it isn't part of html5
12686 bodyElem.innerHTML = body.innerHTML.replace(tagRegExp, '<$1font');
12690 iepp._beforePrint = function() {
12691 // Write iepp custom print CSS
12692 styleElem.styleSheet.cssText = iepp.parseCSS(iepp.getCSS(doc.styleSheets, 'all'));
12696 iepp.restoreHTML = function(){
12697 // Undo everything done in onbeforeprint
12698 bodyElem.innerHTML = '';
12699 html.removeChild(bodyElem);
12700 html.appendChild(body);
12703 iepp._afterPrint = function(){
12704 // Undo everything done in onbeforeprint
12705 iepp.restoreHTML();
12706 styleElem.styleSheet.cssText = '';
12711 // Shim the document and iepp fragment
12716 if(iepp.disablePP){return;}
12718 // Add iepp custom print style element
12719 head.insertBefore(styleElem, head.firstChild);
12720 styleElem.media = 'print';
12721 styleElem.className = 'iepp-printshim';
12730 })(window, document);
12734 // Assign private properties to the return object with prefix
12735 Modernizr._version = version;
12737 // expose these for the plugin API. Look in the source for how to join() them against your input
12738 Modernizr._prefixes = prefixes;
12739 Modernizr._domPrefixes = domPrefixes;
12741 // Modernizr.mq tests a given media query, live against the current state of the window
12742 // A few important notes:
12743 // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
12744 // * A max-width or orientation query will be evaluated against the current state, which may change later.
12745 // * You must specify values. Eg. If you are testing support for the min-width media query use:
12746 // Modernizr.mq('(min-width:0)')
12748 // Modernizr.mq('only screen and (max-width:768)')
12749 Modernizr.mq = testMediaQuery;
12751 // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
12752 // Modernizr.hasEvent('gesturestart', elem)
12753 Modernizr.hasEvent = isEventSupported;
12755 // Modernizr.testProp() investigates whether a given style property is recognized
12756 // Note that the property names must be provided in the camelCase variant.
12757 // Modernizr.testProp('pointerEvents')
12758 Modernizr.testProp = function(prop){
12759 return testProps([prop]);
12762 // Modernizr.testAllProps() investigates whether a given style property,
12763 // or any of its vendor-prefixed variants, is recognized
12764 // Note that the property names must be provided in the camelCase variant.
12765 // Modernizr.testAllProps('boxSizing')
12766 Modernizr.testAllProps = testPropsAll;
12770 // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
12771 // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
12772 Modernizr.testStyles = injectElementWithStyles;
12775 // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
12776 // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
12778 // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
12779 // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
12781 // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
12783 // If you're trying to ascertain which transition end event to bind to, you might do something like...
12785 // var transEndEventNames = {
12786 // 'WebkitTransition' : 'webkitTransitionEnd',
12787 // 'MozTransition' : 'transitionend',
12788 // 'OTransition' : 'oTransitionEnd',
12789 // 'msTransition' : 'msTransitionEnd', // maybe?
12790 // 'transition' : 'transitionEnd'
12792 // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
12794 Modernizr.prefixed = function(prop){
12795 return testPropsAll(prop, 'pfx');
12800 // Remove "no-js" class from <html> element, if it exists:
12801 docElement.className = docElement.className.replace(/\bno-js\b/, '')
12803 // Add the new classes to the <html> element.
12804 + (enableClasses ? ' js ' + classes.join(' ') : '');
12808 })(this, this.document);
12811 * Array prototype extensions.
\r
12812 * Extends array prototype with the following methods:
\r
12813 * contains, every, exfiltrate, filter, forEach, getRange, inArray, indexOf, insertAt, map, randomize, removeAt, some, unique
\r
12815 * This extensions doesn't depend on any other code or overwrite existing methods.
\r
12818 * Copyright (c) 2007 Harald Hanek (http://js-methods.googlecode.com)
\r
12820 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
\r
12821 * and GPL (http://www.gnu.org/licenses/gpl.html) licenses.
\r
12823 * @author Harald Hanek
\r
12825 * @lastchangeddate 10. October 2007 15:46:06
\r
12832 * Extend the array prototype with the method under the given name if it doesn't currently exist.
\r
12836 function append(name, method)
\r
12838 if(!Array.prototype[name])
\r
12839 Array.prototype[name] = method;
\r
12844 * Returns true if every element in 'elements' is in the array.
\r
12846 * @example [1, 2, 1, 4, 5, 4].contains([1, 2, 4]);
\r
12850 * @param Array elements
\r
12851 * @return Boolean
\r
12853 append("contains", function(elements){
\r
12854 return this.every(function(element){
\r
12855 return this.indexOf(element) >= 0; }, elements);
\r
12860 * Returns the array without the elements in 'elements'.
\r
12862 * @example [1, 2, 1, 4, 5, 4].contains([1, 2, 4]);
\r
12865 * @name exfiltrate
\r
12866 * @param Array elements
\r
12867 * @return Boolean
\r
12869 append("exfiltrate", function(elements){
\r
12870 return this.filter(function(element){
\r
12871 return this.indexOf(element) < 0; }, elements);
\r
12876 * Tests whether all elements in the array pass the test implemented by the provided function.
\r
12878 * @example [22, 72, 16, 99, 254].every(function(element, index, array) {
\r
12879 * return element >= 15;
\r
12883 * @example [12, 72, 16, 99, 254].every(function(element, index, array) {
\r
12884 * return element >= 15;
\r
12889 * @param Function fn The function to be called for each element.
\r
12890 * @param Object scope (optional) The scope of the function (defaults to this).
\r
12891 * @return Boolean
\r
12893 append("every", function(fn, scope){
\r
12894 for(var i = 0; i < this.length; i++)
\r
12895 if(!fn.call(scope || window, this[i], i, this))
\r
12902 * Creates a new array with all elements that pass the test implemented by the provided function.
\r
12904 * Natively supported in Gecko since version 1.8.
\r
12905 * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
\r
12907 * @example [12, 5, 8, 1, 44].filter(function(element, index, array) {
\r
12908 * return element >= 10;
\r
12910 * @result [12, 44];
\r
12913 * @param Function fn The function to be called for each element.
\r
12914 * @param Object scope (optional) The scope of the function (defaults to this).
\r
12917 append("filter", function(fn, scope){
\r
12919 for(var i = 0; i < this.length; i++)
\r
12920 if(fn.call(scope || window, this[i], i, this))
\r
12927 * Executes a provided function once per array element.
\r
12929 * Natively supported in Gecko since version 1.8.
\r
12930 * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
\r
12932 * @example var stuff = "";
\r
12933 * ["Java", "Script"].forEach(function(element, index, array) {
\r
12934 * stuff += element;
\r
12936 * @result "JavaScript";
\r
12939 * @param Function fn The function to be called for each element.
\r
12940 * @param Object scope (optional) The scope of the function (defaults to this).
\r
12943 append("forEach", function(fn, scope){
\r
12944 for(var i = 0; i < this.length; i++)
\r
12945 fn.call(scope || window, this[i], i, this);
\r
12950 * Returns a range of items in this collection
\r
12952 * @example [1, 2, 1, 4, 5, 4].getRange(2, 4);
\r
12953 * @result [1, 4, 5]
\r
12956 * @param Number startIndex (optional) defaults to 0
\r
12957 * @param Number endIndex (optional) default to the last item
\r
12960 append("getRange", function(start, end){
\r
12961 var items = this;
\r
12962 if(items.length < 1)
\r
12965 start = start || 0;
\r
12966 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
\r
12969 for(var i = start; i <= end; i++)
\r
12970 r[r.length] = items[i];
\r
12972 for(var i = start; i >= end; i--)
\r
12973 r[r.length] = items[i];
\r
12980 * Returns the first index at which a given element can be found in the array, or -1 if it is not present.
\r
12982 * @example [12, 5, 8, 5, 44].indexOf(5);
\r
12985 * @example [12, 5, 8, 5, 44].indexOf(5, 2);
\r
12989 * @param Object subject Object to search for
\r
12990 * @param Number offset (optional) Index at which to start searching
\r
12993 append("indexOf", function(subject, offset){
\r
12994 for(var i = offset || 0; i < this.length; i++)
\r
12995 if(this[i] === subject)
\r
13002 * Checks if a given subject can be found in the array.
\r
13004 * @example [12, 5, 7, 5].inArray(7);
\r
13007 * @example [12, 5, 7, 5].inArray(9);
\r
13011 * @param Object subject Object to search for
\r
13012 * @return Boolean
\r
13014 append("inArray", function(subject){
\r
13015 for(var i = 0; i < this.length; i++)
\r
13016 if(subject == this[i])
\r
13023 * Inserts an item at the specified index in the array.
\r
13025 * @example ['dog', 'cat', 'horse'].insertAt(2, 'mouse');
\r
13026 * @result ['dog', 'cat', 'mouse', 'horse']
\r
13029 * @param Number index Position where to insert the element into the array
\r
13030 * @param Object element The element to insert
\r
13033 append("insertAt", function(index, element){
\r
13034 for(var k = this.length; k > index; k--)
\r
13035 this[k] = this[k-1];
\r
13036 this[index] = element;
\r
13042 * Creates a new array with the results of calling a provided function on every element in this array.
\r
13044 * Natively supported in Gecko since version 1.8.
\r
13045 * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:map
\r
13047 * @example ["my", "Name", "is", "HARRY"].map(function(element, index, array) {
\r
13048 * return element.toUpperCase();
\r
13050 * @result ["MY", "NAME", "IS", "HARRY"];
\r
13052 * @example [1, 4, 9].map(Math.sqrt);
\r
13053 * @result [1, 2, 3];
\r
13056 * @param Function fn The function to be called for each element.
\r
13057 * @param Object scope (optional) The scope of the function (defaults to this).
\r
13060 append("map", function(fn, scope){
\r
13061 scope = scope || window;
\r
13063 for(var i = 0; i < this.length; i++)
\r
13064 r[r.length] = fn.call(scope, this[i], i, this);
\r
13070 * Remove an item from a specified index in the array.
\r
13072 * @example ['dog', 'cat', 'mouse', 'horse'].deleteAt(2);
\r
13073 * @result ['dog', 'cat', 'horse']
\r
13076 * @param Number index The index within the array of the item to remove.
\r
13079 append("removeAt", function(index){
\r
13080 for(var k = index; k < this.length-1; k++)
\r
13081 this[k] = this[k+1];
\r
13088 * Randomize the order of the elements in the Array.
\r
13090 * @example [2, 3, 4, 5].randomize();
\r
13091 * @result [5, 2, 3, 4] randomized result
\r
13093 * @name randomize
\r
13096 append("randomize", function(){
\r
13097 return this.sort(function(){return(Math.round(Math.random())-0.5)});
\r
13098 //return this.sort(function(){return(Math.round(Math.random())-0.5)}, true);
\r
13103 * Tests whether some element in the array passes the test implemented by the provided function.
\r
13105 * Natively supported in Gecko since version 1.8.
\r
13106 * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
\r
13108 * @example [101, 199, 250, 200].some(function(element, index, array) {
\r
13109 * return element >= 100;
\r
13113 * @example [101, 99, 250, 200].some(function(element, index, array) {
\r
13114 * return element >= 100;
\r
13119 * @param Function fn The function to be called for each element.
\r
13120 * @param Object scope (optional) The scope of the function (defaults to this).
\r
13121 * @return Boolean
\r
13123 append("some", function(fn, scope){
\r
13124 for(var i = 0; i < this.length; i++)
\r
13125 if(fn.call(scope || window, this[i], i, this))
\r
13132 * Returns a new array that contains all unique elements of this array.
\r
13134 * @example [1, 2, 1, 4, 5, 4].unique();
\r
13135 * @result [1, 2, 4, 5]
\r
13140 append("unique", function(){
\r
13141 return this.filter(function(element, index, array){
\r
13142 return array.indexOf(element) >= index;
\r
13150 Copyright 2011 The greplin-exception-catcher Authors.
13152 Licensed under the Apache License, Version 2.0 (the "License");
13153 you may not use this file except in compliance with the License.
13154 You may obtain a copy of the License at
13156 http://www.apache.org/licenses/LICENSE-2.0
13158 Unless required by applicable law or agreed to in writing, software
13159 distributed under the License is distributed on an "AS IS" BASIS,
13160 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13161 See the License for the specific language governing permissions and
13162 limitations under the License.
13165 This Javascript file lets web applications get stacktraces for all uncaught JS exceptions and send them to Greplin
13169 - Stacktraces in IE 6-8, as well as modern versions of Firefox, Chrome, and Opera
13170 - Javascript execution entry point information (such as event type and listener) on IE 6-9 and modern versions of
13171 Firefox, Chrome, Safari, and Opera
13172 - Redaction of URLs and strings in stacktraces to avoid logging sensitive user information
13174 Things that aren't done yet:
13175 - Aggregation. Due to the way GEC works now, this would be impossible to do without losing potentially useful
13176 information. To do this, GEC needs to be able to aggregate based upon a normalized stacktrace while still providing detailed information for each specific incident of the exception.
13177 - Can't wrap DOM0 events (<div onclick> for example).
13178 - Some code cleanup: Since this is a small, self-contained project, I took sort of a "hack it until it works" approach
13179 to coding it. I'd like to go back and structure the code better sometime, but I probably wont' get around to it
13180 anytime soon since it works very reliably as it is.
13183 1. Create an endpoint at your server to send this stuff to GEC.
13184 2. Modify the call to g.errorCatcher at the end of the file to pass in functions that pass exceptions to GEC and that
13185 redact URLs respectively. (Note: your URL redaction function will be passed strings that may contain URLs, not bare
13186 URLs, so keep that in mind)
13187 3. Wrap your JS files if you want to capture errors during their initial execution:
13188
try {
var your_js_here
}
13189 catch(e) { window.g && g.handleInitialException && g.handleInitialException(e, '(script filename here)') }
13190
If you use Closure Compiler, just do
13191 --output_wrapper="window.COMPILED = true; try { %%output%% } catch(e) { window.g && g.handleInitialException && g.handleInitialException(e, '(script filename here)') }"
13192 4. This exception catching script can't see exceptions that happen before it's loaded, so make sure it's loaded early in
13193 your page before most of your other scripts.
13201 * Captures uncaught JS exceptions on the page and passes them to GEC.
13202 * Can capture stacktraces in IE 6-8, Firefox, Chrome, and Opera, and can capture only the top of the stack in IE 9.
13203 * In Safari, only basic event information is captured.
13204 * Uses both window.onerror and wrapped DOM prototype interfaces to capture as much information as possible without
13205 * requiring JS code changes.
13207 g.errorCatcher = function(reportHandler, redactQueryStrings) {
13208 g.errorCatcher.reportHandler_ = reportHandler;
13209 g.errorCatcher.redactQueryStrings_ = redactQueryStrings;
13211 // commented out part is for weird cases where you have two exception catchers.
13212 // i haven't tested that case at all though, so i'm commenting it out for now.
13213 var wrappedProperty = 'WrappedListener'; //+ Math.floor(Math.random() * 10000000).toString(30);
13215 var supportsJsErrorStack;
13218 ({})['undefinedMethod']();
13220 supportsJsErrorStack = 'stack' in error || 'stacktrace' in error;
13223 var supportsWindowOnerror = 'onerror' in window && !/^Opera/.test(navigator.userAgent);
13225 var supportsWindowOnerrorStack = /MSIE /.test(navigator.userAgent);
13227 // Detecting support based on a whitelist sucks, but we don't want to accidentally log personal information, so we
13228 // only allow browsers that we know that we can redact stacktrace strings for.
13229 var supportsDOMWrapping =
13231 /Chrom(e|ium)/.test(navigator.userAgent) ||
13234 /MSIE (9\.|[1-9][0-9]+\.)/.test(navigator.userAgent) || // XXX compat mode?
13237 /Gecko\/[0-9]/.test(navigator.userAgent) && (parseInt(navigator['buildID'], 10) >= 20110830092941) ||
13239 // Safari 5.1+ (AppleWebKit/534+)
13240 /AppleWebKit\/(53[4-9]|5[4-9][0-9]|[6-9][0-9]{2}|[1-9][0-9]{3})/.test(navigator.userAgent) ||
13243 /^Opera.*Presto\/(2\.9|[3-9]|[1-9][0-9])/.test(navigator.userAgent);
13245 if (supportsDOMWrapping) {
13248 wrapXMLHttpRequest();
13251 if (supportsWindowOnerror &&
13252 (!supportsDOMWrapping || (!supportsJsErrorStack && supportsWindowOnerrorStack))) {
13253 window.onerror = function(errorMessage, url, lineNumber) {
13254 // Grab the error provided by DOM wrappings, if it's available
13255 var errorObject = g.errorCatcher.lastDomWrapperError_ || {};
13256 delete g.errorCatcher.lastDomWrapperError_;
13258 errorObject.message = errorObject.message || errorMessage;
13259 errorObject.url = errorObject.url || url;
13260 errorObject.line = errorObject.line || lineNumber;
13262 // In IE, get the character offset inside the line of the error from window.event.
13263 if (window.event && typeof window.event['errorCharacter'] == 'number') {
13264 errorObject.character = (errorObject.character || window.event['errorCharacter']) + '';
13267 // If there isn't already a stacktrace generated by the DOM wrappers, try to generate one using the old-fashioned
13268 // caller method. This only works in IE 6-8. It partially works in IE 9 -- but it only lets you get the top of the
13270 if (!errorObject.stacktrace && supportsWindowOnerrorStack) {
13272 errorObject.stacktrace = g.errorCatcher.getStacktrace(arguments.callee.caller);
13273 } catch(exception) {
13274 errorObject.stacktrace = '[error generating stacktrace: ' + exception.message + ']';
13278 g.errorCatcher.reportException(errorObject);
13283 * Wraps setTimeout and setInterval to handle uncaught exceptions in listeners.
13285 function wrapTimeouts() {
13286 wrapTimeoutsHelper('setTimeout');
13287 wrapTimeoutsHelper('setInterval');
13288 function wrapTimeoutsHelper(timeoutMethodName) {
13289 var original = window[timeoutMethodName];
13290 window[timeoutMethodName] = function(listener, delay) {
13291 if (typeof listener == 'function') {
13292 var newArgs = Array.prototype.slice.call(arguments);
13293 newArgs[0] = function() {
13295 listener.apply(this, arguments);
13296 } catch(exception) {
13297 g.errorCatcher.handleCatchException(
13298 exception, timeoutMethodName + '(' + g.errorCatcher.stringify(listener) + ', ' + delay + ')');
13301 return original.apply(this, newArgs);
13303 // If someone passes a string to setTimeout, don't bother wrapping it.
13304 return original.apply(this, arguments);
13312 * Wraps DOM event interfaces (addEventListener and removeEventListener) to add try/catch wrappers to all event
13315 function wrapDOMEvents() {
13316 var eventsWrappedProperty = 'events' + wrappedProperty;
13318 wrapDOMEventsHelper(window.XMLHttpRequest.prototype);
13319 wrapDOMEventsHelper(window.Element.prototype);
13320 wrapDOMEventsHelper(window);
13321 wrapDOMEventsHelper(window.document);
13323 // Workaround for Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=456151
13324 if (document.documentElement.addEventListener != window.Element.prototype.addEventListener) {
13326 ('Unknown,Anchor,Applet,Area,BR,Base,Body,Button,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,' +
13327 'FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,IsIndex,LI,Label,Legend,Link,Map,Menu,Meta,Span,OList,' +
13328 'Object,OptGroup,Option,Paragraph,Param,Pre,Quote,Script,Select,Style,TableCaption,TableCell,TableCol,' +
13329 'Table,TableRow,TableSection,TextArea,Title,UList,Canvas').split(',');
13330 elementNames.forEach(function(elementName) {
13331 var constructor = window['HTML' + elementName + 'Element'];
13332 if (constructor && constructor.prototype) {
13333 wrapDOMEventsHelper(constructor.prototype);
13339 function wrapDOMEventsHelper(object) {
13340 var originalAddEventListener = object.addEventListener;
13341 var originalRemoveEventListener = object.removeEventListener;
13342 if (!originalAddEventListener || !originalRemoveEventListener) {
13345 object.addEventListener = function(eventType, listener, useCapture) {
13346 // Dedupe the listener in case it is already listening unwrapped.
13347 originalRemoveEventListener.apply(this, arguments);
13348 if (typeof listener != 'function') {
13349 // TODO(david): Handle a listener that is not a function, but instead an object that implements the
13350 // EventListener interface (see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener ).
13351 originalAddEventListener.apply(this, arguments);
13354 listener[eventsWrappedProperty] = listener[eventsWrappedProperty] || {
13355 innerListener: listener,
13356 'handleEvent': g.errorCatcher.listenerWrapper_
13358 originalAddEventListener.call(this, eventType, listener[eventsWrappedProperty], useCapture);
13360 object.removeEventListener = function(eventType, listener, useCapture) {
13361 // Remove unwrapped listener, just to be sure.
13362 originalRemoveEventListener.apply(this, arguments);
13363 if (typeof listener != 'function') {
13366 if (listener[eventsWrappedProperty]) {
13367 originalRemoveEventListener.call(this, eventType, listener[eventsWrappedProperty], useCapture);
13375 * Wrap XMLHttpRequest onreadystatechange listeners to handle uncaught JS exceptions.
13376 * This only affects the .onreadystatechange property. The addEventListener property is handled by wrapDOMEvents.
13378 function wrapXMLHttpRequest() {
13379 var xhrWrappedProperty = 'xhr' + wrappedProperty;
13380 var ctor = XMLHttpRequest, instance = new XMLHttpRequest;
13381 if (!/(AppleWebKit|MSIE)/.test(navigator.userAgent) ||
13382 (Object.getOwnPropertyDescriptor(ctor.prototype, 'onreadystatechange') || {}).configurable &&
13383 instance.__lookupSetter__ && instance.__lookupSetter__('onreadystatechange')) {
13384 // The browser has good support for manipulating XMLHttpRequest prototypes.
13385 var onreadystatechangeSetter = instance.__lookupSetter__('onreadystatechange');
13386 ctor.prototype.__defineGetter__('onreadystatechange', function() {
13387 return this[xhrWrappedProperty];
13389 ctor.prototype.__defineSetter__('onreadystatechange', function(listener) {
13390 this[xhrWrappedProperty] = listener;
13391 onreadystatechangeSetter.call(this, wrappedReadyStateChange);
13394 // Chrome and Safari have problems with this. Instead, check to see if onreadystatechange needs to be wrapped
13395 // from a readystatechange event listener.
13396 var send = instance.send;
13397 var addEventListener = instance.addEventListener;
13398 XMLHttpRequest.prototype.send = function() {
13399 addEventListener.call(this, 'readystatechange', wrapReadyStateChange, true);
13400 return send.apply(this, arguments);
13403 function wrappedReadyStateChange() {
13405 var onreadystatechange =
13406 (this.onreadystatechange == arguments.callee ?
13407 this[xhrWrappedProperty] : this.onreadystatechange);
13408 this[xhrWrappedProperty].apply(this, arguments);
13409 } catch(exception) {
13410 // TODO(david): Expose some information about the xmlhttprequest to the exception logging (maybe request url)
13411 g.errorCatcher.handleCatchException(exception, 'onreadystatechange');
13414 // Used in the wrapped XHR::send handler to wrap onreadystatechange in response to addEventListener
13415 // readystatechange events that fire first.
13416 function wrapReadyStateChange() {
13417 if (this.onreadystatechange && this.onreadystatechange != wrappedReadyStateChange) {
13418 this[xhrWrappedProperty] = this.onreadystatechange;
13419 this.onreadystatechange = wrappedReadyStateChange;
13427 * Time that the last error was reported. Used for rate-limiting.
13430 g.errorCatcher.lastError_ = 0;
13434 * Delay between reporting errors. Increases dynamically.
13437 g.errorCatcher.errorDelay_ = 10;
13441 * Wrapper for addEventListener/removeEventListener listeners. Global to avoid potential memory/performance impacts of a
13442 * function closure for each event listener. This is a handleEvent property of the EventHandler object passed to
13443 * addEventListener. It accesses other properties of that object to read exception information.
13444 * @param {Event} eventObject The DOM event.
13446 g.errorCatcher.listenerWrapper_ = function(eventObject) {
13448 return this.innerListener.apply(eventObject.target, arguments);
13449 } catch(exception) {
13450 g.errorCatcher.handleCatchException(
13451 exception, eventObject.type + ' listener ' + g.errorCatcher.stringify(this.innerListener) + ' on ' +
13452 g.errorCatcher.stringify(eventObject.currentTarget));
13458 * Passes an exception to GEC.
13459 * TODO(david): show a message to the user. Let the user elect to send more detailed error information (un-redacted
13461 * @param {Object} errorObject An object describing the error.
13463 g.errorCatcher.reportException = function(errorObject) {
13464 var d = (new Date).getTime();
13465 if (d - g.errorCatcher.lastError_ < g.errorCatcher.errorDelay_) {
13469 g.errorCatcher.lastError_ = d;
13470 g.errorCatcher.errorDelay_ = g.errorCatcher.errorDelay_ * 2;
13472 'msg':g.errorCatcher.redactQueryStrings_(errorObject.message || ''),
13473 'line': errorObject.line + (typeof errorObject.character == 'string' ? ':' + errorObject.character : ''),
13474 'trace':'Type: ' + errorObject.name + '\nUser-agent: ' + navigator.userAgent +
13475 '\nURL: ' + g.errorCatcher.redactQueryStrings_(location.href) + '\n\n' +
13476 g.errorCatcher.redactQueryStrings_(errorObject.stacktrace || ''),
13477 'ts': Math.floor(new Date().getTime() / 1000),
13478 'name':g.errorCatcher.redactQueryStrings_(errorObject.context || '') || 'unidentified JS thread'};
13479 g.errorCatcher.reportHandler_(errorObj);
13485 * Handles exceptions from the try { } catch { } block added around all of our compiled JS by our Closure Compiler
13486 * configuration. This handles exceptions that occur during the intiial execution of the script.
13487 * @param {Error} caughtException The caught exception.
13488 * @param {string} fileName The name of the JS file where the exception occured.
13490 g.errorCatcher.handleInitialException = function(caughtException, fileName) {
13491 g.errorCatcher.handleCatchException(caughtException, 'Initial execution of ' + fileName);
13496 * Handles a caught exception. When window.onerror is available, the exception is re-thrown so that additional
13497 * information from window.onerror can be added. Otherwise, the exception is passed to reportException, where it is
13498 * sent to GEC and potentially displayed to the user.
13499 * @param {Error} caughtException The caught JS exception.
13502 g.errorCatcher.handleCatchException = function(caughtException, context) {
13503 if (!(caughtException instanceof window.Error)) {
13504 caughtException = new Error(caughtException);
13507 var errorObject = {};
13508 errorObject.context = context;
13509 errorObject.name = caughtException.name;
13510 // Opera has both stacktrace and stack. Stacktrace is much more detailed, so use that when available.
13511 errorObject.stacktrace = caughtException['stacktrace'] || caughtException['stack'];
13512 if (/Gecko/.test(navigator.userAgent) && !/AppleWebKit/.test(navigator.userAgent)) {
13513 errorObject.stacktrace = g.errorCatcher.redactFirefoxStacktraceStrings(errorObject.stacktrace);
13515 errorObject.message = caughtException.message;
13516 errorObject.number = caughtException.number;
13519 if ('lineNumber' in caughtException) {
13520 errorObject.line = caughtException['lineNumber'];
13521 } else if ('line' in caughtException) {
13522 errorObject.line = caughtException['line'];
13523 } else if (/Chrom(e|ium)/.test(navigator.userAgent)) {
13524 matches = caughtException.stack.match(/\:(\d+)\:(\d+)\)(\n|$)/);
13526 errorObject.line = matches[1];
13527 errorObject.character = matches[2];
13529 } else if (/Opera/.test(navigator.userAgent)) {
13530 matches = (errorObject['stacktrace'] || '').match(/Error thrown at line (\d+), column (\d+)/);
13532 errorObject.line = matches[1];
13533 errorObject.character = matches[2];
13535 matches = (errorObject['stacktrace'] || '').match(/Error thrown at line (\d+)/);
13537 errorObject.line = matches[1];
13542 if (window.onerror) {
13543 // window.onerror is still needed to get stack in IE, so we need to re-throw the error to that.
13544 g.errorCatcher.lastDomWrapperError_ = errorObject;
13545 throw caughtException;
13547 g.errorCatcher.reportException(errorObject);
13553 * @param {Function} opt_topFunction The function at the top of the stack; if omitted, the caller of makeStacktrace is
13555 * @return {string} A string showing the stack of functions and arguments.
13557 g.errorCatcher.getStacktrace = function(opt_topFunction) {
13558 var stacktrace = '';
13559 var func = opt_topFunction || arguments.callee.caller;
13562 stacktraceLoop: do {
13563 stacktrace += g.errorCatcher.getFunctionName(func) + g.errorCatcher.getFunctionArgumentsString(func) + '\n';
13566 func = func.caller;
13567 for (var i = 0; i < used.length; i++) {
13568 if (used[i] == func) {
13569 stacktrace += g.errorCatcher.getFunctionName(func) + '(???)\n(...)\n';
13570 break stacktraceLoop;
13573 } catch(exception) {
13574 stacktrace += '(???' + exception.message + ')\n';
13575 break stacktraceLoop;
13578 stacktrace += '(...)\n';
13586 * @param {string} string The string to shorten.
13587 * @param {number} maxLength The maximum length of the new string.
13588 * @return {string} The string, shortened if it exceeds maxLength.
13590 g.errorCatcher.shortenString = function(string, maxLength) {
13591 if (string.length > maxLength) {
13592 string = string.substr(0, maxLength) + '...';
13599 * @param {Function} func The function to get the name of.
13600 * @return {string} The name of the function, or a snippet of the function's source code if it is an anonymous function.
13602 g.errorCatcher.getFunctionName = function(func) {
13605 if ('name' in Function.prototype && func.name) {
13608 var funcStr = func.toString();
13609 var matches = /function ([^\(]+)/.exec(funcStr);
13610 name = matches && matches[1] || '[anonymous function: ' + g.errorCatcher.shortenString(func.toString(), 90) + ']';
13612 } catch(exception) {
13613 name = '[inaccessible function]'
13620 * @param func The function to get a string describing the arguments for. Must be in the current callstack.
13621 * @return {string} A string of the arguments passed to the function.
13623 g.errorCatcher.getFunctionArgumentsString = function(func) {
13624 var argsStrings = [];
13626 var args = func.arguments;
13628 for (var i = 0, length = args.length; i < length; i++) {
13629 argsStrings.push(g.errorCatcher.stringify(args[i]));
13632 } catch(exception) {
13633 argsStrings.push('...?');
13635 return '(' + argsStrings.join(',') + ')';
13640 * Converts objects and primitives to strings describing them. String inputs are redacted.
13641 * @param {*} thing The object or primitive to describe.
13642 * @return {string} String describing the input.
13644 g.errorCatcher.stringify = function(thing) {
13645 var string = '[???]';
13647 var type = typeof thing;
13648 string = '[' + type + '?]';
13651 string = 'undefined';
13655 string = thing.toString();
13658 if (thing == null) {
13662 if (thing instanceof Date) {
13663 string = 'new Date("' + thing.toString() + '")';
13666 var toStringValue = thing.toString();
13667 if (/^\[[a-z ]*\]$/i.test(toStringValue)) {
13668 string = toStringValue;
13671 if (typeof thing.length == 'number') {
13672 string = '[arraylike object, length = ' + thing.length + ']';
13675 string = '[object]';
13678 string = '"' + g.errorCatcher.redactString(thing) + '"';
13681 string = '/* function */ ' + g.errorCatcher.getFunctionName(thing);
13684 string = '[' + type + '???]';
13687 } catch(exception) { }
13693 * Finds quoted strings in a Firefox stacktrace and replaces them with redacted versions. Handles pesky escaped quotes
13694 * too. This relies on Firefox's specific stringification/escaping behavior and might not work as consistently in other
13696 * @param {string} stacktraceStr The stacktrace to redact strings from.
13697 * @return {string} The stacktrace, with strings redacted.
13699 g.errorCatcher.redactFirefoxStacktraceStrings = function(stacktraceStr) {
13700 if (!/\"/.test(stacktraceStr)) {
13701 return stacktraceStr;
13703 // We can safely use new ecmascript array methods because this code only runs in Firefox.
13704 return stacktraceStr.split('\n').map(function(stacktraceLine) {
13705 var quoteLocations = [];
13708 index = (stacktraceLine.indexOf('"', index + 1));
13710 quoteLocations.push(index);
13712 } while (index != -1);
13713 quoteLocations = quoteLocations.filter(function(quoteLocation) {
13714 var backslashCount = 0, index = quoteLocation;
13716 if (stacktraceLine.charAt(index) != '\\') {
13719 backslashCount = backslashCount + 1;
13721 // If a quotation mark is preceded by a non-even number of backslashes, it is escaped. Otherwise, only the
13722 // backslashes are escaped.
13723 // \" escaped quote
13724 // \\" escaped backslash, unescaped quote
13725 // \\\" escaped backslash, escaped quote
13727 return (backslashCount % 2 == 0);
13729 if (quoteLocations.length % 2 == 1) {
13730 quoteLocations.push(stacktraceLine.length);
13732 for (var i = quoteLocations.length - 1; i > 0; i -= 2) {
13733 stacktraceLine = stacktraceLine.substr(0, quoteLocations[i - 1] + 1) +
13734 g.errorCatcher.redactString(stacktraceLine.substring(quoteLocations[i - 1] + 1, quoteLocations[i])) +
13735 stacktraceLine.substr(quoteLocations[i]);
13737 return stacktraceLine;
13743 * Redacts a string for user privacy.
13744 * @param {string} str The string to redact.
13745 * @return {string} The redacted string.
13747 g.errorCatcher.redactString = function(str) {
13748 return '[string redacted]';
13749 // This commented out alternative attempts to at least make certain types of string (HTML, for example) maintain a
13750 // recognizable pattern.
13751 // return g.errorCatcher.shortenString(str.replace(/[a-z]/g, 'x').replace(/[A-Z]/g, 'X').replace(/[0-9]/g, '#').replace(
13752 // /[^\\\s\[\]<>xX\"\'\(\)\.\,\?\!\#\=\:\;\&\|\@\_\-]/g, '*'), 150).replace(/\r/g, '').replace(/\n/g, '\\n');
13755 // g.errorCatcher can cause problems with debuggers (it breaks the Firebug console, for example), so it should be
13756 // disabled in development environments. This if statements g.errorCatcher if you're using
13757 if (!/dev/.test(window.location.host)) {
13758 g.errorCatcher(function(errorObj) {
13759 var key = '27461631-f992-4f72-b94d-b98996ef1a53';
13760 var host = 'https://logs.loggly.com';
13761 castor = new loggly({url: host+'/inputs/'+key+'?rt=1', level: 'log'});
13762 castor.error(JSON.stringify({host: window.location.host, error: errorObj}));
13764 // this is the URL redaction function. this one just removes ?q= paramter values, but you should adapt this to your own application if needed.
13765 return str.replace(/([\#\?\&][Qq]\=)[^\=\&\#\s]*/g, '$1[redacted]');
13770 * Copyright 2010 Matthew Eernisse (mde@fleegix.org)
13771 * and Open Source Applications Foundation
13773 * Licensed under the Apache License, Version 2.0 (the "License");
13774 * you may not use this file except in compliance with the License.
13775 * You may obtain a copy of the License at
13777 * http://www.apache.org/licenses/LICENSE-2.0
13779 * Unless required by applicable law or agreed to in writing, software
13780 * distributed under the License is distributed on an "AS IS" BASIS,
13781 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13782 * See the License for the specific language governing permissions and
13783 * limitations under the License.
13785 * Credits: Ideas included from incomplete JS implementation of Olson
13786 * parser, "XMLDAte" by Philippe Goetz (philippe.goetz@wanadoo.fr)
13791 * Preston Hunt (prestonhunt@gmail.com),
13792 * Dov. B Katz (dov.katz@morganstanley.com),
13793 * Peter Bergström (pbergstr@mac.com)
13796 if (typeof timezoneJS == 'undefined') { timezoneJS = {}; }
13798 timezoneJS.Date = function () {
13799 var args = Array.prototype.slice.apply(arguments);
13805 // No args -- create a floating date based on the current local offset
13806 if (args.length === 0) {
13809 // Date string or timestamp -- assumes floating
13810 else if (args.length == 1) {
13811 dt = new Date(args[0]);
13813 // year, month, [date,] [hours,] [minutes,] [seconds,] [milliseconds,] [tzId,] [utc]
13815 t = args[args.length-1];
13817 if (typeof t == 'boolean') {
13821 // Last arg is tzId
13822 else if (typeof t == 'string') {
13824 if (tz == 'Etc/UTC' || tz == 'Etc/GMT') {
13829 // Date string (e.g., '12/27/2006')
13830 t = args[args.length-1];
13831 if (typeof t == 'string') {
13832 dt = new Date(args[0]);
13834 // Date part numbers
13837 for (var i = 0; i < 8; i++) {
13838 a[i] = args[i] || 0;
13840 dt = new Date(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
13843 this._useCache = false;
13853 this.milliseconds = 0;
13854 this.timezone = tz || null;
13855 this.utc = utc || false;
13856 this.setFromDateObjProxy(dt);
13859 timezoneJS.Date.prototype = {
13860 getDate: function () { return this.date; },
13861 getDay: function () { return this._day; },
13862 getFullYear: function () { return this.year; },
13863 getMonth: function () { return this.month; },
13864 getYear: function () { return this.year; },
13865 getHours: function () {
13868 getMilliseconds: function () {
13869 return this.milliseconds;
13871 getMinutes: function () {
13872 return this.minutes;
13874 getSeconds: function () {
13875 return this.seconds;
13877 getTime: function () {
13878 var dt = Date.UTC(this.year, this.month, this.date,
13879 this.hours, this.minutes, this.seconds, this.milliseconds);
13880 return dt + (this.getTimezoneOffset()*60*1000);
13882 getTimezone: function () {
13883 return this.timezone;
13885 getTimezoneOffset: function () {
13886 var info = this.getTimezoneInfo();
13887 return info.tzOffset;
13889 getTimezoneAbbreviation: function () {
13890 var info = this.getTimezoneInfo();
13891 return info.tzAbbr;
13893 getTimezoneInfo: function () {
13896 res = { tzOffset: 0,
13900 if (this._useCache) {
13901 res = this._tzInfo;
13904 if (this.timezone) {
13905 var dt = new Date(Date.UTC(this.year, this.month, this.date,
13906 this.hours, this.minutes, this.seconds, this.milliseconds));
13907 var tz = this.timezone;
13908 res = timezoneJS.timezone.getTzInfo(dt, tz);
13910 // Floating -- use local offset
13912 res = { tzOffset: this.getLocalOffset(),
13915 this._tzInfo = res;
13916 this._useCache = true;
13921 getUTCDate: function () {
13922 return this.getUTCDateProxy().getUTCDate();
13924 getUTCDay: function () {
13925 return this.getUTCDateProxy().getUTCDay();
13927 getUTCFullYear: function () {
13928 return this.getUTCDateProxy().getUTCFullYear();
13930 getUTCHours: function () {
13931 return this.getUTCDateProxy().getUTCHours();
13933 getUTCMilliseconds: function () {
13934 return this.getUTCDateProxy().getUTCMilliseconds();
13936 getUTCMinutes: function () {
13937 return this.getUTCDateProxy().getUTCMinutes();
13939 getUTCMonth: function () {
13940 return this.getUTCDateProxy().getUTCMonth();
13942 getUTCSeconds: function () {
13943 return this.getUTCDateProxy().getUTCSeconds();
13945 setDate: function (n) {
13946 this.setAttribute('date', n);
13948 setFullYear: function (n) {
13949 this.setAttribute('year', n);
13951 setMonth: function (n) {
13952 this.setAttribute('month', n);
13954 setYear: function (n) {
13955 this.setUTCAttribute('year', n);
13957 setHours: function (n) {
13958 this.setAttribute('hours', n);
13960 setMilliseconds: function (n) {
13961 this.setAttribute('milliseconds', n);
13963 setMinutes: function (n) {
13964 this.setAttribute('minutes', n);
13966 setSeconds: function (n) {
13967 this.setAttribute('seconds', n);
13969 setTime: function (n) {
13970 if (isNaN(n)) { throw new Error('Units must be a number.'); }
13971 var dt = new Date(0);
13972 dt.setUTCMilliseconds(n - (this.getTimezoneOffset()*60*1000));
13973 this.setFromDateObjProxy(dt, true);
13975 setUTCDate: function (n) {
13976 this.setUTCAttribute('date', n);
13978 setUTCFullYear: function (n) {
13979 this.setUTCAttribute('year', n);
13981 setUTCHours: function (n) {
13982 this.setUTCAttribute('hours', n);
13984 setUTCMilliseconds: function (n) {
13985 this.setUTCAttribute('milliseconds', n);
13987 setUTCMinutes: function (n) {
13988 this.setUTCAttribute('minutes', n);
13990 setUTCMonth: function (n) {
13991 this.setUTCAttribute('month', n);
13993 setUTCSeconds: function (n) {
13994 this.setUTCAttribute('seconds', n);
13996 toGMTString: function () {},
13997 toLocaleString: function () {},
13998 toLocaleDateString: function () {},
13999 toLocaleTimeString: function () {},
14000 toSource: function () {},
14001 toString: function () {
14002 // Get a quick looky at what's in there
14003 var str = this.getFullYear() + '-' + (this.getMonth()+1) + '-' + this.getDate();
14004 var hou = this.getHours() || 12;
14006 var min = String(this.getMinutes());
14007 if (min.length == 1) { min = '0' + min; }
14008 var sec = String(this.getSeconds());
14009 if (sec.length == 1) { sec = '0' + sec; }
14015 toUTCString: function () {},
14016 valueOf: function () {
14017 return this.getTime();
14019 clone: function () {
14020 return new timezoneJS.Date(this.year, this.month, this.date,
14021 this.hours, this.minutes, this.seconds, this.milliseconds,
14024 setFromDateObjProxy: function (dt, fromUTC) {
14025 this.year = fromUTC ? dt.getUTCFullYear() : dt.getFullYear();
14026 this.month = fromUTC ? dt.getUTCMonth() : dt.getMonth();
14027 this.date = fromUTC ? dt.getUTCDate() : dt.getDate();
14028 this.hours = fromUTC ? dt.getUTCHours() : dt.getHours();
14029 this.minutes = fromUTC ? dt.getUTCMinutes() : dt.getMinutes();
14030 this.seconds = fromUTC ? dt.getUTCSeconds() : dt.getSeconds();
14031 this.milliseconds = fromUTC ? dt.getUTCMilliseconds() : dt.getMilliseconds();
14032 this._day = fromUTC ? dt.getUTCDay() : dt.getDay();
14033 this._useCache = false;
14035 getUTCDateProxy: function () {
14036 var dt = new Date(Date.UTC(this.year, this.month, this.date,
14037 this.hours, this.minutes, this.seconds, this.milliseconds));
14038 dt.setUTCMinutes(dt.getUTCMinutes() + this.getTimezoneOffset());
14041 setAttribute: function (unit, n) {
14042 if (isNaN(n)) { throw new Error('Units must be a number.'); }
14043 var dt = new Date(this.year, this.month, this.date,
14044 this.hours, this.minutes, this.seconds, this.milliseconds);
14045 var meth = unit == 'year' ? 'FullYear' : unit.substr(0, 1).toUpperCase() +
14047 dt['set' + meth](n);
14048 this.setFromDateObjProxy(dt);
14050 setUTCAttribute: function (unit, n) {
14051 if (isNaN(n)) { throw new Error('Units must be a number.'); }
14052 var meth = unit == 'year' ? 'FullYear' : unit.substr(0, 1).toUpperCase() +
14054 var dt = this.getUTCDateProxy();
14055 dt['setUTC' + meth](n);
14056 dt.setUTCMinutes(dt.getUTCMinutes() - this.getTimezoneOffset());
14057 this.setFromDateObjProxy(dt, true);
14059 setTimezone: function (tz) {
14060 if (tz == 'Etc/UTC' || tz == 'Etc/GMT') {
14065 this.timezone = tz;
14066 this._useCache = false;
14068 removeTimezone: function () {
14070 this.timezone = null;
14071 this._useCache = false;
14073 civilToJulianDayNumber: function (y, m, d) {
14075 // Adjust for zero-based JS-style array
14078 a = parseInt(m/12, 10);
14086 a = Math.floor(y / 100);
14087 var b = 2 - a + Math.floor(a / 4);
14088 jDt = Math.floor(365.25 * (y + 4716)) +
14089 Math.floor(30.6001 * (m + 1)) +
14093 getLocalOffset: function () {
14095 var d = new Date(dt.getYear(), dt.getMonth(), dt.getDate(),
14096 dt.getHours(), dt.getMinutes(), dt.getSeconds());
14097 return d.getTimezoneOffset();
14099 convertToTimezone: function(tz) {
14100 var dt = new Date();
14101 res = timezoneJS.timezone.getTzInfo(dt, tz);
14103 convert_offset = this.getTimezoneOffset() - res.tzOffset // offset in minutes
14104 converted_date = new timezoneJS.Date(this + convert_offset*60*1000)
14105 this.setFromDateObjProxy(converted_date, true)
14106 this.setTimezone(tz)
14110 timezoneJS.timezone = new function() {
14112 var monthMap = { 'jan': 0, 'feb': 1, 'mar': 2, 'apr': 3,'may': 4, 'jun': 5, 'jul': 6, 'aug': 7, 'sep': 8, 'oct': 9, 'nov': 10, 'dec': 11 };
14113 var dayMap = {'sun': 0,'mon' :1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6 };
14114 var regionMap = {'EST':'northamerica','MST':'northamerica','HST':'northamerica','EST5EDT':'northamerica','CST6CDT':'northamerica','MST7MDT':'northamerica','PST8PDT':'northamerica','America':'northamerica','Pacific':'australasia','Atlantic':'europe','Africa':'africa','Indian':'africa','Antarctica':'antarctica','Asia':'asia','Australia':'australasia','Europe':'europe','WET':'europe','CET':'europe','MET':'europe','EET':'europe'};
14115 var regionExceptions = {'Pacific/Honolulu':'northamerica','Atlantic/Bermuda':'northamerica','Atlantic/Cape_Verde':'africa','Atlantic/St_Helena':'africa','Indian/Kerguelen':'antarctica','Indian/Chagos':'asia','Indian/Maldives':'asia','Indian/Christmas':'australasia','Indian/Cocos':'australasia','America/Danmarkshavn':'europe','America/Scoresbysund':'europe','America/Godthab':'europe','America/Thule':'europe','Asia/Yekaterinburg':'europe','Asia/Omsk':'europe','Asia/Novosibirsk':'europe','Asia/Krasnoyarsk':'europe','Asia/Irkutsk':'europe','Asia/Yakutsk':'europe','Asia/Vladivostok':'europe','Asia/Sakhalin':'europe','Asia/Magadan':'europe','Asia/Kamchatka':'europe','Asia/Anadyr':'europe','Africa/Ceuta':'europe','America/Argentina/Buenos_Aires':'southamerica','America/Argentina/Cordoba':'southamerica','America/Argentina/Tucuman':'southamerica','America/Argentina/La_Rioja':'southamerica','America/Argentina/San_Juan':'southamerica','America/Argentina/Jujuy':'southamerica','America/Argentina/Catamarca':'southamerica','America/Argentina/Mendoza':'southamerica','America/Argentina/Rio_Gallegos':'southamerica','America/Argentina/Ushuaia':'southamerica','America/Aruba':'southamerica','America/La_Paz':'southamerica','America/Noronha':'southamerica','America/Belem':'southamerica','America/Fortaleza':'southamerica','America/Recife':'southamerica','America/Araguaina':'southamerica','America/Maceio':'southamerica','America/Bahia':'southamerica','America/Sao_Paulo':'southamerica','America/Campo_Grande':'southamerica','America/Cuiaba':'southamerica','America/Porto_Velho':'southamerica','America/Boa_Vista':'southamerica','America/Manaus':'southamerica','America/Eirunepe':'southamerica','America/Rio_Branco':'southamerica','America/Santiago':'southamerica','Pacific/Easter':'southamerica','America/Bogota':'southamerica','America/Curacao':'southamerica','America/Guayaquil':'southamerica','Pacific/Galapagos':'southamerica','Atlantic/Stanley':'southamerica','America/Cayenne':'southamerica','America/Guyana':'southamerica','America/Asuncion':'southamerica','America/Lima':'southamerica','Atlantic/South_Georgia':'southamerica','America/Paramaribo':'southamerica','America/Port_of_Spain':'southamerica','America/Montevideo':'southamerica','America/Caracas':'southamerica'};
14117 function invalidTZError(t) {
14118 throw new Error('Timezone "' + t + '" is either incorrect, or not loaded in the timezone registry.');
14120 function getRegionForTimezone(tz) {
14121 var exc = regionExceptions[tz];
14127 reg = tz.split('/')[0];
14128 ret = regionMap[reg];
14129 // If there's nothing listed in the main regions for
14130 // this TZ, check the 'backward' links
14132 var link = _this.zones[tz];
14133 if (typeof link == 'string') {
14134 return getRegionForTimezone(link);
14140 function parseTimeString(str) {
14141 var pat = /(\d+)(?::0*(\d*))?(?::0*(\d*))?([wsugz])?$/;
14142 var hms = str.match(pat);
14143 hms[1] = parseInt(hms[1], 10);
14144 hms[2] = hms[2] ? parseInt(hms[2], 10) : 0;
14145 hms[3] = hms[3] ? parseInt(hms[3], 10) : 0;
14148 function getZone(dt, tz) {
14150 var zoneList = _this.zones[t];
14151 // Follow links to get to an acutal zone
14152 while (typeof zoneList == "string") {
14154 zoneList = _this.zones[t];
14156 for(var i = 0; i < zoneList.length; i++) {
14157 var z = zoneList[i];
14158 if (!z[3]) { break; }
14159 var yea = parseInt(z[3], 10);
14163 mon = monthMap[z[4].substr(0, 3).toLowerCase()];
14164 dat = parseInt(z[5], 10);
14166 var t = z[6] ? z[6] : '23:59:59';
14167 t = parseTimeString(t);
14168 var d = Date.UTC(yea, mon, dat, t[1], t[2], t[3]);
14169 if (dt.getTime() < d) { break; }
14171 if (i == zoneList.length) { throw new Error('No Zone found for "' + timezone + '" on ' + dt); }
14172 return zoneList[i];
14175 function getBasicOffset(z) {
14176 var off = parseTimeString(z[0]);
14177 var adj = z[0].indexOf('-') == 0 ? -1 : 1
14178 off = adj * (((off[1] * 60 + off[2]) *60 + off[3]) * 1000);
14179 return -off/60/1000;
14182 // if isUTC is true, date is given in UTC, otherwise it's given
14183 // in local time (ie. date.getUTC*() returns local time components)
14184 function getRule( date, zone, isUTC ) {
14185 var ruleset = zone[1];
14186 var basicOffset = getBasicOffset( zone );
14188 // Convert a date to UTC. Depending on the 'type' parameter, the date
14189 // parameter may be:
14190 // 'u', 'g', 'z': already UTC (no adjustment)
14191 // 's': standard time (adjust for time zone offset but not for DST)
14192 // 'w': wall clock time (adjust for both time zone and DST offset)
14194 // DST adjustment is done using the rule given as third argument
14195 var convertDateToUTC = function( date, type, rule ) {
14198 if(type == 'u' || type == 'g' || type == 'z') { // UTC
14200 } else if(type == 's') { // Standard Time
14201 offset = basicOffset;
14202 } else if(type == 'w' || !type ) { // Wall Clock Time
14203 offset = getAdjustedOffset(basicOffset,rule);
14205 throw("unknown type "+type);
14207 offset *= 60*1000; // to millis
14209 return new Date( date.getTime() + offset );
14212 // Step 1: Find applicable rules for this year.
14213 // Step 2: Sort the rules by effective date.
14214 // Step 3: Check requested date to see if a rule has yet taken effect this year. If not,
14215 // Step 4: Get the rules for the previous year. If there isn't an applicable rule for last year, then
14216 // there probably is no current time offset since they seem to explicitly turn off the offset
14217 // when someone stops observing DST.
14218 // FIXME if this is not the case and we'll walk all the way back (ugh).
14219 // Step 5: Sort the rules by effective date.
14220 // Step 6: Apply the most recent rule before the current time.
14222 var convertRuleToExactDateAndTime = function( yearAndRule, prevRule )
14224 var year = yearAndRule[0];
14225 var rule = yearAndRule[1];
14227 // Assume that the rule applies to the year of the given date.
14229 "Jan": 0, "Feb": 1, "Mar": 2, "Apr": 3, "May": 4, "Jun": 5,
14230 "Jul": 6, "Aug": 7, "Sep": 8, "Oct": 9, "Nov": 10, "Dec": 11
14234 "sun": 0, "mon": 1, "tue": 2, "wed": 3, "thu": 4, "fri": 5, "sat": 6
14237 var hms = parseTimeString( rule[ 5 ] );
14240 if ( !isNaN( rule[ 4 ] ) ) // If we have a specific date, use that!
14242 effectiveDate = new Date( Date.UTC( year, months[ rule[ 3 ] ], rule[ 4 ], hms[ 1 ], hms[ 2 ], hms[ 3 ], 0 ) );
14244 else // Let's hunt for the date.
14249 if ( rule[ 4 ].substr( 0, 4 ) === "last" ) // Example: lastThu
14251 // Start at the last day of the month and work backward.
14252 effectiveDate = new Date( Date.UTC( year, months[ rule[ 3 ] ] + 1, 1, hms[ 1 ] - 24, hms[ 2 ], hms[ 3 ], 0 ) );
14253 targetDay = days[ rule[ 4 ].substr( 4, 3 ).toLowerCase( ) ];
14256 else // Example: Sun>=15
14258 // Start at the specified date.
14259 effectiveDate = new Date( Date.UTC( year, months[ rule[ 3 ] ], rule[ 4 ].substr( 5 ), hms[ 1 ], hms[ 2 ], hms[ 3 ], 0 ) );
14260 targetDay = days[ rule[ 4 ].substr( 0, 3 ).toLowerCase( ) ];
14261 operator = rule[ 4 ].substr( 3, 2 );
14264 var ourDay = effectiveDate.getUTCDay( );
14266 if ( operator === ">=" ) // Go forwards.
14268 effectiveDate.setUTCDate( effectiveDate.getUTCDate( ) + ( targetDay - ourDay + ( ( targetDay < ourDay ) ? 7 : 0 ) ) );
14270 else // Go backwards. Looking for the last of a certain day, or operator is "<=" (less likely).
14272 effectiveDate.setUTCDate( effectiveDate.getUTCDate( ) + ( targetDay - ourDay - ( ( targetDay > ourDay ) ? 7 : 0 ) ) );
14276 // if previous rule is given, correct for the fact that the starting time of the current
14277 // rule may be specified in local time
14279 effectiveDate = convertDateToUTC(effectiveDate, hms[4], prevRule);
14282 return effectiveDate;
14285 var findApplicableRules = function( year, ruleset )
14287 var applicableRules = [];
14289 for ( var i in ruleset )
14291 if ( Number( ruleset[ i ][ 0 ] ) <= year ) // Exclude future rules.
14294 Number( ruleset[ i ][ 1 ] ) >= year // Date is in a set range.
14295 || ( Number( ruleset[ i ][ 0 ] ) === year && ruleset[ i ][ 1 ] === "only" ) // Date is in an "only" year.
14296 || ruleset[ i ][ 1 ] === "max" // We're in a range from the start year to infinity.
14299 // It's completely okay to have any number of matches here.
14300 // Normally we should only see two, but that doesn't preclude other numbers of matches.
14301 // These matches are applicable to this year.
14302 applicableRules.push( [year, ruleset[ i ]] );
14307 return applicableRules;
14310 var compareDates = function( a, b, prev )
14312 if ( a.constructor !== Date ) {
14313 a = convertRuleToExactDateAndTime( a, prev );
14315 a = convertDateToUTC(a, isUTC?'u':'w', prev);
14317 if ( b.constructor !== Date ) {
14318 b = convertRuleToExactDateAndTime( b, prev );
14320 b = convertDateToUTC(b, isUTC?'u':'w', prev);
14329 var year = date.getUTCFullYear( );
14330 var applicableRules;
14332 applicableRules = findApplicableRules( year, _this.rules[ ruleset ] );
14333 applicableRules.push( date );
14334 // While sorting, the time zone in which the rule starting time is specified
14335 // is ignored. This is ok as long as the timespan between two DST changes is
14336 // larger than the DST offset, which is probably always true.
14337 // As the given date may indeed be close to a DST change, it may get sorted
14338 // to a wrong position (off by one), which is corrected below.
14339 applicableRules.sort( compareDates );
14341 if ( applicableRules.indexOf( date ) < 2 ) { // If there are not enough past DST rules...
14342 applicableRules = applicableRules.concat(findApplicableRules( year-1, _this.rules[ ruleset ] ));
14343 applicableRules.sort( compareDates );
14346 var pinpoint = applicableRules.indexOf( date );
14347 if ( pinpoint > 1 && compareDates( date, applicableRules[pinpoint-1], applicableRules[pinpoint-2][1] ) < 0 ) {
14348 // the previous rule does not really apply, take the one before that
14349 return applicableRules[ pinpoint - 2 ][1];
14350 } else if ( pinpoint > 0 && pinpoint < applicableRules.length - 1 && compareDates( date, applicableRules[pinpoint+1], applicableRules[pinpoint-1][1] ) > 0) {
14351 // the next rule does already apply, take that one
14352 return applicableRules[ pinpoint + 1 ][1];
14353 } else if ( pinpoint === 0 ) {
14354 // no applicable rule found in this and in previous year
14357 return applicableRules[ pinpoint - 1 ][1];
14360 function getAdjustedOffset(off, rule) {
14361 var save = rule[6];
14362 var t = parseTimeString(save);
14363 var adj = save.indexOf('-') == 0 ? -1 : 1;
14364 var ret = (adj*(((t[1] *60 + t[2]) * 60 + t[3]) * 1000));
14367 ret = -Math.ceil(ret);
14370 function getAbbreviation(zone, rule) {
14372 var base = zone[2];
14373 if (base.indexOf('%s') > -1) {
14376 repl = rule[7]=='-'?'':rule[7];
14378 // FIXME: Right now just falling back to Standard --
14379 // apparently ought to use the last valid rule,
14380 // although in practice that always ought to be Standard
14384 res = base.replace('%s', repl);
14386 else if (base.indexOf('/') > -1) {
14387 // chose one of two alternative strings
14388 var t = parseTimeString(rule[6]);
14389 var isDst = (t[1])||(t[2])||(t[3]);
14390 res = base.split("/",2)[isDst?1:0];
14397 this.getTzInfo = function(dt, tz, isUTC) {
14398 var zone = getZone(dt, tz);
14399 var off = getBasicOffset(zone);
14400 // See if the offset needs adjustment
14401 var rule = getRule(dt, zone, isUTC);
14403 off = getAdjustedOffset(off, rule);
14405 var abbr = getAbbreviation(zone, rule);
14406 return { tzOffset: off, tzAbbr: abbr };
14410 // Timezone data for: northamerica,europe
14411 timezoneJS.timezone.zones = {"Europe/London":[["-0:01:15","-","LMT","1847","Dec","1","0:00s"],["0:00","GB-Eire","%s","1968","Oct","27"],["1:00","-","BST","1971","Oct","31","2:00u"],["0:00","GB-Eire","%s","1996"],["0:00","EU","GMT/BST"]],"Europe/Jersey":"Europe/London","Europe/Guernsey":"Europe/London","Europe/Isle_of_Man":"Europe/London","Europe/Dublin":[["-0:25:00","-","LMT","1880","Aug","2"],["-0:25:21","-","DMT","1916","May","21","2:00"],["-0:25:21","1:00","IST","1916","Oct","1","2:00s"],["0:00","GB-Eire","%s","1921","Dec","6",""],["0:00","GB-Eire","GMT/IST","1940","Feb","25","2:00"],["0:00","1:00","IST","1946","Oct","6","2:00"],["0:00","-","GMT","1947","Mar","16","2:00"],["0:00","1:00","IST","1947","Nov","2","2:00"],["0:00","-","GMT","1948","Apr","18","2:00"],["0:00","GB-Eire","GMT/IST","1968","Oct","27"],["1:00","-","IST","1971","Oct","31","2:00u"],["0:00","GB-Eire","GMT/IST","1996"],["0:00","EU","GMT/IST"]],"WET":[["0:00","EU","WE%sT"]],"CET":[["1:00","C-Eur","CE%sT"]],"MET":[["1:00","C-Eur","ME%sT"]],"EET":[["2:00","EU","EE%sT"]],"Europe/Tirane":[["1:19:20","-","LMT","1914"],["1:00","-","CET","1940","Jun","16"],["1:00","Albania","CE%sT","1984","Jul"],["1:00","EU","CE%sT"]],"Europe/Andorra":[["0:06:04","-","LMT","1901"],["0:00","-","WET","1946","Sep","30"],["1:00","-","CET","1985","Mar","31","2:00"],["1:00","EU","CE%sT"]],"Europe/Vienna":[["1:05:20","-","LMT","1893","Apr"],["1:00","C-Eur","CE%sT","1920"],["1:00","Austria","CE%sT","1940","Apr","1","2:00s"],["1:00","C-Eur","CE%sT","1945","Apr","2","2:00s"],["1:00","1:00","CEST","1945","Apr","12","2:00s"],["1:00","-","CET","1946"],["1:00","Austria","CE%sT","1981"],["1:00","EU","CE%sT"]],"Europe/Minsk":[["1:50:16","-","LMT","1880"],["1:50","-","MMT","1924","May","2",""],["2:00","-","EET","1930","Jun","21"],["3:00","-","MSK","1941","Jun","28"],["1:00","C-Eur","CE%sT","1944","Jul","3"],["3:00","Russia","MSK/MSD","1990"],["3:00","-","MSK","1991","Mar","31","2:00s"],["2:00","1:00","EEST","1991","Sep","29","2:00s"],["2:00","-","EET","1992","Mar","29","0:00s"],["2:00","1:00","EEST","1992","Sep","27","0:00s"],["2:00","Russia","EE%sT"]],"Europe/Brussels":[["0:17:30","-","LMT","1880"],["0:17:30","-","BMT","1892","May","1","12:00",""],["0:00","-","WET","1914","Nov","8"],["1:00","-","CET","1916","May","1","0:00"],["1:00","C-Eur","CE%sT","1918","Nov","11","11:00u"],["0:00","Belgium","WE%sT","1940","May","20","2:00s"],["1:00","C-Eur","CE%sT","1944","Sep","3"],["1:00","Belgium","CE%sT","1977"],["1:00","EU","CE%sT"]],"Europe/Sofia":[["1:33:16","-","LMT","1880"],["1:56:56","-","IMT","1894","Nov","30",""],["2:00","-","EET","1942","Nov","2","3:00"],["1:00","C-Eur","CE%sT","1945"],["1:00","-","CET","1945","Apr","2","3:00"],["2:00","-","EET","1979","Mar","31","23:00"],["2:00","Bulg","EE%sT","1982","Sep","26","2:00"],["2:00","C-Eur","EE%sT","1991"],["2:00","E-Eur","EE%sT","1997"],["2:00","EU","EE%sT"]],"Europe/Prague":[["0:57:44","-","LMT","1850"],["0:57:44","-","PMT","1891","Oct",""],["1:00","C-Eur","CE%sT","1944","Sep","17","2:00s"],["1:00","Czech","CE%sT","1979"],["1:00","EU","CE%sT"]],"Europe/Copenhagen":[["0:50:20","-","LMT","1890"],["0:50:20","-","CMT","1894","Jan","1",""],["1:00","Denmark","CE%sT","1942","Nov","2","2:00s"],["1:00","C-Eur","CE%sT","1945","Apr","2","2:00"],["1:00","Denmark","CE%sT","1980"],["1:00","EU","CE%sT"]],"Atlantic/Faroe":[["-0:27:04","-","LMT","1908","Jan","11",""],["0:00","-","WET","1981"],["0:00","EU","WE%sT"]],"America/Danmarkshavn":[["-1:14:40","-","LMT","1916","Jul","28"],["-3:00","-","WGT","1980","Apr","6","2:00"],["-3:00","EU","WG%sT","1996"],["0:00","-","GMT"]],"America/Scoresbysund":[["-1:27:52","-","LMT","1916","Jul","28",""],["-2:00","-","CGT","1980","Apr","6","2:00"],["-2:00","C-Eur","CG%sT","1981","Mar","29"],["-1:00","EU","EG%sT"]],"America/Godthab":[["-3:26:56","-","LMT","1916","Jul","28",""],["-3:00","-","WGT","1980","Apr","6","2:00"],["-3:00","EU","WG%sT"]],"America/Thule":[["-4:35:08","-","LMT","1916","Jul","28",""],["-4:00","Thule","A%sT"]],"Europe/Tallinn":[["1:39:00","-","LMT","1880"],["1:39:00","-","TMT","1918","Feb",""],["1:00","C-Eur","CE%sT","1919","Jul"],["1:39:00","-","TMT","1921","May"],["2:00","-","EET","1940","Aug","6"],["3:00","-","MSK","1941","Sep","15"],["1:00","C-Eur","CE%sT","1944","Sep","22"],["3:00","Russia","MSK/MSD","1989","Mar","26","2:00s"],["2:00","1:00","EEST","1989","Sep","24","2:00s"],["2:00","C-Eur","EE%sT","1998","Sep","22"],["2:00","EU","EE%sT","1999","Nov","1"],["2:00","-","EET","2002","Feb","21"],["2:00","EU","EE%sT"]],"Europe/Helsinki":[["1:39:52","-","LMT","1878","May","31"],["1:39:52","-","HMT","1921","May",""],["2:00","Finland","EE%sT","1983"],["2:00","EU","EE%sT"]],"Europe/Mariehamn":"Europe/Helsinki","Europe/Paris":[["0:09:21","-","LMT","1891","Mar","15","0:01"],["0:09:21","-","PMT","1911","Mar","11","0:01",""],["0:00","France","WE%sT","1940","Jun","14","23:00"],["1:00","C-Eur","CE%sT","1944","Aug","25"],["0:00","France","WE%sT","1945","Sep","16","3:00"],["1:00","France","CE%sT","1977"],["1:00","EU","CE%sT"]],"Europe/Berlin":[["0:53:28","-","LMT","1893","Apr"],["1:00","C-Eur","CE%sT","1945","May","24","2:00"],["1:00","SovietZone","CE%sT","1946"],["1:00","Germany","CE%sT","1980"],["1:00","EU","CE%sT"]],"Europe/Gibraltar":[["-0:21:24","-","LMT","1880","Aug","2","0:00s"],["0:00","GB-Eire","%s","1957","Apr","14","2:00"],["1:00","-","CET","1982"],["1:00","EU","CE%sT"]],"Europe/Athens":[["1:34:52","-","LMT","1895","Sep","14"],["1:34:52","-","AMT","1916","Jul","28","0:01",""],["2:00","Greece","EE%sT","1941","Apr","30"],["1:00","Greece","CE%sT","1944","Apr","4"],["2:00","Greece","EE%sT","1981"],[""],[""],["2:00","EU","EE%sT"]],"Europe/Budapest":[["1:16:20","-","LMT","1890","Oct"],["1:00","C-Eur","CE%sT","1918"],["1:00","Hungary","CE%sT","1941","Apr","6","2:00"],["1:00","C-Eur","CE%sT","1945"],["1:00","Hungary","CE%sT","1980","Sep","28","2:00s"],["1:00","EU","CE%sT"]],"Atlantic/Reykjavik":[["-1:27:24","-","LMT","1837"],["-1:27:48","-","RMT","1908",""],["-1:00","Iceland","IS%sT","1968","Apr","7","1:00s"],["0:00","-","GMT"]],"Europe/Rome":[["0:49:56","-","LMT","1866","Sep","22"],["0:49:56","-","RMT","1893","Nov","1","0:00s",""],["1:00","Italy","CE%sT","1942","Nov","2","2:00s"],["1:00","C-Eur","CE%sT","1944","Jul"],["1:00","Italy","CE%sT","1980"],["1:00","EU","CE%sT"]],"Europe/Vatican":"Europe/Rome","Europe/San_Marino":"Europe/Rome","Europe/Riga":[["1:36:24","-","LMT","1880"],["1:36:24","-","RMT","1918","Apr","15","2:00",""],["1:36:24","1:00","LST","1918","Sep","16","3:00",""],["1:36:24","-","RMT","1919","Apr","1","2:00"],["1:36:24","1:00","LST","1919","May","22","3:00"],["1:36:24","-","RMT","1926","May","11"],["2:00","-","EET","1940","Aug","5"],["3:00","-","MSK","1941","Jul"],["1:00","C-Eur","CE%sT","1944","Oct","13"],["3:00","Russia","MSK/MSD","1989","Mar","lastSun","2:00s"],["2:00","1:00","EEST","1989","Sep","lastSun","2:00s"],["2:00","Latvia","EE%sT","1997","Jan","21"],["2:00","EU","EE%sT","2000","Feb","29"],["2:00","-","EET","2001","Jan","2"],["2:00","EU","EE%sT"]],"Europe/Vaduz":[["0:38:04","-","LMT","1894","Jun"],["1:00","-","CET","1981"],["1:00","EU","CE%sT"]],"Europe/Vilnius":[["1:41:16","-","LMT","1880"],["1:24:00","-","WMT","1917",""],["1:35:36","-","KMT","1919","Oct","10",""],["1:00","-","CET","1920","Jul","12"],["2:00","-","EET","1920","Oct","9"],["1:00","-","CET","1940","Aug","3"],["3:00","-","MSK","1941","Jun","24"],["1:00","C-Eur","CE%sT","1944","Aug"],["3:00","Russia","MSK/MSD","1991","Mar","31","2:00s"],["2:00","1:00","EEST","1991","Sep","29","2:00s"],["2:00","C-Eur","EE%sT","1998"],["2:00","-","EET","1998","Mar","29","1:00u"],["1:00","EU","CE%sT","1999","Oct","31","1:00u"],["2:00","-","EET","2003","Jan","1"],["2:00","EU","EE%sT"]],"Europe/Luxembourg":[["0:24:36","-","LMT","1904","Jun"],["1:00","Lux","CE%sT","1918","Nov","25"],["0:00","Lux","WE%sT","1929","Oct","6","2:00s"],["0:00","Belgium","WE%sT","1940","May","14","3:00"],["1:00","C-Eur","WE%sT","1944","Sep","18","3:00"],["1:00","Belgium","CE%sT","1977"],["1:00","EU","CE%sT"]],"Europe/Malta":[["0:58:04","-","LMT","1893","Nov","2","0:00s",""],["1:00","Italy","CE%sT","1942","Nov","2","2:00s"],["1:00","C-Eur","CE%sT","1945","Apr","2","2:00s"],["1:00","Italy","CE%sT","1973","Mar","31"],["1:00","Malta","CE%sT","1981"],["1:00","EU","CE%sT"]],"Europe/Chisinau":[["1:55:20","-","LMT","1880"],["1:55","-","CMT","1918","Feb","15",""],["1:44:24","-","BMT","1931","Jul","24",""],["2:00","Romania","EE%sT","1940","Aug","15"],["2:00","1:00","EEST","1941","Jul","17"],["1:00","C-Eur","CE%sT","1944","Aug","24"],["3:00","Russia","MSK/MSD","1990"],["3:00","-","MSK","1990","May","6"],["2:00","-","EET","1991"],["2:00","Russia","EE%sT","1992"],["2:00","E-Eur","EE%sT","1997"],["2:00","EU","EE%sT"]],"Europe/Monaco":[["0:29:32","-","LMT","1891","Mar","15"],["0:09:21","-","PMT","1911","Mar","11",""],["0:00","France","WE%sT","1945","Sep","16","3:00"],["1:00","France","CE%sT","1977"],["1:00","EU","CE%sT"]],"Europe/Amsterdam":[["0:19:32","-","LMT","1835"],["0:19:32","Neth","%s","1937","Jul","1"],["0:20","Neth","NE%sT","1940","May","16","0:00",""],["1:00","C-Eur","CE%sT","1945","Apr","2","2:00"],["1:00","Neth","CE%sT","1977"],["1:00","EU","CE%sT"]],"Europe/Oslo":[["0:43:00","-","LMT","1895","Jan","1"],["1:00","Norway","CE%sT","1940","Aug","10","23:00"],["1:00","C-Eur","CE%sT","1945","Apr","2","2:00"],["1:00","Norway","CE%sT","1980"],["1:00","EU","CE%sT"]],"Arctic/Longyearbyen":"Europe/Oslo","Europe/Warsaw":[["1:24:00","-","LMT","1880"],["1:24:00","-","WMT","1915","Aug","5",""],["1:00","C-Eur","CE%sT","1918","Sep","16","3:00"],["2:00","Poland","EE%sT","1922","Jun"],["1:00","Poland","CE%sT","1940","Jun","23","2:00"],["1:00","C-Eur","CE%sT","1944","Oct"],["1:00","Poland","CE%sT","1977"],["1:00","W-Eur","CE%sT","1988"],["1:00","EU","CE%sT"]],"Europe/Lisbon":[["-0:36:32","-","LMT","1884"],["-0:36:32","-","LMT","1912","Jan","1",""],["0:00","Port","WE%sT","1966","Apr","3","2:00"],["1:00","-","CET","1976","Sep","26","1:00"],["0:00","Port","WE%sT","1983","Sep","25","1:00s"],["0:00","W-Eur","WE%sT","1992","Sep","27","1:00s"],["1:00","EU","CE%sT","1996","Mar","31","1:00u"],["0:00","EU","WE%sT"]],"Atlantic/Azores":[["-1:42:40","-","LMT","1884",""],["-1:54:32","-","HMT","1911","May","24",""],["-2:00","Port","AZO%sT","1966","Apr","3","2:00",""],["-1:00","Port","AZO%sT","1983","Sep","25","1:00s"],["-1:00","W-Eur","AZO%sT","1992","Sep","27","1:00s"],["0:00","EU","WE%sT","1993","Mar","28","1:00u"],["-1:00","EU","AZO%sT"]],"Atlantic/Madeira":[["-1:07:36","-","LMT","1884",""],["-1:07:36","-","FMT","1911","May","24",""],["-1:00","Port","MAD%sT","1966","Apr","3","2:00",""],["0:00","Port","WE%sT","1983","Sep","25","1:00s"],["0:00","EU","WE%sT"]],"Europe/Bucharest":[["1:44:24","-","LMT","1891","Oct"],["1:44:24","-","BMT","1931","Jul","24",""],["2:00","Romania","EE%sT","1981","Mar","29","2:00s"],["2:00","C-Eur","EE%sT","1991"],["2:00","Romania","EE%sT","1994"],["2:00","E-Eur","EE%sT","1997"],["2:00","EU","EE%sT"]],"Europe/Kaliningrad":[["1:22:00","-","LMT","1893","Apr"],["1:00","C-Eur","CE%sT","1945"],["2:00","Poland","CE%sT","1946"],["3:00","Russia","MSK/MSD","1991","Mar","31","2:00s"],["2:00","Russia","EE%sT","2011","Mar","27","2:00s"],["3:00","-","EET"]],"Europe/Moscow":[["2:30:20","-","LMT","1880"],["2:30","-","MMT","1916","Jul","3",""],["2:30:48","Russia","%s","1919","Jul","1","2:00"],["3:00","Russia","MSK/MSD","1922","Oct"],["2:00","-","EET","1930","Jun","21"],["3:00","Russia","MSK/MSD","1991","Mar","31","2:00s"],["2:00","Russia","EE%sT","1992","Jan","19","2:00s"],["3:00","Russia","MSK/MSD","2011","Mar","27","2:00s"],["4:00","-","MSK"]],"Europe/Volgograd":[["2:57:40","-","LMT","1920","Jan","3"],["3:00","-","TSAT","1925","Apr","6",""],["3:00","-","STAT","1930","Jun","21",""],["4:00","-","STAT","1961","Nov","11"],["4:00","Russia","VOL%sT","1989","Mar","26","2:00s",""],["3:00","Russia","VOL%sT","1991","Mar","31","2:00s"],["4:00","-","VOLT","1992","Mar","29","2:00s"],["3:00","Russia","VOL%sT","2011","Mar","27","2:00s"],["4:00","-","VOLT"]],"Europe/Samara":[["3:20:36","-","LMT","1919","Jul","1","2:00"],["3:00","-","SAMT","1930","Jun","21"],["4:00","-","SAMT","1935","Jan","27"],["4:00","Russia","KUY%sT","1989","Mar","26","2:00s",""],["3:00","Russia","KUY%sT","1991","Mar","31","2:00s"],["2:00","Russia","KUY%sT","1991","Sep","29","2:00s"],["3:00","-","KUYT","1991","Oct","20","3:00"],["4:00","Russia","SAM%sT","2010","Mar","28","2:00s",""],["3:00","Russia","SAM%sT","2011","Mar","27","2:00s"],["4:00","-","SAMT"]],"Asia/Yekaterinburg":[["4:02:24","-","LMT","1919","Jul","15","4:00"],["4:00","-","SVET","1930","Jun","21",""],["5:00","Russia","SVE%sT","1991","Mar","31","2:00s"],["4:00","Russia","SVE%sT","1992","Jan","19","2:00s"],["5:00","Russia","YEK%sT","2011","Mar","27","2:00s"],["6:00","-","YEKT",""]],"Asia/Omsk":[["4:53:36","-","LMT","1919","Nov","14"],["5:00","-","OMST","1930","Jun","21",""],["6:00","Russia","OMS%sT","1991","Mar","31","2:00s"],["5:00","Russia","OMS%sT","1992","Jan","19","2:00s"],["6:00","Russia","OMS%sT","2011","Mar","27","2:00s"],["7:00","-","OMST"]],"Asia/Novosibirsk":[["5:31:40","-","LMT","1919","Dec","14","6:00"],["6:00","-","NOVT","1930","Jun","21",""],["7:00","Russia","NOV%sT","1991","Mar","31","2:00s"],["6:00","Russia","NOV%sT","1992","Jan","19","2:00s"],["7:00","Russia","NOV%sT","1993","May","23",""],["6:00","Russia","NOV%sT","2011","Mar","27","2:00s"],["7:00","-","NOVT"]],"Asia/Novokuznetsk":[["5:48:48","-","NMT","1920","Jan","6"],["6:00","-","KRAT","1930","Jun","21",""],["7:00","Russia","KRA%sT","1991","Mar","31","2:00s"],["6:00","Russia","KRA%sT","1992","Jan","19","2:00s"],["7:00","Russia","KRA%sT","2010","Mar","28","2:00s"],["6:00","Russia","NOV%sT","2011","Mar","27","2:00s"],["7:00","-","NOVT",""]],"Asia/Krasnoyarsk":[["6:11:20","-","LMT","1920","Jan","6"],["6:00","-","KRAT","1930","Jun","21",""],["7:00","Russia","KRA%sT","1991","Mar","31","2:00s"],["6:00","Russia","KRA%sT","1992","Jan","19","2:00s"],["7:00","Russia","KRA%sT","2011","Mar","27","2:00s"],["8:00","-","KRAT"]],"Asia/Irkutsk":[["6:57:20","-","LMT","1880"],["6:57:20","-","IMT","1920","Jan","25",""],["7:00","-","IRKT","1930","Jun","21",""],["8:00","Russia","IRK%sT","1991","Mar","31","2:00s"],["7:00","Russia","IRK%sT","1992","Jan","19","2:00s"],["8:00","Russia","IRK%sT","2011","Mar","27","2:00s"],["9:00","-","IRKT"]],"Asia/Yakutsk":[["8:38:40","-","LMT","1919","Dec","15"],["8:00","-","YAKT","1930","Jun","21",""],["9:00","Russia","YAK%sT","1991","Mar","31","2:00s"],["8:00","Russia","YAK%sT","1992","Jan","19","2:00s"],["9:00","Russia","YAK%sT","2011","Mar","27","2:00s"],["10:00","-","YAKT"]],"Asia/Vladivostok":[["8:47:44","-","LMT","1922","Nov","15"],["9:00","-","VLAT","1930","Jun","21",""],["10:00","Russia","VLA%sT","1991","Mar","31","2:00s"],["9:00","Russia","VLA%sST","1992","Jan","19","2:00s"],["10:00","Russia","VLA%sT","2011","Mar","27","2:00s"],["11:00","-","VLAT"]],"Asia/Sakhalin":[["9:30:48","-","LMT","1905","Aug","23"],["9:00","-","CJT","1938"],["9:00","-","JST","1945","Aug","25"],["11:00","Russia","SAK%sT","1991","Mar","31","2:00s",""],["10:00","Russia","SAK%sT","1992","Jan","19","2:00s"],["11:00","Russia","SAK%sT","1997","Mar","lastSun","2:00s"],["10:00","Russia","SAK%sT","2011","Mar","27","2:00s"],["11:00","-","SAKT"]],"Asia/Magadan":[["10:03:12","-","LMT","1924","May","2"],["10:00","-","MAGT","1930","Jun","21",""],["11:00","Russia","MAG%sT","1991","Mar","31","2:00s"],["10:00","Russia","MAG%sT","1992","Jan","19","2:00s"],["11:00","Russia","MAG%sT","2011","Mar","27","2:00s"],["12:00","-","MAGT"]],"Asia/Kamchatka":[["10:34:36","-","LMT","1922","Nov","10"],["11:00","-","PETT","1930","Jun","21",""],["12:00","Russia","PET%sT","1991","Mar","31","2:00s"],["11:00","Russia","PET%sT","1992","Jan","19","2:00s"],["12:00","Russia","PET%sT","2010","Mar","28","2:00s"],["11:00","Russia","PET%sT","2011","Mar","27","2:00s"],["12:00","-","PETT"]],"Asia/Anadyr":[["11:49:56","-","LMT","1924","May","2"],["12:00","-","ANAT","1930","Jun","21",""],["13:00","Russia","ANA%sT","1982","Apr","1","0:00s"],["12:00","Russia","ANA%sT","1991","Mar","31","2:00s"],["11:00","Russia","ANA%sT","1992","Jan","19","2:00s"],["12:00","Russia","ANA%sT","2010","Mar","28","2:00s"],["11:00","Russia","ANA%sT","2011","Mar","27","2:00s"],["12:00","-","ANAT"]],"Europe/Belgrade":[["1:22:00","-","LMT","1884"],["1:00","-","CET","1941","Apr","18","23:00"],["1:00","C-Eur","CE%sT","1945"],["1:00","-","CET","1945","May","8","2:00s"],["1:00","1:00","CEST","1945","Sep","16","2:00s"],["1:00","-","CET","1982","Nov","27"],["1:00","EU","CE%sT"]],"Europe/Ljubljana":"Europe/Belgrade","Europe/Podgorica":"Europe/Belgrade","Europe/Sarajevo":"Europe/Belgrade","Europe/Skopje":"Europe/Belgrade","Europe/Zagreb":"Europe/Belgrade","Europe/Bratislava":"Europe/Prague","Europe/Madrid":[["-0:14:44","-","LMT","1901","Jan","1","0:00s"],["0:00","Spain","WE%sT","1946","Sep","30"],["1:00","Spain","CE%sT","1979"],["1:00","EU","CE%sT"]],"Africa/Ceuta":[["-0:21:16","-","LMT","1901"],["0:00","-","WET","1918","May","6","23:00"],["0:00","1:00","WEST","1918","Oct","7","23:00"],["0:00","-","WET","1924"],["0:00","Spain","WE%sT","1929"],["0:00","SpainAfrica","WE%sT","1984","Mar","16"],["1:00","-","CET","1986"],["1:00","EU","CE%sT"]],"Atlantic/Canary":[["-1:01:36","-","LMT","1922","Mar",""],["-1:00","-","CANT","1946","Sep","30","1:00",""],["0:00","-","WET","1980","Apr","6","0:00s"],["0:00","1:00","WEST","1980","Sep","28","0:00s"],["0:00","EU","WE%sT"]],"Europe/Stockholm":[["1:12:12","-","LMT","1879","Jan","1"],["1:00:14","-","SET","1900","Jan","1",""],["1:00","-","CET","1916","May","14","23:00"],["1:00","1:00","CEST","1916","Oct","1","01:00"],["1:00","-","CET","1980"],["1:00","EU","CE%sT"]],"Europe/Zurich":[["0:34:08","-","LMT","1848","Sep","12"],["0:29:44","-","BMT","1894","Jun",""],["1:00","Swiss","CE%sT","1981"],["1:00","EU","CE%sT"]],"Europe/Istanbul":[["1:55:52","-","LMT","1880"],["1:56:56","-","IMT","1910","Oct",""],["2:00","Turkey","EE%sT","1978","Oct","15"],["3:00","Turkey","TR%sT","1985","Apr","20",""],["2:00","Turkey","EE%sT","2007"],["2:00","EU","EE%sT","2011","Mar","27","1:00u"],["2:00","-","EET","2011","Mar","28","1:00u"],["2:00","EU","EE%sT"]],"Asia/Istanbul":"Europe/Istanbul","Europe/Kiev":[["2:02:04","-","LMT","1880"],["2:02:04","-","KMT","1924","May","2",""],["2:00","-","EET","1930","Jun","21"],["3:00","-","MSK","1941","Sep","20"],["1:00","C-Eur","CE%sT","1943","Nov","6"],["3:00","Russia","MSK/MSD","1990"],["3:00","-","MSK","1990","Jul","1","2:00"],["2:00","-","EET","1992"],["2:00","E-Eur","EE%sT","1995"],["2:00","EU","EE%sT"]],"Europe/Uzhgorod":[["1:29:12","-","LMT","1890","Oct"],["1:00","-","CET","1940"],["1:00","C-Eur","CE%sT","1944","Oct"],["1:00","1:00","CEST","1944","Oct","26"],["1:00","-","CET","1945","Jun","29"],["3:00","Russia","MSK/MSD","1990"],["3:00","-","MSK","1990","Jul","1","2:00"],["1:00","-","CET","1991","Mar","31","3:00"],["2:00","-","EET","1992"],["2:00","E-Eur","EE%sT","1995"],["2:00","EU","EE%sT"]],"Europe/Zaporozhye":[["2:20:40","-","LMT","1880"],["2:20","-","CUT","1924","May","2",""],["2:00","-","EET","1930","Jun","21"],["3:00","-","MSK","1941","Aug","25"],["1:00","C-Eur","CE%sT","1943","Oct","25"],["3:00","Russia","MSK/MSD","1991","Mar","31","2:00"],["2:00","E-Eur","EE%sT","1995"],["2:00","EU","EE%sT"]],"Europe/Simferopol":[["2:16:24","-","LMT","1880"],["2:16","-","SMT","1924","May","2",""],["2:00","-","EET","1930","Jun","21"],["3:00","-","MSK","1941","Nov"],["1:00","C-Eur","CE%sT","1944","Apr","13"],["3:00","Russia","MSK/MSD","1990"],["3:00","-","MSK","1990","Jul","1","2:00"],["2:00","-","EET","1992"],["2:00","E-Eur","EE%sT","1994","May"],["3:00","E-Eur","MSK/MSD","1996","Mar","31","3:00s"],["3:00","1:00","MSD","1996","Oct","27","3:00s"],["3:00","Russia","MSK/MSD","1997"],["3:00","-","MSK","1997","Mar","lastSun","1:00u"],["2:00","EU","EE%sT"]],"EST":[["-5:00","-","EST"]],"MST":[["-7:00","-","MST"]],"HST":[["-10:00","-","HST"]],"EST5EDT":[["-5:00","US","E%sT"]],"CST6CDT":[["-6:00","US","C%sT"]],"MST7MDT":[["-7:00","US","M%sT"]],"PST8PDT":[["-8:00","US","P%sT"]],"America/New_York":[["-4:56:02","-","LMT","1883","Nov","18","12:03:58"],["-5:00","US","E%sT","1920"],["-5:00","NYC","E%sT","1942"],["-5:00","US","E%sT","1946"],["-5:00","NYC","E%sT","1967"],["-5:00","US","E%sT"]],"America/Chicago":[["-5:50:36","-","LMT","1883","Nov","18","12:09:24"],["-6:00","US","C%sT","1920"],["-6:00","Chicago","C%sT","1936","Mar","1","2:00"],["-5:00","-","EST","1936","Nov","15","2:00"],["-6:00","Chicago","C%sT","1942"],["-6:00","US","C%sT","1946"],["-6:00","Chicago","C%sT","1967"],["-6:00","US","C%sT"]],"America/North_Dakota/Center":[["-6:45:12","-","LMT","1883","Nov","18","12:14:48"],["-7:00","US","M%sT","1992","Oct","25","02:00"],["-6:00","US","C%sT"]],"America/North_Dakota/New_Salem":[["-6:45:39","-","LMT","1883","Nov","18","12:14:21"],["-7:00","US","M%sT","2003","Oct","26","02:00"],["-6:00","US","C%sT"]],"America/North_Dakota/Beulah":[["-6:47:07","-","LMT","1883","Nov","18","12:12:53"],["-7:00","US","M%sT","2010","Nov","7","2:00"],["-6:00","US","C%sT"]],"America/Denver":[["-6:59:56","-","LMT","1883","Nov","18","12:00:04"],["-7:00","US","M%sT","1920"],["-7:00","Denver","M%sT","1942"],["-7:00","US","M%sT","1946"],["-7:00","Denver","M%sT","1967"],["-7:00","US","M%sT"]],"America/Los_Angeles":[["-7:52:58","-","LMT","1883","Nov","18","12:07:02"],["-8:00","US","P%sT","1946"],["-8:00","CA","P%sT","1967"],["-8:00","US","P%sT"]],"America/Juneau":[["15:02:19","-","LMT","1867","Oct","18"],["-8:57:41","-","LMT","1900","Aug","20","12:00"],["-8:00","-","PST","1942"],["-8:00","US","P%sT","1946"],["-8:00","-","PST","1969"],["-8:00","US","P%sT","1980","Apr","27","2:00"],["-9:00","US","Y%sT","1980","Oct","26","2:00",""],["-8:00","US","P%sT","1983","Oct","30","2:00"],["-9:00","US","Y%sT","1983","Nov","30"],["-9:00","US","AK%sT"]],"America/Sitka":[["-14:58:47","-","LMT","1867","Oct","18"],["-9:01:13","-","LMT","1900","Aug","20","12:00"],["-8:00","-","PST","1942"],["-8:00","US","P%sT","1946"],["-8:00","-","PST","1969"],["-8:00","US","P%sT","1983","Oct","30","2:00"],["-9:00","US","Y%sT","1983","Nov","30"],["-9:00","US","AK%sT"]],"America/Metlakatla":[["15:13:42","-","LMT","1867","Oct","18"],["-8:46:18","-","LMT","1900","Aug","20","12:00"],["-8:00","-","PST","1942"],["-8:00","US","P%sT","1946"],["-8:00","-","PST","1969"],["-8:00","US","P%sT","1983","Oct","30","2:00"],["-8:00","US","MeST"]],"America/Yakutat":[["14:41:05","-","LMT","1867","Oct","18"],["-9:18:55","-","LMT","1900","Aug","20","12:00"],["-9:00","-","YST","1942"],["-9:00","US","Y%sT","1946"],["-9:00","-","YST","1969"],["-9:00","US","Y%sT","1983","Nov","30"],["-9:00","US","AK%sT"]],"America/Anchorage":[["14:00:24","-","LMT","1867","Oct","18"],["-9:59:36","-","LMT","1900","Aug","20","12:00"],["-10:00","-","CAT","1942"],["-10:00","US","CAT/CAWT","1945","Aug","14","23:00u"],["-10:00","US","CAT/CAPT","1946",""],["-10:00","-","CAT","1967","Apr"],["-10:00","-","AHST","1969"],["-10:00","US","AH%sT","1983","Oct","30","2:00"],["-9:00","US","Y%sT","1983","Nov","30"],["-9:00","US","AK%sT"]],"America/Nome":[["12:58:21","-","LMT","1867","Oct","18"],["-11:01:38","-","LMT","1900","Aug","20","12:00"],["-11:00","-","NST","1942"],["-11:00","US","N%sT","1946"],["-11:00","-","NST","1967","Apr"],["-11:00","-","BST","1969"],["-11:00","US","B%sT","1983","Oct","30","2:00"],["-9:00","US","Y%sT","1983","Nov","30"],["-9:00","US","AK%sT"]],"America/Adak":[["12:13:21","-","LMT","1867","Oct","18"],["-11:46:38","-","LMT","1900","Aug","20","12:00"],["-11:00","-","NST","1942"],["-11:00","US","N%sT","1946"],["-11:00","-","NST","1967","Apr"],["-11:00","-","BST","1969"],["-11:00","US","B%sT","1983","Oct","30","2:00"],["-10:00","US","AH%sT","1983","Nov","30"],["-10:00","US","HA%sT"]],"Pacific/Honolulu":[["-10:31:26","-","LMT","1896","Jan","13","12:00",""],["-10:30","-","HST","1933","Apr","30","2:00",""],["-10:30","1:00","HDT","1933","May","21","12:00",""],["-10:30","-","HST","1942","Feb","09","2:00",""],["-10:30","1:00","HDT","1945","Sep","30","2:00",""],["-10:30","US","H%sT","1947","Jun","8","2:00",""],["-10:00","-","HST"]],"America/Phoenix":[["-7:28:18","-","LMT","1883","Nov","18","11:31:42"],["-7:00","US","M%sT","1944","Jan","1","00:01"],["-7:00","-","MST","1944","Apr","1","00:01"],["-7:00","US","M%sT","1944","Oct","1","00:01"],["-7:00","-","MST","1967"],["-7:00","US","M%sT","1968","Mar","21"],["-7:00","-","MST"]],"America/Shiprock":"America/Denver","America/Boise":[["-7:44:49","-","LMT","1883","Nov","18","12:15:11"],["-8:00","US","P%sT","1923","May","13","2:00"],["-7:00","US","M%sT","1974"],["-7:00","-","MST","1974","Feb","3","2:00"],["-7:00","US","M%sT"]],"America/Indiana/Indianapolis":[["-5:44:38","-","LMT","1883","Nov","18","12:15:22"],["-6:00","US","C%sT","1920"],["-6:00","Indianapolis","C%sT","1942"],["-6:00","US","C%sT","1946"],["-6:00","Indianapolis","C%sT","1955","Apr","24","2:00"],["-5:00","-","EST","1957","Sep","29","2:00"],["-6:00","-","CST","1958","Apr","27","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1971"],["-5:00","-","EST","2006"],["-5:00","US","E%sT"]],"America/Indiana/Marengo":[["-5:45:23","-","LMT","1883","Nov","18","12:14:37"],["-6:00","US","C%sT","1951"],["-6:00","Marengo","C%sT","1961","Apr","30","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1974","Jan","6","2:00"],["-6:00","1:00","CDT","1974","Oct","27","2:00"],["-5:00","US","E%sT","1976"],["-5:00","-","EST","2006"],["-5:00","US","E%sT"]],"America/Indiana/Vincennes":[["-5:50:07","-","LMT","1883","Nov","18","12:09:53"],["-6:00","US","C%sT","1946"],["-6:00","Vincennes","C%sT","1964","Apr","26","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1971"],["-5:00","-","EST","2006","Apr","2","2:00"],["-6:00","US","C%sT","2007","Nov","4","2:00"],["-5:00","US","E%sT"]],"America/Indiana/Tell_City":[["-5:47:03","-","LMT","1883","Nov","18","12:12:57"],["-6:00","US","C%sT","1946"],["-6:00","Perry","C%sT","1964","Apr","26","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1971"],["-5:00","-","EST","2006","Apr","2","2:00"],["-6:00","US","C%sT"]],"America/Indiana/Petersburg":[["-5:49:07","-","LMT","1883","Nov","18","12:10:53"],["-6:00","US","C%sT","1955"],["-6:00","Pike","C%sT","1965","Apr","25","2:00"],["-5:00","-","EST","1966","Oct","30","2:00"],["-6:00","US","C%sT","1977","Oct","30","2:00"],["-5:00","-","EST","2006","Apr","2","2:00"],["-6:00","US","C%sT","2007","Nov","4","2:00"],["-5:00","US","E%sT"]],"America/Indiana/Knox":[["-5:46:30","-","LMT","1883","Nov","18","12:13:30"],["-6:00","US","C%sT","1947"],["-6:00","Starke","C%sT","1962","Apr","29","2:00"],["-5:00","-","EST","1963","Oct","27","2:00"],["-6:00","US","C%sT","1991","Oct","27","2:00"],["-5:00","-","EST","2006","Apr","2","2:00"],["-6:00","US","C%sT"]],"America/Indiana/Winamac":[["-5:46:25","-","LMT","1883","Nov","18","12:13:35"],["-6:00","US","C%sT","1946"],["-6:00","Pulaski","C%sT","1961","Apr","30","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1971"],["-5:00","-","EST","2006","Apr","2","2:00"],["-6:00","US","C%sT","2007","Mar","11","2:00"],["-5:00","US","E%sT"]],"America/Indiana/Vevay":[["-5:40:16","-","LMT","1883","Nov","18","12:19:44"],["-6:00","US","C%sT","1954","Apr","25","2:00"],["-5:00","-","EST","1969"],["-5:00","US","E%sT","1973"],["-5:00","-","EST","2006"],["-5:00","US","E%sT"]],"America/Kentucky/Louisville":[["-5:43:02","-","LMT","1883","Nov","18","12:16:58"],["-6:00","US","C%sT","1921"],["-6:00","Louisville","C%sT","1942"],["-6:00","US","C%sT","1946"],["-6:00","Louisville","C%sT","1961","Jul","23","2:00"],["-5:00","-","EST","1968"],["-5:00","US","E%sT","1974","Jan","6","2:00"],["-6:00","1:00","CDT","1974","Oct","27","2:00"],["-5:00","US","E%sT"]],"America/Kentucky/Monticello":[["-5:39:24","-","LMT","1883","Nov","18","12:20:36"],["-6:00","US","C%sT","1946"],["-6:00","-","CST","1968"],["-6:00","US","C%sT","2000","Oct","29","2:00"],["-5:00","US","E%sT"]],"America/Detroit":[["-5:32:11","-","LMT","1905"],["-6:00","-","CST","1915","May","15","2:00"],["-5:00","-","EST","1942"],["-5:00","US","E%sT","1946"],["-5:00","Detroit","E%sT","1973"],["-5:00","US","E%sT","1975"],["-5:00","-","EST","1975","Apr","27","2:00"],["-5:00","US","E%sT"]],"America/Menominee":[["-5:50:27","-","LMT","1885","Sep","18","12:00"],["-6:00","US","C%sT","1946"],["-6:00","Menominee","C%sT","1969","Apr","27","2:00"],["-5:00","-","EST","1973","Apr","29","2:00"],["-6:00","US","C%sT"]],"America/St_Johns":[["-3:30:52","-","LMT","1884"],["-3:30:52","StJohns","N%sT","1918"],["-3:30:52","Canada","N%sT","1919"],["-3:30:52","StJohns","N%sT","1935","Mar","30"],["-3:30","StJohns","N%sT","1942","May","11"],["-3:30","Canada","N%sT","1946"],["-3:30","StJohns","N%sT"]],"America/Goose_Bay":[["-4:01:40","-","LMT","1884",""],["-3:30:52","-","NST","1918"],["-3:30:52","Canada","N%sT","1919"],["-3:30:52","-","NST","1935","Mar","30"],["-3:30","-","NST","1936"],["-3:30","StJohns","N%sT","1942","May","11"],["-3:30","Canada","N%sT","1946"],["-3:30","StJohns","N%sT","1966","Mar","15","2:00"],["-4:00","StJohns","A%sT"]],"America/Halifax":[["-4:14:24","-","LMT","1902","Jun","15"],["-4:00","Halifax","A%sT","1918"],["-4:00","Canada","A%sT","1919"],["-4:00","Halifax","A%sT","1942","Feb","9","2:00s"],["-4:00","Canada","A%sT","1946"],["-4:00","Halifax","A%sT","1974"],["-4:00","Canada","A%sT"]],"America/Glace_Bay":[["-3:59:48","-","LMT","1902","Jun","15"],["-4:00","Canada","A%sT","1953"],["-4:00","Halifax","A%sT","1954"],["-4:00","-","AST","1972"],["-4:00","Halifax","A%sT","1974"],["-4:00","Canada","A%sT"]],"America/Moncton":[["-4:19:08","-","LMT","1883","Dec","9"],["-5:00","-","EST","1902","Jun","15"],["-4:00","Canada","A%sT","1933"],["-4:00","Moncton","A%sT","1942"],["-4:00","Canada","A%sT","1946"],["-4:00","Moncton","A%sT","1973"],["-4:00","Canada","A%sT","1993"],["-4:00","Moncton","A%sT","2007"],["-4:00","Canada","A%sT"]],"America/Blanc-Sablon":[["-3:48:28","-","LMT","1884"],["-4:00","Canada","A%sT","1970"],["-4:00","-","AST"]],"America/Montreal":[["-4:54:16","-","LMT","1884"],["-5:00","Mont","E%sT","1918"],["-5:00","Canada","E%sT","1919"],["-5:00","Mont","E%sT","1942","Feb","9","2:00s"],["-5:00","Canada","E%sT","1946"],["-5:00","Mont","E%sT","1974"],["-5:00","Canada","E%sT"]],"America/Toronto":[["-5:17:32","-","LMT","1895"],["-5:00","Canada","E%sT","1919"],["-5:00","Toronto","E%sT","1942","Feb","9","2:00s"],["-5:00","Canada","E%sT","1946"],["-5:00","Toronto","E%sT","1974"],["-5:00","Canada","E%sT"]],"America/Thunder_Bay":[["-5:57:00","-","LMT","1895"],["-6:00","-","CST","1910"],["-5:00","-","EST","1942"],["-5:00","Canada","E%sT","1970"],["-5:00","Mont","E%sT","1973"],["-5:00","-","EST","1974"],["-5:00","Canada","E%sT"]],"America/Nipigon":[["-5:53:04","-","LMT","1895"],["-5:00","Canada","E%sT","1940","Sep","29"],["-5:00","1:00","EDT","1942","Feb","9","2:00s"],["-5:00","Canada","E%sT"]],"America/Rainy_River":[["-6:18:16","-","LMT","1895"],["-6:00","Canada","C%sT","1940","Sep","29"],["-6:00","1:00","CDT","1942","Feb","9","2:00s"],["-6:00","Canada","C%sT"]],"America/Atikokan":[["-6:06:28","-","LMT","1895"],["-6:00","Canada","C%sT","1940","Sep","29"],["-6:00","1:00","CDT","1942","Feb","9","2:00s"],["-6:00","Canada","C%sT","1945","Sep","30","2:00"],["-5:00","-","EST"]],"America/Winnipeg":[["-6:28:36","-","LMT","1887","Jul","16"],["-6:00","Winn","C%sT","2006"],["-6:00","Canada","C%sT"]],"America/Regina":[["-6:58:36","-","LMT","1905","Sep"],["-7:00","Regina","M%sT","1960","Apr","lastSun","2:00"],["-6:00","-","CST"]],"America/Swift_Current":[["-7:11:20","-","LMT","1905","Sep"],["-7:00","Canada","M%sT","1946","Apr","lastSun","2:00"],["-7:00","Regina","M%sT","1950"],["-7:00","Swift","M%sT","1972","Apr","lastSun","2:00"],["-6:00","-","CST"]],"America/Edmonton":[["-7:33:52","-","LMT","1906","Sep"],["-7:00","Edm","M%sT","1987"],["-7:00","Canada","M%sT"]],"America/Vancouver":[["-8:12:28","-","LMT","1884"],["-8:00","Vanc","P%sT","1987"],["-8:00","Canada","P%sT"]],"America/Dawson_Creek":[["-8:00:56","-","LMT","1884"],["-8:00","Canada","P%sT","1947"],["-8:00","Vanc","P%sT","1972","Aug","30","2:00"],["-7:00","-","MST"]],"America/Pangnirtung":[["0","-","zzz","1921",""],["-4:00","NT_YK","A%sT","1995","Apr","Sun>=1","2:00"],["-5:00","Canada","E%sT","1999","Oct","31","2:00"],["-6:00","Canada","C%sT","2000","Oct","29","2:00"],["-5:00","Canada","E%sT"]],"America/Iqaluit":[["0","-","zzz","1942","Aug",""],["-5:00","NT_YK","E%sT","1999","Oct","31","2:00"],["-6:00","Canada","C%sT","2000","Oct","29","2:00"],["-5:00","Canada","E%sT"]],"America/Resolute":[["0","-","zzz","1947","Aug","31",""],["-6:00","NT_YK","C%sT","2000","Oct","29","2:00"],["-5:00","-","EST","2001","Apr","1","3:00"],["-6:00","Canada","C%sT","2006","Oct","29","2:00"],["-5:00","Resolute","%sT"]],"America/Rankin_Inlet":[["0","-","zzz","1957",""],["-6:00","NT_YK","C%sT","2000","Oct","29","2:00"],["-5:00","-","EST","2001","Apr","1","3:00"],["-6:00","Canada","C%sT"]],"America/Cambridge_Bay":[["0","-","zzz","1920",""],["-7:00","NT_YK","M%sT","1999","Oct","31","2:00"],["-6:00","Canada","C%sT","2000","Oct","29","2:00"],["-5:00","-","EST","2000","Nov","5","0:00"],["-6:00","-","CST","2001","Apr","1","3:00"],["-7:00","Canada","M%sT"]],"America/Yellowknife":[["0","-","zzz","1935",""],["-7:00","NT_YK","M%sT","1980"],["-7:00","Canada","M%sT"]],"America/Inuvik":[["0","-","zzz","1953",""],["-8:00","NT_YK","P%sT","1979","Apr","lastSun","2:00"],["-7:00","NT_YK","M%sT","1980"],["-7:00","Canada","M%sT"]],"America/Whitehorse":[["-9:00:12","-","LMT","1900","Aug","20"],["-9:00","NT_YK","Y%sT","1966","Jul","1","2:00"],["-8:00","NT_YK","P%sT","1980"],["-8:00","Canada","P%sT"]],"America/Dawson":[["-9:17:40","-","LMT","1900","Aug","20"],["-9:00","NT_YK","Y%sT","1973","Oct","28","0:00"],["-8:00","NT_YK","P%sT","1980"],["-8:00","Canada","P%sT"]],"America/Cancun":[["-5:47:04","-","LMT","1922","Jan","1","0:12:56"],["-6:00","-","CST","1981","Dec","23"],["-5:00","Mexico","E%sT","1998","Aug","2","2:00"],["-6:00","Mexico","C%sT"]],"America/Merida":[["-5:58:28","-","LMT","1922","Jan","1","0:01:32"],["-6:00","-","CST","1981","Dec","23"],["-5:00","-","EST","1982","Dec","2"],["-6:00","Mexico","C%sT"]],"America/Matamoros":[["-6:40:00","-","LMT","1921","Dec","31","23:20:00"],["-6:00","-","CST","1988"],["-6:00","US","C%sT","1989"],["-6:00","Mexico","C%sT","2010"],["-6:00","US","C%sT"]],"America/Monterrey":[["-6:41:16","-","LMT","1921","Dec","31","23:18:44"],["-6:00","-","CST","1988"],["-6:00","US","C%sT","1989"],["-6:00","Mexico","C%sT"]],"America/Mexico_City":[["-6:36:36","-","LMT","1922","Jan","1","0:23:24"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","Mexico","C%sT","2001","Sep","30","02:00"],["-6:00","-","CST","2002","Feb","20"],["-6:00","Mexico","C%sT"]],"America/Ojinaga":[["-6:57:40","-","LMT","1922","Jan","1","0:02:20"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","-","CST","1996"],["-6:00","Mexico","C%sT","1998"],["-6:00","-","CST","1998","Apr","Sun>=1","3:00"],["-7:00","Mexico","M%sT","2010"],["-7:00","US","M%sT"]],"America/Chihuahua":[["-7:04:20","-","LMT","1921","Dec","31","23:55:40"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","-","CST","1996"],["-6:00","Mexico","C%sT","1998"],["-6:00","-","CST","1998","Apr","Sun>=1","3:00"],["-7:00","Mexico","M%sT"]],"America/Hermosillo":[["-7:23:52","-","LMT","1921","Dec","31","23:36:08"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","-","CST","1942","Apr","24"],["-7:00","-","MST","1949","Jan","14"],["-8:00","-","PST","1970"],["-7:00","Mexico","M%sT","1999"],["-7:00","-","MST"]],"America/Mazatlan":[["-7:05:40","-","LMT","1921","Dec","31","23:54:20"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","-","CST","1942","Apr","24"],["-7:00","-","MST","1949","Jan","14"],["-8:00","-","PST","1970"],["-7:00","Mexico","M%sT"]],"America/Bahia_Banderas":[["-7:01:00","-","LMT","1921","Dec","31","23:59:00"],["-7:00","-","MST","1927","Jun","10","23:00"],["-6:00","-","CST","1930","Nov","15"],["-7:00","-","MST","1931","May","1","23:00"],["-6:00","-","CST","1931","Oct"],["-7:00","-","MST","1932","Apr","1"],["-6:00","-","CST","1942","Apr","24"],["-7:00","-","MST","1949","Jan","14"],["-8:00","-","PST","1970"],["-7:00","Mexico","M%sT","2010","Apr","4","2:00"],["-6:00","Mexico","C%sT"]],"America/Tijuana":[["-7:48:04","-","LMT","1922","Jan","1","0:11:56"],["-7:00","-","MST","1924"],["-8:00","-","PST","1927","Jun","10","23:00"],["-7:00","-","MST","1930","Nov","15"],["-8:00","-","PST","1931","Apr","1"],["-8:00","1:00","PDT","1931","Sep","30"],["-8:00","-","PST","1942","Apr","24"],["-8:00","1:00","PWT","1945","Aug","14","23:00u"],["-8:00","1:00","PPT","1945","Nov","12",""],["-8:00","-","PST","1948","Apr","5"],["-8:00","1:00","PDT","1949","Jan","14"],["-8:00","-","PST","1954"],["-8:00","CA","P%sT","1961"],["-8:00","-","PST","1976"],["-8:00","US","P%sT","1996"],["-8:00","Mexico","P%sT","2001"],["-8:00","US","P%sT","2002","Feb","20"],["-8:00","Mexico","P%sT","2010"],["-8:00","US","P%sT"]],"America/Santa_Isabel":[["-7:39:28","-","LMT","1922","Jan","1","0:20:32"],["-7:00","-","MST","1924"],["-8:00","-","PST","1927","Jun","10","23:00"],["-7:00","-","MST","1930","Nov","15"],["-8:00","-","PST","1931","Apr","1"],["-8:00","1:00","PDT","1931","Sep","30"],["-8:00","-","PST","1942","Apr","24"],["-8:00","1:00","PWT","1945","Aug","14","23:00u"],["-8:00","1:00","PPT","1945","Nov","12",""],["-8:00","-","PST","1948","Apr","5"],["-8:00","1:00","PDT","1949","Jan","14"],["-8:00","-","PST","1954"],["-8:00","CA","P%sT","1961"],["-8:00","-","PST","1976"],["-8:00","US","P%sT","1996"],["-8:00","Mexico","P%sT","2001"],["-8:00","US","P%sT","2002","Feb","20"],["-8:00","Mexico","P%sT"]],"America/Anguilla":[["-4:12:16","-","LMT","1912","Mar","2"],["-4:00","-","AST"]],"America/Antigua":[["-4:07:12","-","LMT","1912","Mar","2"],["-5:00","-","EST","1951"],["-4:00","-","AST"]],"America/Nassau":[["-5:09:24","-","LMT","1912","Mar","2"],["-5:00","Bahamas","E%sT","1976"],["-5:00","US","E%sT"]],"America/Barbados":[["-3:58:28","-","LMT","1924",""],["-3:58:28","-","BMT","1932",""],["-4:00","Barb","A%sT"]],"America/Belize":[["-5:52:48","-","LMT","1912","Apr"],["-6:00","Belize","C%sT"]],"Atlantic/Bermuda":[["-4:19:04","-","LMT","1930","Jan","1","2:00",""],["-4:00","-","AST","1974","Apr","28","2:00"],["-4:00","Bahamas","A%sT","1976"],["-4:00","US","A%sT"]],"America/Cayman":[["-5:25:32","-","LMT","1890",""],["-5:07:12","-","KMT","1912","Feb",""],["-5:00","-","EST"]],"America/Costa_Rica":[["-5:36:20","-","LMT","1890",""],["-5:36:20","-","SJMT","1921","Jan","15",""],["-6:00","CR","C%sT"]],"America/Havana":[["-5:29:28","-","LMT","1890"],["-5:29:36","-","HMT","1925","Jul","19","12:00",""],["-5:00","Cuba","C%sT"]],"America/Dominica":[["-4:05:36","-","LMT","1911","Jul","1","0:01",""],["-4:00","-","AST"]],"America/Santo_Domingo":[["-4:39:36","-","LMT","1890"],["-4:40","-","SDMT","1933","Apr","1","12:00",""],["-5:00","DR","E%sT","1974","Oct","27"],["-4:00","-","AST","2000","Oct","29","02:00"],["-5:00","US","E%sT","2000","Dec","3","01:00"],["-4:00","-","AST"]],"America/El_Salvador":[["-5:56:48","-","LMT","1921",""],["-6:00","Salv","C%sT"]],"America/Grenada":[["-4:07:00","-","LMT","1911","Jul",""],["-4:00","-","AST"]],"America/Guadeloupe":[["-4:06:08","-","LMT","1911","Jun","8",""],["-4:00","-","AST"]],"America/St_Barthelemy":"America/Guadeloupe","America/Marigot":"America/Guadeloupe","America/Guatemala":[["-6:02:04","-","LMT","1918","Oct","5"],["-6:00","Guat","C%sT"]],"America/Port-au-Prince":[["-4:49:20","-","LMT","1890"],["-4:49","-","PPMT","1917","Jan","24","12:00",""],["-5:00","Haiti","E%sT"]],"America/Tegucigalpa":[["-5:48:52","-","LMT","1921","Apr"],["-6:00","Hond","C%sT"]],"America/Jamaica":[["-5:07:12","-","LMT","1890",""],["-5:07:12","-","KMT","1912","Feb",""],["-5:00","-","EST","1974","Apr","28","2:00"],["-5:00","US","E%sT","1984"],["-5:00","-","EST"]],"America/Martinique":[["-4:04:20","-","LMT","1890",""],["-4:04:20","-","FFMT","1911","May",""],["-4:00","-","AST","1980","Apr","6"],["-4:00","1:00","ADT","1980","Sep","28"],["-4:00","-","AST"]],"America/Montserrat":[["-4:08:52","-","LMT","1911","Jul","1","0:01",""],["-4:00","-","AST"]],"America/Managua":[["-5:45:08","-","LMT","1890"],["-5:45:12","-","MMT","1934","Jun","23",""],["-6:00","-","CST","1973","May"],["-5:00","-","EST","1975","Feb","16"],["-6:00","Nic","C%sT","1992","Jan","1","4:00"],["-5:00","-","EST","1992","Sep","24"],["-6:00","-","CST","1993"],["-5:00","-","EST","1997"],["-6:00","Nic","C%sT"]],"America/Panama":[["-5:18:08","-","LMT","1890"],["-5:19:36","-","CMT","1908","Apr","22",""],["-5:00","-","EST"]],"America/Puerto_Rico":[["-4:24:25","-","LMT","1899","Mar","28","12:00",""],["-4:00","-","AST","1942","May","3"],["-4:00","US","A%sT","1946"],["-4:00","-","AST"]],"America/St_Kitts":[["-4:10:52","-","LMT","1912","Mar","2",""],["-4:00","-","AST"]],"America/St_Lucia":[["-4:04:00","-","LMT","1890",""],["-4:04:00","-","CMT","1912",""],["-4:00","-","AST"]],"America/Miquelon":[["-3:44:40","-","LMT","1911","May","15",""],["-4:00","-","AST","1980","May"],["-3:00","-","PMST","1987",""],["-3:00","Canada","PM%sT"]],"America/St_Vincent":[["-4:04:56","-","LMT","1890",""],["-4:04:56","-","KMT","1912",""],["-4:00","-","AST"]],"America/Grand_Turk":[["-4:44:32","-","LMT","1890"],["-5:07:12","-","KMT","1912","Feb",""],["-5:00","TC","E%sT"]],"America/Tortola":[["-4:18:28","-","LMT","1911","Jul",""],["-4:00","-","AST"]],"America/St_Thomas":[["-4:19:44","-","LMT","1911","Jul",""],["-4:00","-","AST"]]};
14412 timezoneJS.timezone.rules = {"GB-Eire":[["1916","only","-","May","21","2:00s","1:00","BST"],["1916","only","-","Oct","1","2:00s","0","GMT"],["1917","only","-","Apr","8","2:00s","1:00","BST"],["1917","only","-","Sep","17","2:00s","0","GMT"],["1918","only","-","Mar","24","2:00s","1:00","BST"],["1918","only","-","Sep","30","2:00s","0","GMT"],["1919","only","-","Mar","30","2:00s","1:00","BST"],["1919","only","-","Sep","29","2:00s","0","GMT"],["1920","only","-","Mar","28","2:00s","1:00","BST"],["1920","only","-","Oct","25","2:00s","0","GMT"],["1921","only","-","Apr","3","2:00s","1:00","BST"],["1921","only","-","Oct","3","2:00s","0","GMT"],["1922","only","-","Mar","26","2:00s","1:00","BST"],["1922","only","-","Oct","8","2:00s","0","GMT"],["1923","only","-","Apr","Sun>=16","2:00s","1:00","BST"],["1923","1924","-","Sep","Sun>=16","2:00s","0","GMT"],["1924","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1925","1926","-","Apr","Sun>=16","2:00s","1:00","BST"],["1925","1938","-","Oct","Sun>=2","2:00s","0","GMT"],["1927","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1928","1929","-","Apr","Sun>=16","2:00s","1:00","BST"],["1930","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1931","1932","-","Apr","Sun>=16","2:00s","1:00","BST"],["1933","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1934","only","-","Apr","Sun>=16","2:00s","1:00","BST"],["1935","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1936","1937","-","Apr","Sun>=16","2:00s","1:00","BST"],["1938","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1939","only","-","Apr","Sun>=16","2:00s","1:00","BST"],["1939","only","-","Nov","Sun>=16","2:00s","0","GMT"],["1940","only","-","Feb","Sun>=23","2:00s","1:00","BST"],["1941","only","-","May","Sun>=2","1:00s","2:00","BDST"],["1941","1943","-","Aug","Sun>=9","1:00s","1:00","BST"],["1942","1944","-","Apr","Sun>=2","1:00s","2:00","BDST"],["1944","only","-","Sep","Sun>=16","1:00s","1:00","BST"],["1945","only","-","Apr","Mon>=2","1:00s","2:00","BDST"],["1945","only","-","Jul","Sun>=9","1:00s","1:00","BST"],["1945","1946","-","Oct","Sun>=2","2:00s","0","GMT"],["1946","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1947","only","-","Mar","16","2:00s","1:00","BST"],["1947","only","-","Apr","13","1:00s","2:00","BDST"],["1947","only","-","Aug","10","1:00s","1:00","BST"],["1947","only","-","Nov","2","2:00s","0","GMT"],["1948","only","-","Mar","14","2:00s","1:00","BST"],["1948","only","-","Oct","31","2:00s","0","GMT"],["1949","only","-","Apr","3","2:00s","1:00","BST"],["1949","only","-","Oct","30","2:00s","0","GMT"],["1950","1952","-","Apr","Sun>=14","2:00s","1:00","BST"],["1950","1952","-","Oct","Sun>=21","2:00s","0","GMT"],["1953","only","-","Apr","Sun>=16","2:00s","1:00","BST"],["1953","1960","-","Oct","Sun>=2","2:00s","0","GMT"],["1954","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1955","1956","-","Apr","Sun>=16","2:00s","1:00","BST"],["1957","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1958","1959","-","Apr","Sun>=16","2:00s","1:00","BST"],["1960","only","-","Apr","Sun>=9","2:00s","1:00","BST"],["1961","1963","-","Mar","lastSun","2:00s","1:00","BST"],["1961","1968","-","Oct","Sun>=23","2:00s","0","GMT"],["1964","1967","-","Mar","Sun>=19","2:00s","1:00","BST"],["1968","only","-","Feb","18","2:00s","1:00","BST"],["1972","1980","-","Mar","Sun>=16","2:00s","1:00","BST"],["1972","1980","-","Oct","Sun>=23","2:00s","0","GMT"],["1981","1995","-","Mar","lastSun","1:00u","1:00","BST"],["1981","1989","-","Oct","Sun>=23","1:00u","0","GMT"],["1990","1995","-","Oct","Sun>=22","1:00u","0","GMT"]],"EU":[["1977","1980","-","Apr","Sun>=1","1:00u","1:00","S"],["1977","only","-","Sep","lastSun","1:00u","0","-"],["1978","only","-","Oct","1","1:00u","0","-"],["1979","1995","-","Sep","lastSun","1:00u","0","-"],["1981","max","-","Mar","lastSun","1:00u","1:00","S"],["1996","max","-","Oct","lastSun","1:00u","0","-"]],"W-Eur":[["1977","1980","-","Apr","Sun>=1","1:00s","1:00","S"],["1977","only","-","Sep","lastSun","1:00s","0","-"],["1978","only","-","Oct","1","1:00s","0","-"],["1979","1995","-","Sep","lastSun","1:00s","0","-"],["1981","max","-","Mar","lastSun","1:00s","1:00","S"],["1996","max","-","Oct","lastSun","1:00s","0","-"]],"C-Eur":[["1916","only","-","Apr","30","23:00","1:00","S"],["1916","only","-","Oct","1","1:00","0","-"],["1917","1918","-","Apr","Mon>=15","2:00s","1:00","S"],["1917","1918","-","Sep","Mon>=15","2:00s","0","-"],["1940","only","-","Apr","1","2:00s","1:00","S"],["1942","only","-","Nov","2","2:00s","0","-"],["1943","only","-","Mar","29","2:00s","1:00","S"],["1943","only","-","Oct","4","2:00s","0","-"],["1944","1945","-","Apr","Mon>=1","2:00s","1:00","S"],["1944","only","-","Oct","2","2:00s","0","-"],["1945","only","-","Sep","16","2:00s","0","-"],["1977","1980","-","Apr","Sun>=1","2:00s","1:00","S"],["1977","only","-","Sep","lastSun","2:00s","0","-"],["1978","only","-","Oct","1","2:00s","0","-"],["1979","1995","-","Sep","lastSun","2:00s","0","-"],["1981","max","-","Mar","lastSun","2:00s","1:00","S"],["1996","max","-","Oct","lastSun","2:00s","0","-"]],"E-Eur":[["1977","1980","-","Apr","Sun>=1","0:00","1:00","S"],["1977","only","-","Sep","lastSun","0:00","0","-"],["1978","only","-","Oct","1","0:00","0","-"],["1979","1995","-","Sep","lastSun","0:00","0","-"],["1981","max","-","Mar","lastSun","0:00","1:00","S"],["1996","max","-","Oct","lastSun","0:00","0","-"]],"Russia":[["1917","only","-","Jul","1","23:00","1:00","MST",""],["1917","only","-","Dec","28","0:00","0","MMT",""],["1918","only","-","May","31","22:00","2:00","MDST",""],["1918","only","-","Sep","16","1:00","1:00","MST"],["1919","only","-","May","31","23:00","2:00","MDST"],["1919","only","-","Jul","1","2:00","1:00","S"],["1919","only","-","Aug","16","0:00","0","-"],["1921","only","-","Feb","14","23:00","1:00","S"],["1921","only","-","Mar","20","23:00","2:00","M",""],["1921","only","-","Sep","1","0:00","1:00","S"],["1921","only","-","Oct","1","0:00","0","-"],["1981","1984","-","Apr","1","0:00","1:00","S"],["1981","1983","-","Oct","1","0:00","0","-"],["1984","1991","-","Sep","lastSun","2:00s","0","-"],["1985","1991","-","Mar","lastSun","2:00s","1:00","S"],["1992","only","-","Mar","lastSat","23:00","1:00","S"],["1992","only","-","Sep","lastSat","23:00","0","-"],["1993","max","-","Mar","lastSun","2:00s","1:00","S"],["1993","1995","-","Sep","lastSun","2:00s","0","-"],["1996","max","-","Oct","lastSun","2:00s","0","-"]],"Albania":[["1940","only","-","Jun","16","0:00","1:00","S"],["1942","only","-","Nov","2","3:00","0","-"],["1943","only","-","Mar","29","2:00","1:00","S"],["1943","only","-","Apr","10","3:00","0","-"],["1974","only","-","May","4","0:00","1:00","S"],["1974","only","-","Oct","2","0:00","0","-"],["1975","only","-","May","1","0:00","1:00","S"],["1975","only","-","Oct","2","0:00","0","-"],["1976","only","-","May","2","0:00","1:00","S"],["1976","only","-","Oct","3","0:00","0","-"],["1977","only","-","May","8","0:00","1:00","S"],["1977","only","-","Oct","2","0:00","0","-"],["1978","only","-","May","6","0:00","1:00","S"],["1978","only","-","Oct","1","0:00","0","-"],["1979","only","-","May","5","0:00","1:00","S"],["1979","only","-","Sep","30","0:00","0","-"],["1980","only","-","May","3","0:00","1:00","S"],["1980","only","-","Oct","4","0:00","0","-"],["1981","only","-","Apr","26","0:00","1:00","S"],["1981","only","-","Sep","27","0:00","0","-"],["1982","only","-","May","2","0:00","1:00","S"],["1982","only","-","Oct","3","0:00","0","-"],["1983","only","-","Apr","18","0:00","1:00","S"],["1983","only","-","Oct","1","0:00","0","-"],["1984","only","-","Apr","1","0:00","1:00","S"]],"Austria":[["1920","only","-","Apr","5","2:00s","1:00","S"],["1920","only","-","Sep","13","2:00s","0","-"],["1946","only","-","Apr","14","2:00s","1:00","S"],["1946","1948","-","Oct","Sun>=1","2:00s","0","-"],["1947","only","-","Apr","6","2:00s","1:00","S"],["1948","only","-","Apr","18","2:00s","1:00","S"],["1980","only","-","Apr","6","0:00","1:00","S"],["1980","only","-","Sep","28","0:00","0","-"]],"Belgium":[["1918","only","-","Mar","9","0:00s","1:00","S"],["1918","1919","-","Oct","Sat>=1","23:00s","0","-"],["1919","only","-","Mar","1","23:00s","1:00","S"],["1920","only","-","Feb","14","23:00s","1:00","S"],["1920","only","-","Oct","23","23:00s","0","-"],["1921","only","-","Mar","14","23:00s","1:00","S"],["1921","only","-","Oct","25","23:00s","0","-"],["1922","only","-","Mar","25","23:00s","1:00","S"],["1922","1927","-","Oct","Sat>=1","23:00s","0","-"],["1923","only","-","Apr","21","23:00s","1:00","S"],["1924","only","-","Mar","29","23:00s","1:00","S"],["1925","only","-","Apr","4","23:00s","1:00","S"],["1926","only","-","Apr","17","23:00s","1:00","S"],["1927","only","-","Apr","9","23:00s","1:00","S"],["1928","only","-","Apr","14","23:00s","1:00","S"],["1928","1938","-","Oct","Sun>=2","2:00s","0","-"],["1929","only","-","Apr","21","2:00s","1:00","S"],["1930","only","-","Apr","13","2:00s","1:00","S"],["1931","only","-","Apr","19","2:00s","1:00","S"],["1932","only","-","Apr","3","2:00s","1:00","S"],["1933","only","-","Mar","26","2:00s","1:00","S"],["1934","only","-","Apr","8","2:00s","1:00","S"],["1935","only","-","Mar","31","2:00s","1:00","S"],["1936","only","-","Apr","19","2:00s","1:00","S"],["1937","only","-","Apr","4","2:00s","1:00","S"],["1938","only","-","Mar","27","2:00s","1:00","S"],["1939","only","-","Apr","16","2:00s","1:00","S"],["1939","only","-","Nov","19","2:00s","0","-"],["1940","only","-","Feb","25","2:00s","1:00","S"],["1944","only","-","Sep","17","2:00s","0","-"],["1945","only","-","Apr","2","2:00s","1:00","S"],["1945","only","-","Sep","16","2:00s","0","-"],["1946","only","-","May","19","2:00s","1:00","S"],["1946","only","-","Oct","7","2:00s","0","-"]],"Bulg":[["1979","only","-","Mar","31","23:00","1:00","S"],["1979","only","-","Oct","1","1:00","0","-"],["1980","1982","-","Apr","Sat>=1","23:00","1:00","S"],["1980","only","-","Sep","29","1:00","0","-"],["1981","only","-","Sep","27","2:00","0","-"]],"Czech":[["1945","only","-","Apr","8","2:00s","1:00","S"],["1945","only","-","Nov","18","2:00s","0","-"],["1946","only","-","May","6","2:00s","1:00","S"],["1946","1949","-","Oct","Sun>=1","2:00s","0","-"],["1947","only","-","Apr","20","2:00s","1:00","S"],["1948","only","-","Apr","18","2:00s","1:00","S"],["1949","only","-","Apr","9","2:00s","1:00","S"]],"Denmark":[["1916","only","-","May","14","23:00","1:00","S"],["1916","only","-","Sep","30","23:00","0","-"],["1940","only","-","May","15","0:00","1:00","S"],["1945","only","-","Apr","2","2:00s","1:00","S"],["1945","only","-","Aug","15","2:00s","0","-"],["1946","only","-","May","1","2:00s","1:00","S"],["1946","only","-","Sep","1","2:00s","0","-"],["1947","only","-","May","4","2:00s","1:00","S"],["1947","only","-","Aug","10","2:00s","0","-"],["1948","only","-","May","9","2:00s","1:00","S"],["1948","only","-","Aug","8","2:00s","0","-"]],"Thule":[["1991","1992","-","Mar","lastSun","2:00","1:00","D"],["1991","1992","-","Sep","lastSun","2:00","0","S"],["1993","2006","-","Apr","Sun>=1","2:00","1:00","D"],["1993","2006","-","Oct","lastSun","2:00","0","S"],["2007","max","-","Mar","Sun>=8","2:00","1:00","D"],["2007","max","-","Nov","Sun>=1","2:00","0","S"]],"Finland":[["1942","only","-","Apr","3","0:00","1:00","S"],["1942","only","-","Oct","3","0:00","0","-"],["1981","1982","-","Mar","lastSun","2:00","1:00","S"],["1981","1982","-","Sep","lastSun","3:00","0","-"]],"France":[["1916","only","-","Jun","14","23:00s","1:00","S"],["1916","1919","-","Oct","Sun>=1","23:00s","0","-"],["1917","only","-","Mar","24","23:00s","1:00","S"],["1918","only","-","Mar","9","23:00s","1:00","S"],["1919","only","-","Mar","1","23:00s","1:00","S"],["1920","only","-","Feb","14","23:00s","1:00","S"],["1920","only","-","Oct","23","23:00s","0","-"],["1921","only","-","Mar","14","23:00s","1:00","S"],["1921","only","-","Oct","25","23:00s","0","-"],["1922","only","-","Mar","25","23:00s","1:00","S"],["1922","1938","-","Oct","Sat>=1","23:00s","0","-"],["1923","only","-","May","26","23:00s","1:00","S"],["1924","only","-","Mar","29","23:00s","1:00","S"],["1925","only","-","Apr","4","23:00s","1:00","S"],["1926","only","-","Apr","17","23:00s","1:00","S"],["1927","only","-","Apr","9","23:00s","1:00","S"],["1928","only","-","Apr","14","23:00s","1:00","S"],["1929","only","-","Apr","20","23:00s","1:00","S"],["1930","only","-","Apr","12","23:00s","1:00","S"],["1931","only","-","Apr","18","23:00s","1:00","S"],["1932","only","-","Apr","2","23:00s","1:00","S"],["1933","only","-","Mar","25","23:00s","1:00","S"],["1934","only","-","Apr","7","23:00s","1:00","S"],["1935","only","-","Mar","30","23:00s","1:00","S"],["1936","only","-","Apr","18","23:00s","1:00","S"],["1937","only","-","Apr","3","23:00s","1:00","S"],["1938","only","-","Mar","26","23:00s","1:00","S"],["1939","only","-","Apr","15","23:00s","1:00","S"],["1939","only","-","Nov","18","23:00s","0","-"],["1940","only","-","Feb","25","2:00","1:00","S"],["1941","only","-","May","5","0:00","2:00","M",""],["1941","only","-","Oct","6","0:00","1:00","S"],["1942","only","-","Mar","9","0:00","2:00","M"],["1942","only","-","Nov","2","3:00","1:00","S"],["1943","only","-","Mar","29","2:00","2:00","M"],["1943","only","-","Oct","4","3:00","1:00","S"],["1944","only","-","Apr","3","2:00","2:00","M"],["1944","only","-","Oct","8","1:00","1:00","S"],["1945","only","-","Apr","2","2:00","2:00","M"],["1945","only","-","Sep","16","3:00","0","-"],["1976","only","-","Mar","28","1:00","1:00","S"],["1976","only","-","Sep","26","1:00","0","-"]],"Germany":[["1946","only","-","Apr","14","2:00s","1:00","S"],["1946","only","-","Oct","7","2:00s","0","-"],["1947","1949","-","Oct","Sun>=1","2:00s","0","-"],["1947","only","-","Apr","6","3:00s","1:00","S"],["1947","only","-","May","11","2:00s","2:00","M"],["1947","only","-","Jun","29","3:00","1:00","S"],["1948","only","-","Apr","18","2:00s","1:00","S"],["1949","only","-","Apr","10","2:00s","1:00","S"]],"SovietZone":[["1945","only","-","May","24","2:00","2:00","M",""],["1945","only","-","Sep","24","3:00","1:00","S"],["1945","only","-","Nov","18","2:00s","0","-"]],"Greece":[["1932","only","-","Jul","7","0:00","1:00","S"],["1932","only","-","Sep","1","0:00","0","-"],["1941","only","-","Apr","7","0:00","1:00","S"],["1942","only","-","Nov","2","3:00","0","-"],["1943","only","-","Mar","30","0:00","1:00","S"],["1943","only","-","Oct","4","0:00","0","-"],["1952","only","-","Jul","1","0:00","1:00","S"],["1952","only","-","Nov","2","0:00","0","-"],["1975","only","-","Apr","12","0:00s","1:00","S"],["1975","only","-","Nov","26","0:00s","0","-"],["1976","only","-","Apr","11","2:00s","1:00","S"],["1976","only","-","Oct","10","2:00s","0","-"],["1977","1978","-","Apr","Sun>=1","2:00s","1:00","S"],["1977","only","-","Sep","26","2:00s","0","-"],["1978","only","-","Sep","24","4:00","0","-"],["1979","only","-","Apr","1","9:00","1:00","S"],["1979","only","-","Sep","29","2:00","0","-"],["1980","only","-","Apr","1","0:00","1:00","S"],["1980","only","-","Sep","28","0:00","0","-"]],"Hungary":[["1918","only","-","Apr","1","3:00","1:00","S"],["1918","only","-","Sep","29","3:00","0","-"],["1919","only","-","Apr","15","3:00","1:00","S"],["1919","only","-","Sep","15","3:00","0","-"],["1920","only","-","Apr","5","3:00","1:00","S"],["1920","only","-","Sep","30","3:00","0","-"],["1945","only","-","May","1","23:00","1:00","S"],["1945","only","-","Nov","3","0:00","0","-"],["1946","only","-","Mar","31","2:00s","1:00","S"],["1946","1949","-","Oct","Sun>=1","2:00s","0","-"],["1947","1949","-","Apr","Sun>=4","2:00s","1:00","S"],["1950","only","-","Apr","17","2:00s","1:00","S"],["1950","only","-","Oct","23","2:00s","0","-"],["1954","1955","-","May","23","0:00","1:00","S"],["1954","1955","-","Oct","3","0:00","0","-"],["1956","only","-","Jun","Sun>=1","0:00","1:00","S"],["1956","only","-","Sep","lastSun","0:00","0","-"],["1957","only","-","Jun","Sun>=1","1:00","1:00","S"],["1957","only","-","Sep","lastSun","3:00","0","-"],["1980","only","-","Apr","6","1:00","1:00","S"]],"Iceland":[["1917","1918","-","Feb","19","23:00","1:00","S"],["1917","only","-","Oct","21","1:00","0","-"],["1918","only","-","Nov","16","1:00","0","-"],["1939","only","-","Apr","29","23:00","1:00","S"],["1939","only","-","Nov","29","2:00","0","-"],["1940","only","-","Feb","25","2:00","1:00","S"],["1940","only","-","Nov","3","2:00","0","-"],["1941","only","-","Mar","2","1:00s","1:00","S"],["1941","only","-","Nov","2","1:00s","0","-"],["1942","only","-","Mar","8","1:00s","1:00","S"],["1942","only","-","Oct","25","1:00s","0","-"],["1943","1946","-","Mar","Sun>=1","1:00s","1:00","S"],["1943","1948","-","Oct","Sun>=22","1:00s","0","-"],["1947","1967","-","Apr","Sun>=1","1:00s","1:00","S"],["1949","only","-","Oct","30","1:00s","0","-"],["1950","1966","-","Oct","Sun>=22","1:00s","0","-"],["1967","only","-","Oct","29","1:00s","0","-"]],"Italy":[["1916","only","-","Jun","3","0:00s","1:00","S"],["1916","only","-","Oct","1","0:00s","0","-"],["1917","only","-","Apr","1","0:00s","1:00","S"],["1917","only","-","Sep","30","0:00s","0","-"],["1918","only","-","Mar","10","0:00s","1:00","S"],["1918","1919","-","Oct","Sun>=1","0:00s","0","-"],["1919","only","-","Mar","2","0:00s","1:00","S"],["1920","only","-","Mar","21","0:00s","1:00","S"],["1920","only","-","Sep","19","0:00s","0","-"],["1940","only","-","Jun","15","0:00s","1:00","S"],["1944","only","-","Sep","17","0:00s","0","-"],["1945","only","-","Apr","2","2:00","1:00","S"],["1945","only","-","Sep","15","0:00s","0","-"],["1946","only","-","Mar","17","2:00s","1:00","S"],["1946","only","-","Oct","6","2:00s","0","-"],["1947","only","-","Mar","16","0:00s","1:00","S"],["1947","only","-","Oct","5","0:00s","0","-"],["1948","only","-","Feb","29","2:00s","1:00","S"],["1948","only","-","Oct","3","2:00s","0","-"],["1966","1968","-","May","Sun>=22","0:00","1:00","S"],["1966","1969","-","Sep","Sun>=22","0:00","0","-"],["1969","only","-","Jun","1","0:00","1:00","S"],["1970","only","-","May","31","0:00","1:00","S"],["1970","only","-","Sep","lastSun","0:00","0","-"],["1971","1972","-","May","Sun>=22","0:00","1:00","S"],["1971","only","-","Sep","lastSun","1:00","0","-"],["1972","only","-","Oct","1","0:00","0","-"],["1973","only","-","Jun","3","0:00","1:00","S"],["1973","1974","-","Sep","lastSun","0:00","0","-"],["1974","only","-","May","26","0:00","1:00","S"],["1975","only","-","Jun","1","0:00s","1:00","S"],["1975","1977","-","Sep","lastSun","0:00s","0","-"],["1976","only","-","May","30","0:00s","1:00","S"],["1977","1979","-","May","Sun>=22","0:00s","1:00","S"],["1978","only","-","Oct","1","0:00s","0","-"],["1979","only","-","Sep","30","0:00s","0","-"]],"Latvia":[["1989","1996","-","Mar","lastSun","2:00s","1:00","S"],["1989","1996","-","Sep","lastSun","2:00s","0","-"]],"Lux":[["1916","only","-","May","14","23:00","1:00","S"],["1916","only","-","Oct","1","1:00","0","-"],["1917","only","-","Apr","28","23:00","1:00","S"],["1917","only","-","Sep","17","1:00","0","-"],["1918","only","-","Apr","Mon>=15","2:00s","1:00","S"],["1918","only","-","Sep","Mon>=15","2:00s","0","-"],["1919","only","-","Mar","1","23:00","1:00","S"],["1919","only","-","Oct","5","3:00","0","-"],["1920","only","-","Feb","14","23:00","1:00","S"],["1920","only","-","Oct","24","2:00","0","-"],["1921","only","-","Mar","14","23:00","1:00","S"],["1921","only","-","Oct","26","2:00","0","-"],["1922","only","-","Mar","25","23:00","1:00","S"],["1922","only","-","Oct","Sun>=2","1:00","0","-"],["1923","only","-","Apr","21","23:00","1:00","S"],["1923","only","-","Oct","Sun>=2","2:00","0","-"],["1924","only","-","Mar","29","23:00","1:00","S"],["1924","1928","-","Oct","Sun>=2","1:00","0","-"],["1925","only","-","Apr","5","23:00","1:00","S"],["1926","only","-","Apr","17","23:00","1:00","S"],["1927","only","-","Apr","9","23:00","1:00","S"],["1928","only","-","Apr","14","23:00","1:00","S"],["1929","only","-","Apr","20","23:00","1:00","S"]],"Malta":[["1973","only","-","Mar","31","0:00s","1:00","S"],["1973","only","-","Sep","29","0:00s","0","-"],["1974","only","-","Apr","21","0:00s","1:00","S"],["1974","only","-","Sep","16","0:00s","0","-"],["1975","1979","-","Apr","Sun>=15","2:00","1:00","S"],["1975","1980","-","Sep","Sun>=15","2:00","0","-"],["1980","only","-","Mar","31","2:00","1:00","S"]],"Neth":[["1916","only","-","May","1","0:00","1:00","NST",""],["1916","only","-","Oct","1","0:00","0","AMT",""],["1917","only","-","Apr","16","2:00s","1:00","NST"],["1917","only","-","Sep","17","2:00s","0","AMT"],["1918","1921","-","Apr","Mon>=1","2:00s","1:00","NST"],["1918","1921","-","Sep","lastMon","2:00s","0","AMT"],["1922","only","-","Mar","lastSun","2:00s","1:00","NST"],["1922","1936","-","Oct","Sun>=2","2:00s","0","AMT"],["1923","only","-","Jun","Fri>=1","2:00s","1:00","NST"],["1924","only","-","Mar","lastSun","2:00s","1:00","NST"],["1925","only","-","Jun","Fri>=1","2:00s","1:00","NST"],["1926","1931","-","May","15","2:00s","1:00","NST"],["1932","only","-","May","22","2:00s","1:00","NST"],["1933","1936","-","May","15","2:00s","1:00","NST"],["1937","only","-","May","22","2:00s","1:00","NST"],["1937","only","-","Jul","1","0:00","1:00","S"],["1937","1939","-","Oct","Sun>=2","2:00s","0","-"],["1938","1939","-","May","15","2:00s","1:00","S"],["1945","only","-","Apr","2","2:00s","1:00","S"],["1945","only","-","Sep","16","2:00s","0","-"]],"Norway":[["1916","only","-","May","22","1:00","1:00","S"],["1916","only","-","Sep","30","0:00","0","-"],["1945","only","-","Apr","2","2:00s","1:00","S"],["1945","only","-","Oct","1","2:00s","0","-"],["1959","1964","-","Mar","Sun>=15","2:00s","1:00","S"],["1959","1965","-","Sep","Sun>=15","2:00s","0","-"],["1965","only","-","Apr","25","2:00s","1:00","S"]],"Poland":[["1918","1919","-","Sep","16","2:00s","0","-"],["1919","only","-","Apr","15","2:00s","1:00","S"],["1944","only","-","Apr","3","2:00s","1:00","S"],["1944","only","-","Oct","4","2:00","0","-"],["1945","only","-","Apr","29","0:00","1:00","S"],["1945","only","-","Nov","1","0:00","0","-"],["1946","only","-","Apr","14","0:00s","1:00","S"],["1946","only","-","Oct","7","2:00s","0","-"],["1947","only","-","May","4","2:00s","1:00","S"],["1947","1949","-","Oct","Sun>=1","2:00s","0","-"],["1948","only","-","Apr","18","2:00s","1:00","S"],["1949","only","-","Apr","10","2:00s","1:00","S"],["1957","only","-","Jun","2","1:00s","1:00","S"],["1957","1958","-","Sep","lastSun","1:00s","0","-"],["1958","only","-","Mar","30","1:00s","1:00","S"],["1959","only","-","May","31","1:00s","1:00","S"],["1959","1961","-","Oct","Sun>=1","1:00s","0","-"],["1960","only","-","Apr","3","1:00s","1:00","S"],["1961","1964","-","May","lastSun","1:00s","1:00","S"],["1962","1964","-","Sep","lastSun","1:00s","0","-"]],"Port":[["1916","only","-","Jun","17","23:00","1:00","S"],["1916","only","-","Nov","1","1:00","0","-"],["1917","only","-","Feb","28","23:00s","1:00","S"],["1917","1921","-","Oct","14","23:00s","0","-"],["1918","only","-","Mar","1","23:00s","1:00","S"],["1919","only","-","Feb","28","23:00s","1:00","S"],["1920","only","-","Feb","29","23:00s","1:00","S"],["1921","only","-","Feb","28","23:00s","1:00","S"],["1924","only","-","Apr","16","23:00s","1:00","S"],["1924","only","-","Oct","14","23:00s","0","-"],["1926","only","-","Apr","17","23:00s","1:00","S"],["1926","1929","-","Oct","Sat>=1","23:00s","0","-"],["1927","only","-","Apr","9","23:00s","1:00","S"],["1928","only","-","Apr","14","23:00s","1:00","S"],["1929","only","-","Apr","20","23:00s","1:00","S"],["1931","only","-","Apr","18","23:00s","1:00","S"],["1931","1932","-","Oct","Sat>=1","23:00s","0","-"],["1932","only","-","Apr","2","23:00s","1:00","S"],["1934","only","-","Apr","7","23:00s","1:00","S"],["1934","1938","-","Oct","Sat>=1","23:00s","0","-"],["1935","only","-","Mar","30","23:00s","1:00","S"],["1936","only","-","Apr","18","23:00s","1:00","S"],["1937","only","-","Apr","3","23:00s","1:00","S"],["1938","only","-","Mar","26","23:00s","1:00","S"],["1939","only","-","Apr","15","23:00s","1:00","S"],["1939","only","-","Nov","18","23:00s","0","-"],["1940","only","-","Feb","24","23:00s","1:00","S"],["1940","1941","-","Oct","5","23:00s","0","-"],["1941","only","-","Apr","5","23:00s","1:00","S"],["1942","1945","-","Mar","Sat>=8","23:00s","1:00","S"],["1942","only","-","Apr","25","22:00s","2:00","M",""],["1942","only","-","Aug","15","22:00s","1:00","S"],["1942","1945","-","Oct","Sat>=24","23:00s","0","-"],["1943","only","-","Apr","17","22:00s","2:00","M"],["1943","1945","-","Aug","Sat>=25","22:00s","1:00","S"],["1944","1945","-","Apr","Sat>=21","22:00s","2:00","M"],["1946","only","-","Apr","Sat>=1","23:00s","1:00","S"],["1946","only","-","Oct","Sat>=1","23:00s","0","-"],["1947","1949","-","Apr","Sun>=1","2:00s","1:00","S"],["1947","1949","-","Oct","Sun>=1","2:00s","0","-"],["1951","1965","-","Apr","Sun>=1","2:00s","1:00","S"],["1951","1965","-","Oct","Sun>=1","2:00s","0","-"],["1977","only","-","Mar","27","0:00s","1:00","S"],["1977","only","-","Sep","25","0:00s","0","-"],["1978","1979","-","Apr","Sun>=1","0:00s","1:00","S"],["1978","only","-","Oct","1","0:00s","0","-"],["1979","1982","-","Sep","lastSun","1:00s","0","-"],["1980","only","-","Mar","lastSun","0:00s","1:00","S"],["1981","1982","-","Mar","lastSun","1:00s","1:00","S"],["1983","only","-","Mar","lastSun","2:00s","1:00","S"]],"Romania":[["1932","only","-","May","21","0:00s","1:00","S"],["1932","1939","-","Oct","Sun>=1","0:00s","0","-"],["1933","1939","-","Apr","Sun>=2","0:00s","1:00","S"],["1979","only","-","May","27","0:00","1:00","S"],["1979","only","-","Sep","lastSun","0:00","0","-"],["1980","only","-","Apr","5","23:00","1:00","S"],["1980","only","-","Sep","lastSun","1:00","0","-"],["1991","1993","-","Mar","lastSun","0:00s","1:00","S"],["1991","1993","-","Sep","lastSun","0:00s","0","-"]],"Spain":[["1917","only","-","May","5","23:00s","1:00","S"],["1917","1919","-","Oct","6","23:00s","0","-"],["1918","only","-","Apr","15","23:00s","1:00","S"],["1919","only","-","Apr","5","23:00s","1:00","S"],["1924","only","-","Apr","16","23:00s","1:00","S"],["1924","only","-","Oct","4","23:00s","0","-"],["1926","only","-","Apr","17","23:00s","1:00","S"],["1926","1929","-","Oct","Sat>=1","23:00s","0","-"],["1927","only","-","Apr","9","23:00s","1:00","S"],["1928","only","-","Apr","14","23:00s","1:00","S"],["1929","only","-","Apr","20","23:00s","1:00","S"],["1937","only","-","May","22","23:00s","1:00","S"],["1937","1939","-","Oct","Sat>=1","23:00s","0","-"],["1938","only","-","Mar","22","23:00s","1:00","S"],["1939","only","-","Apr","15","23:00s","1:00","S"],["1940","only","-","Mar","16","23:00s","1:00","S"],["1942","only","-","May","2","22:00s","2:00","M",""],["1942","only","-","Sep","1","22:00s","1:00","S"],["1943","1946","-","Apr","Sat>=13","22:00s","2:00","M"],["1943","only","-","Oct","3","22:00s","1:00","S"],["1944","only","-","Oct","10","22:00s","1:00","S"],["1945","only","-","Sep","30","1:00","1:00","S"],["1946","only","-","Sep","30","0:00","0","-"],["1949","only","-","Apr","30","23:00","1:00","S"],["1949","only","-","Sep","30","1:00","0","-"],["1974","1975","-","Apr","Sat>=13","23:00","1:00","S"],["1974","1975","-","Oct","Sun>=1","1:00","0","-"],["1976","only","-","Mar","27","23:00","1:00","S"],["1976","1977","-","Sep","lastSun","1:00","0","-"],["1977","1978","-","Apr","2","23:00","1:00","S"],["1978","only","-","Oct","1","1:00","0","-"]],"SpainAfrica":[["1967","only","-","Jun","3","12:00","1:00","S"],["1967","only","-","Oct","1","0:00","0","-"],["1974","only","-","Jun","24","0:00","1:00","S"],["1974","only","-","Sep","1","0:00","0","-"],["1976","1977","-","May","1","0:00","1:00","S"],["1976","only","-","Aug","1","0:00","0","-"],["1977","only","-","Sep","28","0:00","0","-"],["1978","only","-","Jun","1","0:00","1:00","S"],["1978","only","-","Aug","4","0:00","0","-"]],"Swiss":[["1941","1942","-","May","Mon>=1","1:00","1:00","S"],["1941","1942","-","Oct","Mon>=1","2:00","0","-"]],"Turkey":[["1916","only","-","May","1","0:00","1:00","S"],["1916","only","-","Oct","1","0:00","0","-"],["1920","only","-","Mar","28","0:00","1:00","S"],["1920","only","-","Oct","25","0:00","0","-"],["1921","only","-","Apr","3","0:00","1:00","S"],["1921","only","-","Oct","3","0:00","0","-"],["1922","only","-","Mar","26","0:00","1:00","S"],["1922","only","-","Oct","8","0:00","0","-"],["1924","only","-","May","13","0:00","1:00","S"],["1924","1925","-","Oct","1","0:00","0","-"],["1925","only","-","May","1","0:00","1:00","S"],["1940","only","-","Jun","30","0:00","1:00","S"],["1940","only","-","Oct","5","0:00","0","-"],["1940","only","-","Dec","1","0:00","1:00","S"],["1941","only","-","Sep","21","0:00","0","-"],["1942","only","-","Apr","1","0:00","1:00","S"],["1942","only","-","Nov","1","0:00","0","-"],["1945","only","-","Apr","2","0:00","1:00","S"],["1945","only","-","Oct","8","0:00","0","-"],["1946","only","-","Jun","1","0:00","1:00","S"],["1946","only","-","Oct","1","0:00","0","-"],["1947","1948","-","Apr","Sun>=16","0:00","1:00","S"],["1947","1950","-","Oct","Sun>=2","0:00","0","-"],["1949","only","-","Apr","10","0:00","1:00","S"],["1950","only","-","Apr","19","0:00","1:00","S"],["1951","only","-","Apr","22","0:00","1:00","S"],["1951","only","-","Oct","8","0:00","0","-"],["1962","only","-","Jul","15","0:00","1:00","S"],["1962","only","-","Oct","8","0:00","0","-"],["1964","only","-","May","15","0:00","1:00","S"],["1964","only","-","Oct","1","0:00","0","-"],["1970","1972","-","May","Sun>=2","0:00","1:00","S"],["1970","1972","-","Oct","Sun>=2","0:00","0","-"],["1973","only","-","Jun","3","1:00","1:00","S"],["1973","only","-","Nov","4","3:00","0","-"],["1974","only","-","Mar","31","2:00","1:00","S"],["1974","only","-","Nov","3","5:00","0","-"],["1975","only","-","Mar","30","0:00","1:00","S"],["1975","1976","-","Oct","lastSun","0:00","0","-"],["1976","only","-","Jun","1","0:00","1:00","S"],["1977","1978","-","Apr","Sun>=1","0:00","1:00","S"],["1977","only","-","Oct","16","0:00","0","-"],["1979","1980","-","Apr","Sun>=1","3:00","1:00","S"],["1979","1982","-","Oct","Mon>=11","0:00","0","-"],["1981","1982","-","Mar","lastSun","3:00","1:00","S"],["1983","only","-","Jul","31","0:00","1:00","S"],["1983","only","-","Oct","2","0:00","0","-"],["1985","only","-","Apr","20","0:00","1:00","S"],["1985","only","-","Sep","28","0:00","0","-"],["1986","1990","-","Mar","lastSun","2:00s","1:00","S"],["1986","1990","-","Sep","lastSun","2:00s","0","-"],["1991","2006","-","Mar","lastSun","1:00s","1:00","S"],["1991","1995","-","Sep","lastSun","1:00s","0","-"],["1996","2006","-","Oct","lastSun","1:00s","0","-"]],"US":[["1918","1919","-","Mar","lastSun","2:00","1:00","D"],["1918","1919","-","Oct","lastSun","2:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","30","2:00","0","S"],["1967","2006","-","Oct","lastSun","2:00","0","S"],["1967","1973","-","Apr","lastSun","2:00","1:00","D"],["1974","only","-","Jan","6","2:00","1:00","D"],["1975","only","-","Feb","23","2:00","1:00","D"],["1976","1986","-","Apr","lastSun","2:00","1:00","D"],["1987","2006","-","Apr","Sun>=1","2:00","1:00","D"],["2007","max","-","Mar","Sun>=8","2:00","1:00","D"],["2007","max","-","Nov","Sun>=1","2:00","0","S"]],"NYC":[["1920","only","-","Mar","lastSun","2:00","1:00","D"],["1920","only","-","Oct","lastSun","2:00","0","S"],["1921","1966","-","Apr","lastSun","2:00","1:00","D"],["1921","1954","-","Sep","lastSun","2:00","0","S"],["1955","1966","-","Oct","lastSun","2:00","0","S"]],"Chicago":[["1920","only","-","Jun","13","2:00","1:00","D"],["1920","1921","-","Oct","lastSun","2:00","0","S"],["1921","only","-","Mar","lastSun","2:00","1:00","D"],["1922","1966","-","Apr","lastSun","2:00","1:00","D"],["1922","1954","-","Sep","lastSun","2:00","0","S"],["1955","1966","-","Oct","lastSun","2:00","0","S"]],"Denver":[["1920","1921","-","Mar","lastSun","2:00","1:00","D"],["1920","only","-","Oct","lastSun","2:00","0","S"],["1921","only","-","May","22","2:00","0","S"],["1965","1966","-","Apr","lastSun","2:00","1:00","D"],["1965","1966","-","Oct","lastSun","2:00","0","S"]],"CA":[["1948","only","-","Mar","14","2:00","1:00","D"],["1949","only","-","Jan","1","2:00","0","S"],["1950","1966","-","Apr","lastSun","2:00","1:00","D"],["1950","1961","-","Sep","lastSun","2:00","0","S"],["1962","1966","-","Oct","lastSun","2:00","0","S"]],"Indianapolis":[["1941","only","-","Jun","22","2:00","1:00","D"],["1941","1954","-","Sep","lastSun","2:00","0","S"],["1946","1954","-","Apr","lastSun","2:00","1:00","D"]],"Marengo":[["1951","only","-","Apr","lastSun","2:00","1:00","D"],["1951","only","-","Sep","lastSun","2:00","0","S"],["1954","1960","-","Apr","lastSun","2:00","1:00","D"],["1954","1960","-","Sep","lastSun","2:00","0","S"]],"Vincennes":[["1946","only","-","Apr","lastSun","2:00","1:00","D"],["1946","only","-","Sep","lastSun","2:00","0","S"],["1953","1954","-","Apr","lastSun","2:00","1:00","D"],["1953","1959","-","Sep","lastSun","2:00","0","S"],["1955","only","-","May","1","0:00","1:00","D"],["1956","1963","-","Apr","lastSun","2:00","1:00","D"],["1960","only","-","Oct","lastSun","2:00","0","S"],["1961","only","-","Sep","lastSun","2:00","0","S"],["1962","1963","-","Oct","lastSun","2:00","0","S"]],"Perry":[["1946","only","-","Apr","lastSun","2:00","1:00","D"],["1946","only","-","Sep","lastSun","2:00","0","S"],["1953","1954","-","Apr","lastSun","2:00","1:00","D"],["1953","1959","-","Sep","lastSun","2:00","0","S"],["1955","only","-","May","1","0:00","1:00","D"],["1956","1963","-","Apr","lastSun","2:00","1:00","D"],["1960","only","-","Oct","lastSun","2:00","0","S"],["1961","only","-","Sep","lastSun","2:00","0","S"],["1962","1963","-","Oct","lastSun","2:00","0","S"]],"Pike":[["1955","only","-","May","1","0:00","1:00","D"],["1955","1960","-","Sep","lastSun","2:00","0","S"],["1956","1964","-","Apr","lastSun","2:00","1:00","D"],["1961","1964","-","Oct","lastSun","2:00","0","S"]],"Starke":[["1947","1961","-","Apr","lastSun","2:00","1:00","D"],["1947","1954","-","Sep","lastSun","2:00","0","S"],["1955","1956","-","Oct","lastSun","2:00","0","S"],["1957","1958","-","Sep","lastSun","2:00","0","S"],["1959","1961","-","Oct","lastSun","2:00","0","S"]],"Pulaski":[["1946","1960","-","Apr","lastSun","2:00","1:00","D"],["1946","1954","-","Sep","lastSun","2:00","0","S"],["1955","1956","-","Oct","lastSun","2:00","0","S"],["1957","1960","-","Sep","lastSun","2:00","0","S"]],"Louisville":[["1921","only","-","May","1","2:00","1:00","D"],["1921","only","-","Sep","1","2:00","0","S"],["1941","1961","-","Apr","lastSun","2:00","1:00","D"],["1941","only","-","Sep","lastSun","2:00","0","S"],["1946","only","-","Jun","2","2:00","0","S"],["1950","1955","-","Sep","lastSun","2:00","0","S"],["1956","1960","-","Oct","lastSun","2:00","0","S"]],"Detroit":[["1948","only","-","Apr","lastSun","2:00","1:00","D"],["1948","only","-","Sep","lastSun","2:00","0","S"],["1967","only","-","Jun","14","2:00","1:00","D"],["1967","only","-","Oct","lastSun","2:00","0","S"]],"Menominee":[["1946","only","-","Apr","lastSun","2:00","1:00","D"],["1946","only","-","Sep","lastSun","2:00","0","S"],["1966","only","-","Apr","lastSun","2:00","1:00","D"],["1966","only","-","Oct","lastSun","2:00","0","S"]],"Canada":[["1918","only","-","Apr","14","2:00","1:00","D"],["1918","only","-","Oct","31","2:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","30","2:00","0","S"],["1974","1986","-","Apr","lastSun","2:00","1:00","D"],["1974","2006","-","Oct","lastSun","2:00","0","S"],["1987","2006","-","Apr","Sun>=1","2:00","1:00","D"],["2007","max","-","Mar","Sun>=8","2:00","1:00","D"],["2007","max","-","Nov","Sun>=1","2:00","0","S"]],"StJohns":[["1917","only","-","Apr","8","2:00","1:00","D"],["1917","only","-","Sep","17","2:00","0","S"],["1919","only","-","May","5","23:00","1:00","D"],["1919","only","-","Aug","12","23:00","0","S"],["1920","1935","-","May","Sun>=1","23:00","1:00","D"],["1920","1935","-","Oct","lastSun","23:00","0","S"],["1936","1941","-","May","Mon>=9","0:00","1:00","D"],["1936","1941","-","Oct","Mon>=2","0:00","0","S"],["1946","1950","-","May","Sun>=8","2:00","1:00","D"],["1946","1950","-","Oct","Sun>=2","2:00","0","S"],["1951","1986","-","Apr","lastSun","2:00","1:00","D"],["1951","1959","-","Sep","lastSun","2:00","0","S"],["1960","1986","-","Oct","lastSun","2:00","0","S"],["1987","only","-","Apr","Sun>=1","0:01","1:00","D"],["1987","2006","-","Oct","lastSun","0:01","0","S"],["1988","only","-","Apr","Sun>=1","0:01","2:00","DD"],["1989","2006","-","Apr","Sun>=1","0:01","1:00","D"],["2007","max","-","Mar","Sun>=8","0:01","1:00","D"],["2007","max","-","Nov","Sun>=1","0:01","0","S"]],"Halifax":[["1916","only","-","Apr","1","0:00","1:00","D"],["1916","only","-","Oct","1","0:00","0","S"],["1920","only","-","May","9","0:00","1:00","D"],["1920","only","-","Aug","29","0:00","0","S"],["1921","only","-","May","6","0:00","1:00","D"],["1921","1922","-","Sep","5","0:00","0","S"],["1922","only","-","Apr","30","0:00","1:00","D"],["1923","1925","-","May","Sun>=1","0:00","1:00","D"],["1923","only","-","Sep","4","0:00","0","S"],["1924","only","-","Sep","15","0:00","0","S"],["1925","only","-","Sep","28","0:00","0","S"],["1926","only","-","May","16","0:00","1:00","D"],["1926","only","-","Sep","13","0:00","0","S"],["1927","only","-","May","1","0:00","1:00","D"],["1927","only","-","Sep","26","0:00","0","S"],["1928","1931","-","May","Sun>=8","0:00","1:00","D"],["1928","only","-","Sep","9","0:00","0","S"],["1929","only","-","Sep","3","0:00","0","S"],["1930","only","-","Sep","15","0:00","0","S"],["1931","1932","-","Sep","Mon>=24","0:00","0","S"],["1932","only","-","May","1","0:00","1:00","D"],["1933","only","-","Apr","30","0:00","1:00","D"],["1933","only","-","Oct","2","0:00","0","S"],["1934","only","-","May","20","0:00","1:00","D"],["1934","only","-","Sep","16","0:00","0","S"],["1935","only","-","Jun","2","0:00","1:00","D"],["1935","only","-","Sep","30","0:00","0","S"],["1936","only","-","Jun","1","0:00","1:00","D"],["1936","only","-","Sep","14","0:00","0","S"],["1937","1938","-","May","Sun>=1","0:00","1:00","D"],["1937","1941","-","Sep","Mon>=24","0:00","0","S"],["1939","only","-","May","28","0:00","1:00","D"],["1940","1941","-","May","Sun>=1","0:00","1:00","D"],["1946","1949","-","Apr","lastSun","2:00","1:00","D"],["1946","1949","-","Sep","lastSun","2:00","0","S"],["1951","1954","-","Apr","lastSun","2:00","1:00","D"],["1951","1954","-","Sep","lastSun","2:00","0","S"],["1956","1959","-","Apr","lastSun","2:00","1:00","D"],["1956","1959","-","Sep","lastSun","2:00","0","S"],["1962","1973","-","Apr","lastSun","2:00","1:00","D"],["1962","1973","-","Oct","lastSun","2:00","0","S"]],"Moncton":[["1933","1935","-","Jun","Sun>=8","1:00","1:00","D"],["1933","1935","-","Sep","Sun>=8","1:00","0","S"],["1936","1938","-","Jun","Sun>=1","1:00","1:00","D"],["1936","1938","-","Sep","Sun>=1","1:00","0","S"],["1939","only","-","May","27","1:00","1:00","D"],["1939","1941","-","Sep","Sat>=21","1:00","0","S"],["1940","only","-","May","19","1:00","1:00","D"],["1941","only","-","May","4","1:00","1:00","D"],["1946","1972","-","Apr","lastSun","2:00","1:00","D"],["1946","1956","-","Sep","lastSun","2:00","0","S"],["1957","1972","-","Oct","lastSun","2:00","0","S"],["1993","2006","-","Apr","Sun>=1","0:01","1:00","D"],["1993","2006","-","Oct","lastSun","0:01","0","S"]],"Mont":[["1917","only","-","Mar","25","2:00","1:00","D"],["1917","only","-","Apr","24","0:00","0","S"],["1919","only","-","Mar","31","2:30","1:00","D"],["1919","only","-","Oct","25","2:30","0","S"],["1920","only","-","May","2","2:30","1:00","D"],["1920","1922","-","Oct","Sun>=1","2:30","0","S"],["1921","only","-","May","1","2:00","1:00","D"],["1922","only","-","Apr","30","2:00","1:00","D"],["1924","only","-","May","17","2:00","1:00","D"],["1924","1926","-","Sep","lastSun","2:30","0","S"],["1925","1926","-","May","Sun>=1","2:00","1:00","D"],["1927","only","-","May","1","0:00","1:00","D"],["1927","1932","-","Sep","lastSun","0:00","0","S"],["1928","1931","-","Apr","lastSun","0:00","1:00","D"],["1932","only","-","May","1","0:00","1:00","D"],["1933","1940","-","Apr","lastSun","0:00","1:00","D"],["1933","only","-","Oct","1","0:00","0","S"],["1934","1939","-","Sep","lastSun","0:00","0","S"],["1946","1973","-","Apr","lastSun","2:00","1:00","D"],["1945","1948","-","Sep","lastSun","2:00","0","S"],["1949","1950","-","Oct","lastSun","2:00","0","S"],["1951","1956","-","Sep","lastSun","2:00","0","S"],["1957","1973","-","Oct","lastSun","2:00","0","S"]],"Toronto":[["1919","only","-","Mar","30","23:30","1:00","D"],["1919","only","-","Oct","26","0:00","0","S"],["1920","only","-","May","2","2:00","1:00","D"],["1920","only","-","Sep","26","0:00","0","S"],["1921","only","-","May","15","2:00","1:00","D"],["1921","only","-","Sep","15","2:00","0","S"],["1922","1923","-","May","Sun>=8","2:00","1:00","D"],["1922","1926","-","Sep","Sun>=15","2:00","0","S"],["1924","1927","-","May","Sun>=1","2:00","1:00","D"],["1927","1932","-","Sep","lastSun","2:00","0","S"],["1928","1931","-","Apr","lastSun","2:00","1:00","D"],["1932","only","-","May","1","2:00","1:00","D"],["1933","1940","-","Apr","lastSun","2:00","1:00","D"],["1933","only","-","Oct","1","2:00","0","S"],["1934","1939","-","Sep","lastSun","2:00","0","S"],["1945","1946","-","Sep","lastSun","2:00","0","S"],["1946","only","-","Apr","lastSun","2:00","1:00","D"],["1947","1949","-","Apr","lastSun","0:00","1:00","D"],["1947","1948","-","Sep","lastSun","0:00","0","S"],["1949","only","-","Nov","lastSun","0:00","0","S"],["1950","1973","-","Apr","lastSun","2:00","1:00","D"],["1950","only","-","Nov","lastSun","2:00","0","S"],["1951","1956","-","Sep","lastSun","2:00","0","S"],["1957","1973","-","Oct","lastSun","2:00","0","S"]],"Winn":[["1916","only","-","Apr","23","0:00","1:00","D"],["1916","only","-","Sep","17","0:00","0","S"],["1918","only","-","Apr","14","2:00","1:00","D"],["1918","only","-","Oct","31","2:00","0","S"],["1937","only","-","May","16","2:00","1:00","D"],["1937","only","-","Sep","26","2:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","lastSun","2:00","0","S"],["1946","only","-","May","12","2:00","1:00","D"],["1946","only","-","Oct","13","2:00","0","S"],["1947","1949","-","Apr","lastSun","2:00","1:00","D"],["1947","1949","-","Sep","lastSun","2:00","0","S"],["1950","only","-","May","1","2:00","1:00","D"],["1950","only","-","Sep","30","2:00","0","S"],["1951","1960","-","Apr","lastSun","2:00","1:00","D"],["1951","1958","-","Sep","lastSun","2:00","0","S"],["1959","only","-","Oct","lastSun","2:00","0","S"],["1960","only","-","Sep","lastSun","2:00","0","S"],["1963","only","-","Apr","lastSun","2:00","1:00","D"],["1963","only","-","Sep","22","2:00","0","S"],["1966","1986","-","Apr","lastSun","2:00s","1:00","D"],["1966","2005","-","Oct","lastSun","2:00s","0","S"],["1987","2005","-","Apr","Sun>=1","2:00s","1:00","D"]],"Regina":[["1918","only","-","Apr","14","2:00","1:00","D"],["1918","only","-","Oct","31","2:00","0","S"],["1930","1934","-","May","Sun>=1","0:00","1:00","D"],["1930","1934","-","Oct","Sun>=1","0:00","0","S"],["1937","1941","-","Apr","Sun>=8","0:00","1:00","D"],["1937","only","-","Oct","Sun>=8","0:00","0","S"],["1938","only","-","Oct","Sun>=1","0:00","0","S"],["1939","1941","-","Oct","Sun>=8","0:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","lastSun","2:00","0","S"],["1946","only","-","Apr","Sun>=8","2:00","1:00","D"],["1946","only","-","Oct","Sun>=8","2:00","0","S"],["1947","1957","-","Apr","lastSun","2:00","1:00","D"],["1947","1957","-","Sep","lastSun","2:00","0","S"],["1959","only","-","Apr","lastSun","2:00","1:00","D"],["1959","only","-","Oct","lastSun","2:00","0","S"]],"Swift":[["1957","only","-","Apr","lastSun","2:00","1:00","D"],["1957","only","-","Oct","lastSun","2:00","0","S"],["1959","1961","-","Apr","lastSun","2:00","1:00","D"],["1959","only","-","Oct","lastSun","2:00","0","S"],["1960","1961","-","Sep","lastSun","2:00","0","S"]],"Edm":[["1918","1919","-","Apr","Sun>=8","2:00","1:00","D"],["1918","only","-","Oct","31","2:00","0","S"],["1919","only","-","May","27","2:00","0","S"],["1920","1923","-","Apr","lastSun","2:00","1:00","D"],["1920","only","-","Oct","lastSun","2:00","0","S"],["1921","1923","-","Sep","lastSun","2:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","lastSun","2:00","0","S"],["1947","only","-","Apr","lastSun","2:00","1:00","D"],["1947","only","-","Sep","lastSun","2:00","0","S"],["1967","only","-","Apr","lastSun","2:00","1:00","D"],["1967","only","-","Oct","lastSun","2:00","0","S"],["1969","only","-","Apr","lastSun","2:00","1:00","D"],["1969","only","-","Oct","lastSun","2:00","0","S"],["1972","1986","-","Apr","lastSun","2:00","1:00","D"],["1972","2006","-","Oct","lastSun","2:00","0","S"]],"Vanc":[["1918","only","-","Apr","14","2:00","1:00","D"],["1918","only","-","Oct","31","2:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","30","2:00","0","S"],["1946","1986","-","Apr","lastSun","2:00","1:00","D"],["1946","only","-","Oct","13","2:00","0","S"],["1947","1961","-","Sep","lastSun","2:00","0","S"],["1962","2006","-","Oct","lastSun","2:00","0","S"]],"NT_YK":[["1918","only","-","Apr","14","2:00","1:00","D"],["1918","only","-","Oct","27","2:00","0","S"],["1919","only","-","May","25","2:00","1:00","D"],["1919","only","-","Nov","1","0:00","0","S"],["1942","only","-","Feb","9","2:00","1:00","W",""],["1945","only","-","Aug","14","23:00u","1:00","P",""],["1945","only","-","Sep","30","2:00","0","S"],["1965","only","-","Apr","lastSun","0:00","2:00","DD"],["1965","only","-","Oct","lastSun","2:00","0","S"],["1980","1986","-","Apr","lastSun","2:00","1:00","D"],["1980","2006","-","Oct","lastSun","2:00","0","S"],["1987","2006","-","Apr","Sun>=1","2:00","1:00","D"]],"Resolute":[["2006","max","-","Nov","Sun>=1","2:00","0","ES"],["2007","max","-","Mar","Sun>=8","2:00","0","CD"]],"Mexico":[["1939","only","-","Feb","5","0:00","1:00","D"],["1939","only","-","Jun","25","0:00","0","S"],["1940","only","-","Dec","9","0:00","1:00","D"],["1941","only","-","Apr","1","0:00","0","S"],["1943","only","-","Dec","16","0:00","1:00","W",""],["1944","only","-","May","1","0:00","0","S"],["1950","only","-","Feb","12","0:00","1:00","D"],["1950","only","-","Jul","30","0:00","0","S"],["1996","2000","-","Apr","Sun>=1","2:00","1:00","D"],["1996","2000","-","Oct","lastSun","2:00","0","S"],["2001","only","-","May","Sun>=1","2:00","1:00","D"],["2001","only","-","Sep","lastSun","2:00","0","S"],["2002","max","-","Apr","Sun>=1","2:00","1:00","D"],["2002","max","-","Oct","lastSun","2:00","0","S"]],"Bahamas":[["1964","1975","-","Oct","lastSun","2:00","0","S"],["1964","1975","-","Apr","lastSun","2:00","1:00","D"]],"Barb":[["1977","only","-","Jun","12","2:00","1:00","D"],["1977","1978","-","Oct","Sun>=1","2:00","0","S"],["1978","1980","-","Apr","Sun>=15","2:00","1:00","D"],["1979","only","-","Sep","30","2:00","0","S"],["1980","only","-","Sep","25","2:00","0","S"]],"Belize":[["1918","1942","-","Oct","Sun>=2","0:00","0:30","HD"],["1919","1943","-","Feb","Sun>=9","0:00","0","S"],["1973","only","-","Dec","5","0:00","1:00","D"],["1974","only","-","Feb","9","0:00","0","S"],["1982","only","-","Dec","18","0:00","1:00","D"],["1983","only","-","Feb","12","0:00","0","S"]],"CR":[["1979","1980","-","Feb","lastSun","0:00","1:00","D"],["1979","1980","-","Jun","Sun>=1","0:00","0","S"],["1991","1992","-","Jan","Sat>=15","0:00","1:00","D"],["1991","only","-","Jul","1","0:00","0","S"],["1992","only","-","Mar","15","0:00","0","S"]],"Cuba":[["1928","only","-","Jun","10","0:00","1:00","D"],["1928","only","-","Oct","10","0:00","0","S"],["1940","1942","-","Jun","Sun>=1","0:00","1:00","D"],["1940","1942","-","Sep","Sun>=1","0:00","0","S"],["1945","1946","-","Jun","Sun>=1","0:00","1:00","D"],["1945","1946","-","Sep","Sun>=1","0:00","0","S"],["1965","only","-","Jun","1","0:00","1:00","D"],["1965","only","-","Sep","30","0:00","0","S"],["1966","only","-","May","29","0:00","1:00","D"],["1966","only","-","Oct","2","0:00","0","S"],["1967","only","-","Apr","8","0:00","1:00","D"],["1967","1968","-","Sep","Sun>=8","0:00","0","S"],["1968","only","-","Apr","14","0:00","1:00","D"],["1969","1977","-","Apr","lastSun","0:00","1:00","D"],["1969","1971","-","Oct","lastSun","0:00","0","S"],["1972","1974","-","Oct","8","0:00","0","S"],["1975","1977","-","Oct","lastSun","0:00","0","S"],["1978","only","-","May","7","0:00","1:00","D"],["1978","1990","-","Oct","Sun>=8","0:00","0","S"],["1979","1980","-","Mar","Sun>=15","0:00","1:00","D"],["1981","1985","-","May","Sun>=5","0:00","1:00","D"],["1986","1989","-","Mar","Sun>=14","0:00","1:00","D"],["1990","1997","-","Apr","Sun>=1","0:00","1:00","D"],["1991","1995","-","Oct","Sun>=8","0:00s","0","S"],["1996","only","-","Oct","6","0:00s","0","S"],["1997","only","-","Oct","12","0:00s","0","S"],["1998","1999","-","Mar","lastSun","0:00s","1:00","D"],["1998","2003","-","Oct","lastSun","0:00s","0","S"],["2000","2004","-","Apr","Sun>=1","0:00s","1:00","D"],["2006","max","-","Oct","lastSun","0:00s","0","S"],["2007","only","-","Mar","Sun>=8","0:00s","1:00","D"],["2008","only","-","Mar","Sun>=15","0:00s","1:00","D"],["2009","2010","-","Mar","Sun>=8","0:00s","1:00","D"],["2011","only","-","Mar","Sun>=15","0:00s","1:00","D"],["2012","max","-","Mar","Sun>=8","0:00s","1:00","D"]],"DR":[["1966","only","-","Oct","30","0:00","1:00","D"],["1967","only","-","Feb","28","0:00","0","S"],["1969","1973","-","Oct","lastSun","0:00","0:30","HD"],["1970","only","-","Feb","21","0:00","0","S"],["1971","only","-","Jan","20","0:00","0","S"],["1972","1974","-","Jan","21","0:00","0","S"]],"Salv":[["1987","1988","-","May","Sun>=1","0:00","1:00","D"],["1987","1988","-","Sep","lastSun","0:00","0","S"]],"Guat":[["1973","only","-","Nov","25","0:00","1:00","D"],["1974","only","-","Feb","24","0:00","0","S"],["1983","only","-","May","21","0:00","1:00","D"],["1983","only","-","Sep","22","0:00","0","S"],["1991","only","-","Mar","23","0:00","1:00","D"],["1991","only","-","Sep","7","0:00","0","S"],["2006","only","-","Apr","30","0:00","1:00","D"],["2006","only","-","Oct","1","0:00","0","S"]],"Haiti":[["1983","only","-","May","8","0:00","1:00","D"],["1984","1987","-","Apr","lastSun","0:00","1:00","D"],["1983","1987","-","Oct","lastSun","0:00","0","S"],["1988","1997","-","Apr","Sun>=1","1:00s","1:00","D"],["1988","1997","-","Oct","lastSun","1:00s","0","S"],["2005","2006","-","Apr","Sun>=1","0:00","1:00","D"],["2005","2006","-","Oct","lastSun","0:00","0","S"]],"Hond":[["1987","1988","-","May","Sun>=1","0:00","1:00","D"],["1987","1988","-","Sep","lastSun","0:00","0","S"],["2006","only","-","May","Sun>=1","0:00","1:00","D"],["2006","only","-","Aug","Mon>=1","0:00","0","S"]],"Nic":[["1979","1980","-","Mar","Sun>=16","0:00","1:00","D"],["1979","1980","-","Jun","Mon>=23","0:00","0","S"],["2005","only","-","Apr","10","0:00","1:00","D"],["2005","only","-","Oct","Sun>=1","0:00","0","S"],["2006","only","-","Apr","30","2:00","1:00","D"],["2006","only","-","Oct","Sun>=1","1:00","0","S"]],"TC":[["1979","1986","-","Apr","lastSun","2:00","1:00","D"],["1979","2006","-","Oct","lastSun","2:00","0","S"],["1987","2006","-","Apr","Sun>=1","2:00","1:00","D"],["2007","max","-","Mar","Sun>=8","2:00","1:00","D"],["2007","max","-","Nov","Sun>=1","2:00","0","S"]]};
14416 * By: Trent Richardson [http://trentrichardson.com]
14418 * Last Modified: 3/30/2010
14420 * Copyright 2010 Trent Richardson
14421 * Dual licensed under the MIT and GPL licenses.
14422 * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
14423 * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
14428 $.prompt = function(message, options) {
14429 options = $.extend({},$.prompt.defaults,options);
14430 $.prompt.currentPrefix = options.prefix;
14432 var ie6 = ($.browser.msie && $.browser.version < 7);
14433 var $body = $(document.body);
14434 var $window = $(window);
14436 options.classes = $.trim(options.classes);
14437 if(options.classes != '')
14438 options.classes = ' '+ options.classes;
14440 //build the box and fade
14441 var msgbox = '<div class="'+ options.prefix +'box'+ options.classes +'" id="'+ options.prefix +'box">';
14442 if(options.useiframe && (($('object, applet').length > 0) || ie6)) {
14443 msgbox += '<iframe src="javascript:false;" style="display:block;position:absolute;z-index:-1;" class="'+ options.prefix +'fade" id="'+ options.prefix +'fade"></iframe>';
14446 $('select').css('visibility','hidden');
14448 msgbox +='<div class="'+ options.prefix +'fade" id="'+ options.prefix +'fade"></div>';
14450 msgbox += '<div class="'+ options.prefix +'" id="'+ options.prefix +'"><div class="'+ options.prefix +'container"><div class="';
14451 msgbox += options.prefix +'close">X</div><div id="'+ options.prefix +'states"></div>';
14452 msgbox += '</div></div></div>';
14454 var $jqib = $(msgbox).appendTo($body);
14455 var $jqi = $jqib.children('#'+ options.prefix);
14456 var $jqif = $jqib.children('#'+ options.prefix +'fade');
14458 //if a string was passed, convert to a single state
14459 if(message.constructor == String){
14463 buttons: options.buttons,
14464 focus: options.focus,
14465 submit: options.submit
14473 $.each(message,function(statename,stateobj){
14474 stateobj = $.extend({},$.prompt.defaults.state,stateobj);
14475 message[statename] = stateobj;
14477 states += '<div id="'+ options.prefix +'_state_'+ statename +'" class="'+ options.prefix + '_state" style="display:none;"><div class="'+ options.prefix +'message">' + stateobj.html +'</div><div class="'+ options.prefix +'buttons">';
14478 $.each(stateobj.buttons, function(k, v){
14479 if(typeof v == 'object')
14480 states += '<button name="' + options.prefix + '_' + statename + '_button' + v.title.replace(/[^a-z0-9]+/gi,'') + '" id="' + options.prefix + '_' + statename + '_button' + v.title.replace(/[^a-z0-9]+/gi,'') + '" value="' + v.value + '">' + v.title + '</button>';
14481 else states += '<button name="' + options.prefix + '_' + statename + '_button' + k + '" id="' + options.prefix + '_' + statename + '_button' + k + '" value="' + v + '">' + k + '</button>';
14483 states += '</div></div>';
14486 //insert the states...
14487 $jqi.find('#'+ options.prefix +'states').html(states).children('.'+ options.prefix +'_state:first').css('display','block');
14488 $jqi.find('.'+ options.prefix +'buttons:empty').css('display','none');
14491 $.each(message,function(statename,stateobj){
14492 var $state = $jqi.find('#'+ options.prefix +'_state_'+ statename);
14494 $state.children('.'+ options.prefix +'buttons').children('button').click(function(){
14495 var msg = $state.children('.'+ options.prefix +'message');
14496 var clicked = stateobj.buttons[$(this).text()];
14497 if(clicked == undefined){
14498 for(var i in stateobj.buttons)
14499 if(stateobj.buttons[i].title == $(this).text())
14500 clicked = stateobj.buttons[i].value;
14503 if(typeof clicked == 'object')
14504 clicked = clicked.value;
14505 var forminputs = {};
14507 //collect all form element values from all states
14508 $.each($jqi.find('#'+ options.prefix +'states :input').serializeArray(),function(i,obj){
14509 if (forminputs[obj.name] === undefined) {
14510 forminputs[obj.name] = obj.value;
14511 } else if (typeof forminputs[obj.name] == Array || typeof forminputs[obj.name] == 'object') {
14512 forminputs[obj.name].push(obj.value);
14514 forminputs[obj.name] = [forminputs[obj.name],obj.value];
14518 var close = stateobj.submit(clicked,msg,forminputs);
14519 if(close === undefined || close) {
14520 removePrompt(true,clicked,msg,forminputs);
14523 $state.find('.'+ options.prefix +'buttons button:eq('+ stateobj.focus +')').addClass(options.prefix +'defaultbutton');
14527 var ie6scroll = function(){
14528 $jqib.css({ top: $window.scrollTop() });
14531 var fadeClicked = function(){
14532 if(options.persistent){
14534 $jqib.addClass(options.prefix +'warning');
14535 var intervalid = setInterval(function(){
14536 $jqib.toggleClass(options.prefix +'warning');
14538 clearInterval(intervalid);
14539 $jqib.removeClass(options.prefix +'warning');
14548 var keyPressEventHandler = function(e){
14549 var key = (window.event) ? event.keyCode : e.keyCode; // MSIE or Firefox?
14551 //escape key closes
14558 var $inputels = $(':input:enabled:visible',$jqib);
14559 var fwd = !e.shiftKey && e.target == $inputels[$inputels.length-1];
14560 var back = e.shiftKey && e.target == $inputels[0];
14562 setTimeout(function(){
14565 var el = $inputels[back===true ? $inputels.length-1 : 0];
14575 var positionPrompt = function(){
14577 position: (ie6) ? "absolute" : "fixed",
14578 height: $window.height(),
14580 top: (ie6)? $window.scrollTop() : 0,
14586 position: "absolute",
14587 height: $window.height(),
14595 position: "absolute",
14598 marginLeft: (($jqi.outerWidth()/2)*-1)
14602 var stylePrompt = function(){
14604 zIndex: options.zIndex,
14606 opacity: options.opacity
14609 zIndex: options.zIndex+1,
14613 zIndex: options.zIndex
14617 var removePrompt = function(callCallback, clicked, msg, formvals){
14619 //ie6, remove the scroll event
14621 $body.unbind('scroll',ie6scroll);
14623 $window.unbind('resize',positionPrompt);
14624 $jqif.fadeOut(options.overlayspeed,function(){
14625 $jqif.unbind('click',fadeClicked);
14628 options.callback(clicked,msg,formvals);
14630 $jqib.unbind('keypress',keyPressEventHandler);
14632 if(ie6 && !options.useiframe) {
14633 $('select').css('visibility','visible');
14641 //ie6, add a scroll event to fix position:fixed
14643 $window.scroll(ie6scroll);
14645 $jqif.click(fadeClicked);
14646 $window.resize(positionPrompt);
14647 $jqib.bind("keydown keypress",keyPressEventHandler);
14648 $jqi.find('.'+ options.prefix +'close').click(removePrompt);
14651 $jqif.fadeIn(options.overlayspeed);
14652 $jqi[options.show](options.promptspeed,options.loaded);
14653 $jqi.find('#'+ options.prefix +'states .'+ options.prefix +'_state:first .'+ options.prefix +'defaultbutton').focus();
14655 if(options.timeout > 0)
14656 setTimeout($.prompt.close,options.timeout);
14661 $.prompt.defaults = {
14667 loaded: function(){
14670 submit: function(){
14673 callback: function(){
14678 overlayspeed: 'slow',
14679 promptspeed: 'fast',
14692 submit: function(){
14698 $.prompt.currentPrefix = $.prompt.defaults.prefix;
14700 $.prompt.setDefaults = function(o) {
14701 $.prompt.defaults = $.extend({}, $.prompt.defaults, o);
14704 $.prompt.setStateDefaults = function(o) {
14705 $.prompt.defaults.state = $.extend({}, $.prompt.defaults.state, o);
14708 $.prompt.getStateContent = function(state) {
14709 return $('#'+ $.prompt.currentPrefix +'_state_'+ state);
14712 $.prompt.getCurrentState = function() {
14713 return $('.'+ $.prompt.currentPrefix +'_state:visible');
14716 $.prompt.getCurrentStateName = function() {
14717 var stateid = $.prompt.getCurrentState().attr('id');
14719 return stateid.replace($.prompt.currentPrefix +'_state_','');
14722 $.prompt.goToState = function(state, callback) {
14723 $('.'+ $.prompt.currentPrefix +'_state').slideUp('slow');
14724 $('#'+ $.prompt.currentPrefix +'_state_'+ state).slideDown('slow',function(){
14725 $(this).find('.'+ $.prompt.currentPrefix +'defaultbutton').focus();
14726 if (typeof callback == 'function')
14731 $.prompt.nextState = function(callback) {
14732 var $next = $('.'+ $.prompt.currentPrefix +'_state:visible').next();
14734 $('.'+ $.prompt.currentPrefix +'_state').slideUp('slow');
14736 $next.slideDown('slow',function(){
14737 $next.find('.'+ $.prompt.currentPrefix +'defaultbutton').focus();
14738 if (typeof callback == 'function')
14743 $.prompt.prevState = function(callback) {
14744 var $next = $('.'+ $.prompt.currentPrefix +'_state:visible').prev();
14746 $('.'+ $.prompt.currentPrefix +'_state').slideUp('slow');
14748 $next.slideDown('slow',function(){
14749 $next.find('.'+ $.prompt.currentPrefix +'defaultbutton').focus();
14750 if (typeof callback == 'function')
14755 $.prompt.close = function() {
14756 $('#'+ $.prompt.currentPrefix +'box').fadeOut('fast',function(){
14761 $.fn.prompt = function(options){
14762 if(options == undefined)
14764 if(options.withDataAndEvents == undefined)
14765 options.withDataAndEvents = false;
14767 $.prompt($(this).clone(options.withDataAndEvents).html(),options);
14772 $.fn.serializeToJson = function() {
14774 this.find('[name]').each(function(i, field) {
14776 if ($field.is(':checkbox')) {
14777 val = $field.is(':checked');
14779 val = $field.val();
14781 attrs[$field.attr('name')] = val;
14788 http://www.JSON.org/json2.js
14793 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
14795 See http://www.JSON.org/js.html
14798 This code should be minified before deployment.
14799 See http://javascript.crockford.com/jsmin.html
14801 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
14805 This file creates a global JSON object containing two methods: stringify
14808 JSON.stringify(value, replacer, space)
14809 value any JavaScript value, usually an object or array.
14811 replacer an optional parameter that determines how object
14812 values are stringified for objects. It can be a
14813 function or an array of strings.
14815 space an optional parameter that specifies the indentation
14816 of nested structures. If it is omitted, the text will
14817 be packed without extra whitespace. If it is a number,
14818 it will specify the number of spaces to indent at each
14819 level. If it is a string (such as '\t' or ' '),
14820 it contains the characters used to indent at each level.
14822 This method produces a JSON text from a JavaScript value.
14824 When an object value is found, if the object contains a toJSON
14825 method, its toJSON method will be called and the result will be
14826 stringified. A toJSON method does not serialize: it returns the
14827 value represented by the name/value pair that should be serialized,
14828 or undefined if nothing should be serialized. The toJSON method
14829 will be passed the key associated with the value, and this will be
14832 For example, this would serialize Dates as ISO strings.
14834 Date.prototype.toJSON = function (key) {
14836 // Format integers to have at least two digits.
14837 return n < 10 ? '0' + n : n;
14840 return this.getUTCFullYear() + '-' +
14841 f(this.getUTCMonth() + 1) + '-' +
14842 f(this.getUTCDate()) + 'T' +
14843 f(this.getUTCHours()) + ':' +
14844 f(this.getUTCMinutes()) + ':' +
14845 f(this.getUTCSeconds()) + 'Z';
14848 You can provide an optional replacer method. It will be passed the
14849 key and value of each member, with this bound to the containing
14850 object. The value that is returned from your method will be
14851 serialized. If your method returns undefined, then the member will
14852 be excluded from the serialization.
14854 If the replacer parameter is an array of strings, then it will be
14855 used to select the members to be serialized. It filters the results
14856 such that only members with keys listed in the replacer array are
14859 Values that do not have JSON representations, such as undefined or
14860 functions, will not be serialized. Such values in objects will be
14861 dropped; in arrays they will be replaced with null. You can use
14862 a replacer function to replace those with JSON values.
14863 JSON.stringify(undefined) returns undefined.
14865 The optional space parameter produces a stringification of the
14866 value that is filled with line breaks and indentation to make it
14869 If the space parameter is a non-empty string, then that string will
14870 be used for indentation. If the space parameter is a number, then
14871 the indentation will be that many spaces.
14875 text = JSON.stringify(['e', {pluribus: 'unum'}]);
14876 // text is '["e",{"pluribus":"unum"}]'
14879 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
14880 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
14882 text = JSON.stringify([new Date()], function (key, value) {
14883 return this[key] instanceof Date ?
14884 'Date(' + this[key] + ')' : value;
14886 // text is '["Date(---current time---)"]'
14889 JSON.parse(text, reviver)
14890 This method parses a JSON text to produce an object or array.
14891 It can throw a SyntaxError exception.
14893 The optional reviver parameter is a function that can filter and
14894 transform the results. It receives each of the keys and values,
14895 and its return value is used instead of the original value.
14896 If it returns what it received, then the structure is not modified.
14897 If it returns undefined then the member is deleted.
14901 // Parse the text. Values that look like ISO date strings will
14902 // be converted to Date objects.
14904 myData = JSON.parse(text, function (key, value) {
14906 if (typeof value === 'string') {
14908 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
14910 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
14917 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
14919 if (typeof value === 'string' &&
14920 value.slice(0, 5) === 'Date(' &&
14921 value.slice(-1) === ')') {
14922 d = new Date(value.slice(5, -1));
14931 This is a reference implementation. You are free to copy, modify, or
14935 /*jslint evil: true, strict: false, regexp: false */
14937 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
14938 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
14939 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
14940 lastIndex, length, parse, prototype, push, replace, slice, stringify,
14941 test, toJSON, toString, valueOf
14945 // Create a JSON object only if one does not already exist. We create the
14946 // methods in a closure to avoid creating global variables.
14957 // Format integers to have at least two digits.
14958 return n < 10 ? '0' + n : n;
14961 if (typeof Date.prototype.toJSON !== 'function') {
14963 Date.prototype.toJSON = function (key) {
14965 return isFinite(this.valueOf()) ?
14966 this.getUTCFullYear() + '-' +
14967 f(this.getUTCMonth() + 1) + '-' +
14968 f(this.getUTCDate()) + 'T' +
14969 f(this.getUTCHours()) + ':' +
14970 f(this.getUTCMinutes()) + ':' +
14971 f(this.getUTCSeconds()) + 'Z' : null;
14974 String.prototype.toJSON =
14975 Number.prototype.toJSON =
14976 Boolean.prototype.toJSON = function (key) {
14977 return this.valueOf();
14981 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
14982 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
14985 meta = { // table of character substitutions
14997 function quote(string) {
14999 // If the string contains no control characters, no quote characters, and no
15000 // backslash characters, then we can safely slap some quotes around it.
15001 // Otherwise we must also replace the offending characters with safe escape
15004 escapable.lastIndex = 0;
15005 return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
15007 return typeof c === 'string' ? c :
15008 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
15009 }) + '"' : '"' + string + '"';
15013 function str(key, holder) {
15015 // Produce a string from holder[key].
15017 var i, // The loop counter.
15018 k, // The member key.
15019 v, // The member value.
15023 value = holder[key];
15025 // If the value has a toJSON method, call it to obtain a replacement value.
15027 if (value && typeof value === 'object' &&
15028 typeof value.toJSON === 'function') {
15029 value = value.toJSON(key);
15032 // If we were called with a replacer function, then call the replacer to
15033 // obtain a replacement value.
15035 if (typeof rep === 'function') {
15036 value = rep.call(holder, key, value);
15039 // What happens next depends on the value's type.
15041 switch (typeof value) {
15043 return quote(value);
15047 // JSON numbers must be finite. Encode non-finite numbers as null.
15049 return isFinite(value) ? String(value) : 'null';
15054 // If the value is a boolean or null, convert it to a string. Note:
15055 // typeof null does not produce 'null'. The case is included here in
15056 // the remote chance that this gets fixed someday.
15058 return String(value);
15060 // If the type is 'object', we might be dealing with an object or an array or
15065 // Due to a specification blunder in ECMAScript, typeof null is 'object',
15066 // so watch out for that case.
15072 // Make an array to hold the partial results of stringifying this object value.
15077 // Is the value an array?
15079 if (Object.prototype.toString.apply(value) === '[object Array]') {
15081 // The value is an array. Stringify every element. Use null as a placeholder
15082 // for non-JSON values.
15084 length = value.length;
15085 for (i = 0; i < length; i += 1) {
15086 partial[i] = str(i, value) || 'null';
15089 // Join all of the elements together, separated with commas, and wrap them in
15092 v = partial.length === 0 ? '[]' : gap ?
15093 '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
15094 '[' + partial.join(',') + ']';
15099 // If the replacer is an array, use it to select the members to be stringified.
15101 if (rep && typeof rep === 'object') {
15102 length = rep.length;
15103 for (i = 0; i < length; i += 1) {
15104 if (typeof rep[i] === 'string') {
15108 partial.push(quote(k) + (gap ? ': ' : ':') + v);
15114 // Otherwise, iterate through all of the keys in the object.
15117 if (Object.prototype.hasOwnProperty.call(value, k)) {
15120 partial.push(quote(k) + (gap ? ': ' : ':') + v);
15126 // Join all of the member texts together, separated with commas,
15127 // and wrap them in braces.
15129 v = partial.length === 0 ? '{}' : gap ?
15130 '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
15131 '{' + partial.join(',') + '}';
15137 // If the JSON object does not yet have a stringify method, give it one.
15139 if (typeof JSON.stringify !== 'function') {
15140 JSON.stringify = function (value, replacer, space) {
15142 // The stringify method takes a value and an optional replacer, and an optional
15143 // space parameter, and returns a JSON text. The replacer can be a function
15144 // that can replace values, or an array of strings that will select the keys.
15145 // A default replacer method can be provided. Use of the space parameter can
15146 // produce text that is more easily readable.
15152 // If the space parameter is a number, make an indent string containing that
15155 if (typeof space === 'number') {
15156 for (i = 0; i < space; i += 1) {
15160 // If the space parameter is a string, it will be used as the indent string.
15162 } else if (typeof space === 'string') {
15166 // If there is a replacer, it must be a function or an array.
15167 // Otherwise, throw an error.
15170 if (replacer && typeof replacer !== 'function' &&
15171 (typeof replacer !== 'object' ||
15172 typeof replacer.length !== 'number')) {
15173 throw new Error('JSON.stringify');
15176 // Make a fake root object containing our value under the key of ''.
15177 // Return the result of stringifying the value.
15179 return str('', {'': value});
15184 // If the JSON object does not yet have a parse method, give it one.
15186 if (typeof JSON.parse !== 'function') {
15187 JSON.parse = function (text, reviver) {
15189 // The parse method takes a text and an optional reviver function, and returns
15190 // a JavaScript value if the text is a valid JSON text.
15194 function walk(holder, key) {
15196 // The walk method is used to recursively walk the resulting structure so
15197 // that modifications can be made.
15199 var k, v, value = holder[key];
15200 if (value && typeof value === 'object') {
15202 if (Object.prototype.hasOwnProperty.call(value, k)) {
15203 v = walk(value, k);
15204 if (v !== undefined) {
15212 return reviver.call(holder, key, value);
15216 // Parsing happens in four stages. In the first stage, we replace certain
15217 // Unicode characters with escape sequences. JavaScript handles many characters
15218 // incorrectly, either silently deleting them, or treating them as line endings.
15220 text = String(text);
15222 if (cx.test(text)) {
15223 text = text.replace(cx, function (a) {
15225 ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
15229 // In the second stage, we run the text against regular expressions that look
15230 // for non-JSON patterns. We are especially concerned with '()' and 'new'
15231 // because they can cause invocation, and '=' because it can cause mutation.
15232 // But just to be safe, we want to reject all unexpected forms.
15234 // We split the second stage into 4 regexp operations in order to work around
15235 // crippling inefficiencies in IE's and Safari's regexp engines. First we
15236 // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
15237 // replace all simple value tokens with ']' characters. Third, we delete all
15238 // open brackets that follow a colon or comma or that begin the text. Finally,
15239 // we look to see that the remaining characters are only whitespace or ']' or
15240 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
15242 if (/^[\],:{}\s]*$/
15243 .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
15244 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
15245 .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
15247 // In the third stage we use the eval function to compile the text into a
15248 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
15249 // in JavaScript: it can begin a block or an object literal. We wrap the text
15250 // in parens to eliminate the ambiguity.
15252 j = eval('(' + text + ')');
15254 // In the optional fourth stage, we recursively walk the new structure, passing
15255 // each name/value pair to a reviver function for possible transformation.
15257 return typeof reviver === 'function' ?
15258 walk({'': j}, '') : j;
15261 // If the text is not JSON parseable, then a SyntaxError is thrown.
15263 throw new SyntaxError('JSON.parse');
15272 createUploadIframe: function(id, uri)
\r
15275 var frameId = 'jUploadFrame' + id;
\r
15276 var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"';
\r
15277 if(window.ActiveXObject)
\r
15279 if(typeof uri== 'boolean'){
\r
15280 iframeHtml += ' src="' + 'javascript:false' + '"';
\r
15283 else if(typeof uri== 'string'){
\r
15284 iframeHtml += ' src="' + uri + '"';
\r
15288 iframeHtml += ' />';
\r
15289 jQuery(iframeHtml).appendTo(document.body);
\r
15291 return jQuery('#' + frameId).get(0);
\r
15293 createUploadForm: function(id, fileElementId, data)
\r
15296 var formId = 'jUploadForm' + id;
\r
15297 var fileId = 'jUploadFile' + id;
\r
15298 var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
\r
15301 for(var i in data)
\r
15303 jQuery('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form);
\r
15306 var oldElement = jQuery('#' + fileElementId);
\r
15307 var newElement = jQuery(oldElement).clone();
\r
15308 jQuery(oldElement).attr('id', fileId);
\r
15309 jQuery(oldElement).before(newElement);
\r
15310 jQuery(oldElement).appendTo(form);
\r
15315 jQuery(form).css('position', 'absolute');
\r
15316 jQuery(form).css('top', '-1200px');
\r
15317 jQuery(form).css('left', '-1200px');
\r
15318 jQuery(form).appendTo('body');
\r
15322 ajaxFileUpload: function(s) {
\r
15323 // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
\r
15324 s = jQuery.extend({}, jQuery.ajaxSettings, s);
\r
15325 var id = new Date().getTime()
\r
15326 var form = jQuery.createUploadForm(id, s.fileElementId, (typeof(s.data)=='undefined'?false:s.data));
\r
15327 var io = jQuery.createUploadIframe(id, s.secureuri);
\r
15328 var frameId = 'jUploadFrame' + id;
\r
15329 var formId = 'jUploadForm' + id;
\r
15330 // Watch for a new set of requests
\r
15331 if ( s.global && ! jQuery.active++ )
\r
15333 jQuery.event.trigger( "ajaxStart" );
\r
15335 var requestDone = false;
\r
15336 // Create the request object
\r
15339 jQuery.event.trigger("ajaxSend", [xml, s]);
\r
15340 // Wait for a response to come back
\r
15341 var uploadCallback = function(isTimeout)
\r
15343 var io = document.getElementById(frameId);
\r
15346 if(io.contentWindow)
\r
15348 xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
\r
15349 xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
\r
15351 }else if(io.contentDocument)
\r
15353 xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
\r
15354 xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
\r
15358 jQuery.handleError(s, xml, null, e);
\r
15361 var data = $(xml.responseText).html();
\r
15362 if ( xml || isTimeout == "timeout")
\r
15364 requestDone = true;
\r
15367 data = JSON.parse(data);
\r
15368 //check for error in return JSON
\r
15370 status = "error";
\r
15372 status = "success";
\r
15375 // Fire the global callback
\r
15377 jQuery.event.trigger( "ajaxSuccess", [xml, s] );
\r
15379 status = "error";
\r
15380 jQuery.handleError(s, xml, status, e);
\r
15383 // The request was completed
\r
15385 jQuery.event.trigger( "ajaxComplete", [xml, s] );
\r
15387 // Handle the global AJAX counter
\r
15388 if ( s.global && ! --jQuery.active )
\r
15389 jQuery.event.trigger( "ajaxStop" );
\r
15391 // Process result
\r
15392 if ( s.complete )
\r
15393 s.complete(data, status);
\r
15395 jQuery(io).unbind()
\r
15397 setTimeout(function()
\r
15400 jQuery(io).remove();
\r
15401 jQuery(form).remove();
\r
15405 jQuery.handleError(s, xml, null, e);
\r
15414 // Timeout checker
\r
15415 if ( s.timeout > 0 )
\r
15417 setTimeout(function(){
\r
15418 // Check to see if the request is still happening
\r
15419 if( !requestDone ) uploadCallback( "timeout" );
\r
15425 var form = jQuery('#' + formId);
\r
15426 jQuery(form).attr('action', s.url);
\r
15427 jQuery(form).attr('method', 'POST');
\r
15428 jQuery(form).attr('target', frameId);
\r
15429 if(form.encoding)
\r
15431 jQuery(form).attr('encoding', 'multipart/form-data');
\r
15435 jQuery(form).attr('enctype', 'multipart/form-data');
\r
15437 jQuery(form).submit();
\r
15441 jQuery.handleError(s, xml, null, e);
\r
15444 jQuery('#' + frameId).load(uploadCallback );
\r
15445 return {abort: function () {}};
\r
15451 /*jslint browser: true */ /*global jQuery: true */
15454 * jQuery Cookie plugin
15456 * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
15457 * Dual licensed under the MIT and GPL licenses:
15458 * http://www.opensource.org/licenses/mit-license.php
15459 * http://www.gnu.org/licenses/gpl.html
15466 * Create a cookie with the given key and value and other optional parameters.
15468 * @example $.cookie('the_cookie', 'the_value');
15469 * @desc Set the value of a cookie.
15470 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
15471 * @desc Create a cookie with all available options.
15472 * @example $.cookie('the_cookie', 'the_value');
15473 * @desc Create a session cookie.
15474 * @example $.cookie('the_cookie', null);
15475 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
15476 * used when the cookie was set.
15478 * @param String key The key of the cookie.
15479 * @param String value The value of the cookie.
15480 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
15481 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
15482 * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
15483 * If set to null or omitted, the cookie will be a session cookie and will not be retained
15484 * when the the browser exits.
15485 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
15486 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
15487 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
15488 * require a secure protocol (like HTTPS).
15492 * @cat Plugins/Cookie
15493 * @author Klaus Hartl/klaus.hartl@stilbuero.de
15497 * Get the value of a cookie with the given key.
15499 * @example $.cookie('the_cookie');
15500 * @desc Get the value of a cookie.
15502 * @param String key The key of the cookie.
15503 * @return The value of the cookie.
15507 * @cat Plugins/Cookie
15508 * @author Klaus Hartl/klaus.hartl@stilbuero.de
15510 jQuery.cookie = function (key, value, options) {
15512 // key and at least value given, set cookie...
15513 if (arguments.length > 1 && String(value) !== "[object Object]") {
15514 options = jQuery.extend({}, options);
15516 if (value === null || value === undefined) {
15517 options.expires = -1;
15520 if (typeof options.expires === 'number') {
15521 var days = options.expires, t = options.expires = new Date();
15522 t.setDate(t.getDate() + days);
15525 value = String(value);
15527 return (document.cookie = [
15528 encodeURIComponent(key), '=',
15529 options.raw ? value : encodeURIComponent(value),
15530 options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
15531 options.path ? '; path=' + options.path : '',
15532 options.domain ? '; domain=' + options.domain : '',
15533 options.secure ? '; secure' : ''
15537 // key and possibly options given, get cookie...
15538 options = value || {};
15539 var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
15540 return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
15543 (function(/*! Stitch !*/) {
15544 if (!this.require) {
15545 var modules = {}, cache = {}, require = function(name, root) {
15546 var module = cache[name], path = expand(root, name), fn;
15549 } else if (fn = modules[path] || modules[path = expand(path, './index')]) {
15550 module = {id: name, exports: {}};
15552 cache[name] = module.exports;
15553 fn(module.exports, function(name) {
15554 return require(name, dirname(path));
15556 return cache[name] = module.exports;
15558 delete cache[name];
15562 throw 'module \'' + name + '\' not found';
15564 }, expand = function(root, name) {
15565 var results = [], parts, part;
15566 if (/^\.\.?(\/|$)/.test(name)) {
15567 parts = [root, name].join('/').split('/');
15569 parts = name.split('/');
15571 for (var i = 0, length = parts.length; i < length; i++) {
15573 if (part == '..') {
15575 } else if (part != '.' && part != '') {
15576 results.push(part);
15579 return results.join('/');
15580 }, dirname = function(path) {
15581 return path.split('/').slice(0, -1).join('/');
15583 this.require = function(name) {
15584 return require(name, '');
15586 this.require.define = function(bundle) {
15587 for (var key in bundle)
15588 modules[key] = bundle[key];
15591 return this.require.define;
15592 }).call(this)({"collections/locations": function(exports, require, module) {(function() {
15593 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15594 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15595 function ctor() { this.constructor = child; }
15596 ctor.prototype = parent.prototype;
15597 child.prototype = new ctor;
15598 child.__super__ = parent.prototype;
15601 exports.LocationsCollection = (function() {
15602 __extends(LocationsCollection, UberCollection);
15603 function LocationsCollection() {
15604 LocationsCollection.__super__.constructor.apply(this, arguments);
15606 LocationsCollection.prototype.model = app.models.location;
15607 return LocationsCollection;
15610 }, "collections/payment_profiles": function(exports, require, module) {(function() {
15611 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15612 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15613 function ctor() { this.constructor = child; }
15614 ctor.prototype = parent.prototype;
15615 child.prototype = new ctor;
15616 child.__super__ = parent.prototype;
15619 exports.PaymentProfilesCollection = (function() {
15620 __extends(PaymentProfilesCollection, UberCollection);
15621 function PaymentProfilesCollection() {
15622 PaymentProfilesCollection.__super__.constructor.apply(this, arguments);
15624 PaymentProfilesCollection.prototype.model = app.models.paymentprofile;
15625 return PaymentProfilesCollection;
15628 }, "collections/trips": function(exports, require, module) {(function() {
15629 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15630 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15631 function ctor() { this.constructor = child; }
15632 ctor.prototype = parent.prototype;
15633 child.prototype = new ctor;
15634 child.__super__ = parent.prototype;
15637 exports.TripsCollection = (function() {
15638 __extends(TripsCollection, UberCollection);
15639 function TripsCollection() {
15640 TripsCollection.__super__.constructor.apply(this, arguments);
15642 TripsCollection.prototype.model = app.models.trip;
15643 TripsCollection.prototype.url = '/trips';
15644 TripsCollection.prototype.relationships = 'client,driver,city';
15645 return TripsCollection;
15648 }, "lib/config": function(exports, require, module) {(function() {
15649 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
15650 exports.config = (function() {
15651 function config() {
15652 this.get = __bind(this.get, this);
15654 config.prototype.type = 'production';
15655 config.prototype.configurations = {
15659 'url': 'http://dev.www.uber.com:8080',
15660 'googleJsApiKey': 'ABQIAAAAKSiLiNwCxOW479xGFqHoTBTsMh9mumH-zfDa0AhzI7RTmmqoCRTv2C11J43hXCK7vZguPC7CgGDcNQ',
15667 'url': 'http://www.uber.com',
15668 'googleJsApiKey': 'ABQIAAAAKSiLiNwCxOW479xGFqHoTBTsMh9mumH-zfDa0AhzI7RTmmqoCRTv2C11J43hXCK7vZguPC7CgGDcNQ',
15672 'development-vm': {
15673 'api': 'http://192.168.106.1:6543/api',
15674 'url': 'http://192.168.106.1:8080',
15676 'googleJsApiKey': 'ABQIAAAAKSiLiNwCxOW479xGFqHoTBTsMh9mumH-zfDa0AhzI7RTmmqoCRTv2C11J43hXCK7vZguPC7CgGDcNQ',
15681 config.prototype.get = function(param) {
15682 if (this.configurations[this.type][param] === void 0) {
15685 return this.configurations[this.type][param];
15690 }, "lib/uber_collection": function(exports, require, module) {(function() {
15691 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15692 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15693 function ctor() { this.constructor = child; }
15694 ctor.prototype = parent.prototype;
15695 child.prototype = new ctor;
15696 child.__super__ = parent.prototype;
15699 exports.UberCollection = (function() {
15700 __extends(UberCollection, Backbone.Collection);
15701 function UberCollection() {
15702 UberCollection.__super__.constructor.apply(this, arguments);
15704 UberCollection.prototype.parse = function(data) {
15706 this.meta = data.meta;
15707 return data.resources;
15711 return UberCollection;
15714 }, "lib/uber_controller": function(exports, require, module) {(function() {
15715 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15716 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15717 function ctor() { this.constructor = child; }
15718 ctor.prototype = parent.prototype;
15719 child.prototype = new ctor;
15720 child.__super__ = parent.prototype;
15723 exports.UberController = (function() {
15724 __extends(UberController, Backbone.Router);
15725 function UberController() {
15726 UberController.__super__.constructor.apply(this, arguments);
15728 UberController.prototype.LoggedInRedirect = function(callback) {
15729 if ($.cookie('token') !== null) {
15730 return app.routers.clients.navigate('!/dashboard', true);
15732 if (typeof callback === 'function') {
15733 return callback.call();
15737 UberController.prototype.LoggedOutRedirect = function(callback) {
15738 if ($.cookie('token') === null) {
15739 return app.routers.clients.navigate('!/sign-in', true);
15741 if (typeof callback === 'function') {
15742 return callback.call();
15746 return UberController;
15749 }, "lib/uber_sync": function(exports, require, module) {(function() {
15750 exports.UberSync = function(method, model, options) {
15751 var methodMap, params, type;
15755 'delete': 'DELETE',
15758 type = methodMap[method];
15759 params = _.extend({
15762 params.url = _.isString(this.url) ? API + this.url : API + this.url(type);
15763 if (type === "DELETE") {
15764 params.url = "" + params.url + "?token=" + USER.token;
15766 if (!params.data && model && (method === 'create' || method === 'update')) {
15767 params.data = JSON.parse(JSON.stringify(model.toJSON()));
15769 if (Backbone.emulateJSON) {
15770 params.contentType = 'application/x-www-form-urlencoded';
15771 params.processData = true;
15772 params.data = params.data ? {
15776 if (Backbone.emulateHTTP) {
15777 if (type === 'PUT' || type === 'DELETE') {
15778 if (Backbone.emulateJSON) {
15779 params.data._method = type;
15781 params.type = 'POST';
15782 params.beforeSend = function(xhr) {
15783 return xhr.setRequestHeader('X-HTTP-Method-Override', type);
15787 if (!params.data) {
15790 if (!params.data.token && $.cookie('token')) {
15791 params.data.token = $.cookie('token');
15793 params.dataType = 'json';
15794 params.cache = false;
15795 return $.ajax(params);
15798 }, "lib/uber_view": function(exports, require, module) {(function() {
15799 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
15800 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
15801 function ctor() { this.constructor = child; }
15802 ctor.prototype = parent.prototype;
15803 child.prototype = new ctor;
15804 child.__super__ = parent.prototype;
15807 exports.UberView = (function() {
15808 __extends(UberView, Backbone.View);
15809 function UberView() {
15810 this.DownloadUserTrips = __bind(this.DownloadUserTrips, this);
15811 UberView.__super__.constructor.apply(this, arguments);
15813 UberView.prototype.place = function(content) {
15815 $target = this.options.scope ? this.options.scope.find(this.options.selector) : $(this.options.selector);
15816 $target[this.options.method || 'html'](content || this.el);
15817 this.delegateEvents();
15820 UberView.prototype.mixin = function(m, args) {
15822 if (args == null) {
15826 events = m._events;
15828 if (m.initialize) {
15829 m.initialize(self, args);
15831 return _.each(_.keys(events), function(key) {
15832 var event, func, selector, split;
15833 split = key.split(' ');
15835 selector = split[1];
15836 func = events[key];
15837 return $(self.el).find(selector).live(event, function(e) {
15838 return self[func](e);
15842 UberView.prototype.RefreshUserInfo = function(callback, silent) {
15843 if (silent == null) {
15847 this.model = new app.models.client({
15848 id: amplify.store('USERjson').id
15851 if (e.name.toString() === "TypeError") {
15852 app.routers.clients.navigate('!/sign-out', true);
15858 this.ShowSpinner("load");
15860 return this.model.fetch({
15861 success: __bind(function() {
15862 this.HideSpinner();
15863 $.cookie('token', this.model.get('token'));
15864 amplify.store('USERjson', this.model);
15865 this.ReadUserInfo(true);
15866 if (typeof callback === 'function') {
15867 return callback.call();
15871 relationships: 'unexpired_client_promotions,locations,credit_balance,payment_gateway.payment_profiles,client_bills_in_arrears.client_transaction,country'
15876 UberView.prototype.ReadUserInfo = function(forced) {
15877 if (forced == null) {
15880 if (!window.USER.id) {
15881 window.USER = amplify.store('USERjson');
15884 return window.USER = amplify.store('USERjson');
15887 UberView.prototype.DownloadUserPromotions = function(callback, forced) {
15888 var downloadData, stored;
15889 if (forced == null) {
15892 downloadData = __bind(function() {
15893 this.ShowSpinner("load");
15894 this.model = new app.models.client({
15895 id: amplify.store('USERjson').id
15897 return this.model.fetch({
15898 success: __bind(function() {
15899 window.USER.client_promotions = this.model.get('valid_client_promotions');
15900 this.CacheData('USERPromos', this.model.get('valid_client_promotions'));
15901 if (typeof callback === 'function') {
15902 return callback.call();
15906 relationships: 'valid_client_promotions.trips_remaining'
15911 stored = this.GetCache('USERPromos');
15912 if (stored && !forced) {
15913 window.USER.client_promotions = stored;
15914 if (typeof callback === 'function') {
15921 UberView.prototype.DownloadUserTrips = function(callback, forced, limit) {
15922 var downloadData, stored;
15923 if (forced == null) {
15926 if (limit == null) {
15929 downloadData = __bind(function() {
15930 this.ShowSpinner("load");
15931 return app.collections.trips.fetch({
15933 status: 'completed,canceled',
15934 relationships: 'driver,city',
15935 client_id: USER.id,
15938 success: __bind(function() {
15939 window.USER.trips = app.collections.trips;
15940 this.CacheData('USERtrips', window.USER.trips);
15941 if (typeof callback === 'function') {
15944 return this.HideSpinner();
15949 stored = this.GetCache("USERtrips");
15950 if (stored && !forced) {
15951 if (app.collections.trips.length !== stored.length) {
15952 app.collections.trips.reset(stored);
15954 window.USER.trips = app.collections.trips;
15955 if (typeof callback === 'function') {
15956 return callback.call();
15959 return downloadData();
15962 UberView.prototype.ShowSpinner = function(type) {
15963 if (type == null) {
15966 return $('.spinner#' + type).show();
15968 UberView.prototype.HideSpinner = function() {
15969 return $('.spinner').hide();
15971 UberView.prototype.RequireMaps = function(callback) {
15972 if (typeof google !== 'undefined' && google.maps) {
15975 return $.getScript("https://www.google.com/jsapi?key=" + (app.config.get('googleJsApiKey')), function() {
15976 return google.load('maps', 3, {
15977 callback: callback,
15978 other_params: 'sensor=false&language=en&libraries=places'
15983 UberView.prototype.CacheData = function(storeName, data) {
15985 amplify.store(storeName, data);
15986 currentTime = new Date();
15987 amplify.store("" + storeName + "TS", currentTime.getTime());
15989 UberView.prototype.GetCache = function(storeName) {
15990 var cacheTime, currentTime, storedTime;
15991 cacheTime = parseInt(app.config.get('cache')) * 60 * 1000;
15992 currentTime = new Date();
15993 currentTime = currentTime.getTime();
15994 storedTime = amplify.store("" + storeName + "TS");
15996 if (currentTime - storedTime < cacheTime) {
15997 return amplify.store(storeName);
16000 amplify.store("" + storeName + "TS", null);
16001 amplify.store(storeName, null);
16004 UberView.prototype.ClearGlobalStatus = function() {
16005 $('#global_status').find(".success_message").html("").hide();
16006 return $('#global_status').find(".error_message").html("").hide();
16008 UberView.prototype.ShowError = function(message) {
16009 if (message == null) {
16012 this.ClearGlobalStatus();
16013 return $('#global_status').find(".error_message").html(message).fadeIn();
16015 UberView.prototype.ShowSuccess = function(message) {
16016 if (message == null) {
16017 message = "Success";
16019 this.ClearGlobalStatus();
16020 return $('#global_status').find(".success_message").html(message).fadeIn('slow');
16025 }, "main": function(exports, require, module) {(function() {
16026 var ClientsBillingView, ClientsDashboardView, ClientsForgotPasswordView, ClientsInviteView, ClientsLoginView, ClientsPromotionsView, ClientsRequestsView, ClientsRouter, ClientsSettingsView, ClientsSignUpView, Config, ConfirmEmailView, CountriesCollection, CreditCardView, LocationsCollection, PaymentProfilesCollection, SharedFooterView, SharedMenuView, TripDetailView, TripsCollection;
16027 Config = require('lib/config').config;
16028 window.i18n = require('web-lib/i18n').i18n;
16030 Backbone.sync = require('lib/uber_sync').UberSync;
16032 window.UberView = require('lib/uber_view').UberView;
16033 window.UberCollection = require('lib/uber_collection').UberCollection;
16034 window.UberController = require('lib/uber_controller').UberController;
16038 app.collections = {};
16040 app.views.pages = {};
16041 app.views.clients = {};
16042 app.views.clients.modules = {};
16043 app.views.shared = {};
16044 app.views.pages.modules = {};
16045 app.helpers = require('web-lib/helpers').helpers;
16046 app.weblib_helpers = app.helpers;
16047 app.models.client = require('models/client').Client;
16048 app.models.trip = require('models/trip').Trip;
16049 app.models.paymentprofile = require('models/paymentprofile').PaymentProfile;
16050 app.models.clientbills = require('models/clientbills').ClientBills;
16051 app.models.promotions = require('models/promotions').Promotions;
16052 app.models.location = require('models/location').Location;
16053 app.models.country = require('web-lib/models/country').Country;
16054 TripsCollection = require('collections/trips').TripsCollection;
16055 PaymentProfilesCollection = require('collections/payment_profiles').PaymentProfilesCollection;
16056 LocationsCollection = require('collections/locations').LocationsCollection;
16057 CountriesCollection = require('web-lib/collections/countries').CountriesCollection;
16058 ClientsRouter = require('routers/clients_controller').ClientsRouter;
16059 SharedMenuView = require('views/shared/menu').SharedMenuView;
16060 SharedFooterView = require('web-lib/views/footer').SharedFooterView;
16061 ClientsSignUpView = require('views/clients/sign_up').ClientsSignUpView;
16062 ClientsLoginView = require('views/clients/login').ClientsLoginView;
16063 ClientsForgotPasswordView = require('views/clients/forgot_password').ClientsForgotPasswordView;
16064 ClientsDashboardView = require('views/clients/dashboard').ClientsDashboardView;
16065 ClientsInviteView = require('views/clients/invite').ClientsInviteView;
16066 ConfirmEmailView = require('views/clients/confirm_email').ClientsConfirmEmailView;
16067 ClientsPromotionsView = require('views/clients/promotions').ClientsPromotionsView;
16068 ClientsBillingView = require('views/clients/billing').ClientsBillingView;
16069 ClientsSettingsView = require('views/clients/settings').ClientsSettingsView;
16070 ClientsRequestsView = require('views/clients/request').ClientsRequestView;
16071 TripDetailView = require('views/clients/trip_detail').TripDetailView;
16072 CreditCardView = require('views/clients/modules/credit_card').CreditCardView;
16073 $(document).ready(function() {
16074 app.initialize = function() {
16075 var key, _i, _len, _ref;
16076 window.USER = new app.models.client;
16077 if ($.cookie('redirected_user')) {
16078 _ref = _.keys(amplify.store());
16079 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
16081 amplify.store(key, null);
16083 $.cookie('user', $.cookie('redirected_user'));
16084 $.cookie('token', JSON.parse($.cookie('user')).token);
16085 amplify.store('USERjson', JSON.parse($.cookie('user')));
16086 $.cookie('redirected_user', null, {
16087 domain: '.uber.com'
16090 if ($.cookie('user')) {
16091 USER.set(JSON.parse($.cookie('user')));
16093 app.config = new Config();
16094 window.API = app.config.get('api');
16095 window.DISPATCH = app.config.get('dispatch');
16096 app.routers.clients = new ClientsRouter();
16097 app.collections.trips = new TripsCollection();
16098 app.collections.paymentprofiles = new PaymentProfilesCollection();
16099 app.collections.locations = LocationsCollection;
16100 app.collections.countries = CountriesCollection;
16101 app.views.clients.create = new ClientsSignUpView();
16102 app.views.clients.read = new ClientsLoginView();
16103 app.views.clients.forgotpassword = new ClientsForgotPasswordView();
16104 app.views.clients.dashboard = new ClientsDashboardView();
16105 app.views.clients.invite = new ClientsInviteView();
16106 app.views.clients.promotions = new ClientsPromotionsView();
16107 app.views.clients.settings = new ClientsSettingsView();
16108 app.views.clients.tripdetail = new TripDetailView();
16109 app.views.clients.billing = new ClientsBillingView();
16110 app.views.clients.confirmemail = new ConfirmEmailView();
16111 app.views.clients.request = new ClientsRequestsView();
16112 app.views.shared.menu = new SharedMenuView();
16113 app.views.shared.footer = new SharedFooterView();
16114 app.views.clients.modules.creditcard = CreditCardView;
16115 if (Backbone.history.getFragment() === '') {
16116 return app.routers.clients.navigate('!/sign-in', true);
16119 app.refreshMenu = function() {
16120 $('header').html(app.views.shared.menu.render().el);
16121 return $('footer').html(app.views.shared.footer.render().el);
16125 return Backbone.history.start();
16128 }, "models/client": function(exports, require, module) {(function() {
16130 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16131 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16132 function ctor() { this.constructor = child; }
16133 ctor.prototype = parent.prototype;
16134 child.prototype = new ctor;
16135 child.__super__ = parent.prototype;
16138 UberModel = require('web-lib/uber_model').UberModel;
16139 exports.Client = (function() {
16140 __extends(Client, UberModel);
16141 function Client() {
16142 Client.__super__.constructor.apply(this, arguments);
16144 Client.prototype.url = function() {
16146 return "/clients/" + this.id;
16154 }, "models/clientbills": function(exports, require, module) {(function() {
16155 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16156 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16157 function ctor() { this.constructor = child; }
16158 ctor.prototype = parent.prototype;
16159 child.prototype = new ctor;
16160 child.__super__ = parent.prototype;
16163 exports.ClientBills = (function() {
16164 __extends(ClientBills, Backbone.Model);
16165 function ClientBills() {
16166 ClientBills.__super__.constructor.apply(this, arguments);
16168 ClientBills.prototype.url = function() {
16169 return "/client_bills/" + this.id;
16171 return ClientBills;
16174 }, "models/location": function(exports, require, module) {(function() {
16175 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16176 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16177 function ctor() { this.constructor = child; }
16178 ctor.prototype = parent.prototype;
16179 child.prototype = new ctor;
16180 child.__super__ = parent.prototype;
16183 exports.Location = (function() {
16184 __extends(Location, Backbone.Model);
16185 function Location() {
16186 Location.__super__.constructor.apply(this, arguments);
16188 Location.prototype.url = function() {
16190 return "/locations/" + this.id;
16192 return "/locations";
16198 }, "models/paymentprofile": function(exports, require, module) {(function() {
16199 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16200 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16201 function ctor() { this.constructor = child; }
16202 ctor.prototype = parent.prototype;
16203 child.prototype = new ctor;
16204 child.__super__ = parent.prototype;
16207 exports.PaymentProfile = (function() {
16208 __extends(PaymentProfile, Backbone.Model);
16209 function PaymentProfile() {
16210 PaymentProfile.__super__.constructor.apply(this, arguments);
16212 PaymentProfile.prototype.url = function() {
16214 return "/payment_profiles/" + this.id;
16216 return "/payment_profiles";
16219 return PaymentProfile;
16222 }, "models/promotions": function(exports, require, module) {(function() {
16223 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16224 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16225 function ctor() { this.constructor = child; }
16226 ctor.prototype = parent.prototype;
16227 child.prototype = new ctor;
16228 child.__super__ = parent.prototype;
16231 exports.Promotions = (function() {
16232 __extends(Promotions, Backbone.Model);
16233 function Promotions() {
16234 Promotions.__super__.constructor.apply(this, arguments);
16236 Promotions.prototype.url = function() {
16237 return "/clients_promotions";
16242 }, "models/trip": function(exports, require, module) {(function() {
16243 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16244 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16245 function ctor() { this.constructor = child; }
16246 ctor.prototype = parent.prototype;
16247 child.prototype = new ctor;
16248 child.__super__ = parent.prototype;
16251 exports.Trip = (function() {
16252 __extends(Trip, Backbone.Model);
16254 Trip.__super__.constructor.apply(this, arguments);
16256 Trip.prototype.url = function() {
16257 return "/trips/" + (this.get('id'));
16262 }, "routers/clients_controller": function(exports, require, module) {(function() {
16263 var ClientsLoginView;
16264 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
16265 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
16266 function ctor() { this.constructor = child; }
16267 ctor.prototype = parent.prototype;
16268 child.prototype = new ctor;
16269 child.__super__ = parent.prototype;
16272 ClientsLoginView = require('views/clients/login').ClientsLoginView;
16273 exports.ClientsRouter = (function() {
16274 __extends(ClientsRouter, UberController);
16275 function ClientsRouter() {
16276 ClientsRouter.__super__.constructor.apply(this, arguments);
16278 ClientsRouter.prototype.routes = {
16279 "!/sign-up": "signup",
16280 "!/sign-in": "signin",
16281 "!/sign-out": "signout",
16282 "!/forgot-password": "forgotpassword",
16283 "!/forgot-password?email_token=:token": "passwordReset",
16284 "!/dashboard": "dashboard",
16285 "!/invite": "invite",
16286 "!/promotions": "promotions",
16287 "!/settings/information": "settingsInfo",
16288 "!/settings/picture": "settingsPic",
16289 "!/settings/locations": "settingsLoc",
16290 "!/trip/:id": "tripDetail",
16291 "!/billing": "billing",
16292 "!/confirm-email?token=:token": "confirmEmail",
16293 "!/invite/:invite": "signupInvite",
16294 "!/request": "request"
16296 ClientsRouter.prototype.signup = function(invite) {
16298 if (invite == null) {
16301 renderContent = function() {
16302 $('section').html(app.views.clients.create.render(invite).el);
16303 document.title = t('Sign Up') + ' | ' + t('Uber');
16304 $('a').removeClass('active');
16305 return $('a[href="/#!/sign-up"]').addClass('active');
16307 return this.LoggedInRedirect(renderContent);
16309 ClientsRouter.prototype.signupInvite = function(invite) {
16310 return this.signup(invite);
16312 ClientsRouter.prototype.forgotpassword = function() {
16314 renderContent = function() {
16315 $('section').html(app.views.clients.forgotpassword.render().el);
16316 return document.title = t('Password Recovery') + ' | ' + t('Uber');
16318 return this.LoggedInRedirect(renderContent);
16320 ClientsRouter.prototype.signin = function() {
16322 renderContent = function() {
16324 document.title = t('Login') + ' | ' + t('Uber');
16325 view = new ClientsLoginView({
16326 selector: 'section'
16328 $('a').removeClass('active');
16329 return $('a[href="/#!/sign-in"]').addClass('active');
16331 return this.LoggedInRedirect(renderContent);
16333 ClientsRouter.prototype.signout = function() {
16334 $.cookie('token', null);
16335 $.cookie('user', null);
16336 amplify.store('USERjson', null);
16337 amplify.store('USERtrips', null);
16338 amplify.store('USERPromos', null);
16340 return app.routers.clients.navigate('!/sign-in', true);
16342 ClientsRouter.prototype.dashboard = function() {
16344 renderContent = function() {
16345 $('section').html(app.views.clients.dashboard.render().el);
16346 document.title = t('Dashboard') + ' | ' + t('Uber');
16347 $('a').removeClass('active');
16348 return $('a[href="/#!/dashboard"]').addClass('active');
16350 return this.LoggedOutRedirect(renderContent);
16352 ClientsRouter.prototype.invite = function() {
16354 renderContent = function() {
16355 $('section').html(app.views.clients.invite.render().el);
16356 document.title = t('Invite Friends') + ' | ' + t('Uber');
16357 $('a').removeClass('active');
16358 return $('a[href="/#!/invite"]').addClass('active');
16360 return this.LoggedOutRedirect(renderContent);
16362 ClientsRouter.prototype.tripDetail = function(id) {
16364 renderContent = function() {
16365 $('a').removeClass('active');
16366 $('section').html(app.views.clients.tripdetail.render(id).el);
16367 return document.title = t('Trip Detail') + ' | ' + t('Uber');
16369 return this.LoggedOutRedirect(renderContent);
16371 ClientsRouter.prototype.promotions = function() {
16373 renderContent = function() {
16374 $('section').html(app.views.clients.promotions.render().el);
16375 document.title = t('Promotions') + ' | ' + t('Uber');
16376 $('a').removeClass('active');
16377 return $('a[href="/#!/promotions"]').addClass('active');
16379 return this.LoggedOutRedirect(renderContent);
16381 ClientsRouter.prototype.settingsInfo = function() {
16383 renderContent = function() {
16384 $('section').html(app.views.clients.settings.render('info').el);
16385 $('a').removeClass('active');
16386 return $('a[href="/#!/settings/information"]').addClass('active');
16388 return this.LoggedOutRedirect(renderContent);
16390 ClientsRouter.prototype.settingsLoc = function() {
16392 renderContent = function() {
16393 $('section').html(app.views.clients.settings.render('loc').el);
16394 $('a').removeClass('active');
16395 return $('a[href="/#!/settings/information"]').addClass('active');
16397 return this.LoggedOutRedirect(renderContent);
16399 ClientsRouter.prototype.settingsPic = function() {
16401 renderContent = function() {
16402 $('section').html(app.views.clients.settings.render('pic').el);
16403 $('a').removeClass('active');
16404 return $('a[href="/#!/settings/information"]').addClass('active');
16406 return this.LoggedOutRedirect(renderContent);
16408 ClientsRouter.prototype.passwordReset = function(token) {
16410 if (token == null) {
16413 renderContent = function() {
16414 $('section').html(app.views.clients.forgotpassword.render(token).el);
16415 document.title = t('Password Reset') + ' | ' + t('Uber');
16416 return $('a').removeClass('active');
16418 return this.LoggedInRedirect(renderContent);
16420 ClientsRouter.prototype.billing = function() {
16422 renderContent = function() {
16423 $('section').html(app.views.clients.billing.render().el);
16424 document.title = t('Billing') + ' | ' + t('Uber');
16425 $('a').removeClass('active');
16426 return $('a[href="/#!/billing"]').addClass('active');
16428 return this.LoggedOutRedirect(renderContent);
16430 ClientsRouter.prototype.confirmEmail = function(token) {
16431 $('section').html(app.views.clients.confirmemail.render(token).el);
16432 document.title = t('Confirm Email') + ' | ' + t('Uber');
16433 return $('a').removeClass('active');
16435 ClientsRouter.prototype.request = function() {
16437 renderContent = function() {
16438 $('section').html(app.views.clients.request.render().el);
16439 document.title = t('Request Ride') + ' | ' + t('Uber');
16440 $('a').removeClass('active');
16441 return $('a[href="/#!/request"]').addClass('active');
16443 return this.LoggedOutRedirect(renderContent);
16445 ClientsRouter.prototype.errorPage = function(path) {
16446 if (path == null) {
16449 return app.helpers.debug(path, "path");
16451 return ClientsRouter;
16454 }, "templates/clients/billing": function(exports, require, module) {module.exports = function(__obj) {
16455 if (!__obj) __obj = {};
16456 var __out = [], __capture = function(callback) {
16457 var out = __out, result;
16459 callback.call(this);
16460 result = __out.join('');
16462 return __safe(result);
16463 }, __sanitize = function(value) {
16464 if (value && value.ecoSafe) {
16466 } else if (typeof value !== 'undefined' && value != null) {
16467 return __escape(value);
16471 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16472 __safe = __obj.safe = function(value) {
16473 if (value && value.ecoSafe) {
16476 if (!(typeof value !== 'undefined' && value != null)) value = '';
16477 var result = new String(value);
16478 result.ecoSafe = true;
16483 __escape = __obj.escape = function(value) {
16484 return ('' + value)
16485 .replace(/&/g, '&')
16486 .replace(/</g, '<')
16487 .replace(/>/g, '>')
16488 .replace(/"/g, '"');
16493 var arrears, numCards, printArrear, printCardOption;
16494 numCards = parseInt(USER.payment_gateway.payment_profiles.length);
16496 arrears = USER.client_bills_in_arrears;
16497 __out.push('\n\n');
16498 printCardOption = function(card) {
16499 __out.push('\n <option value="');
16500 __out.push(__sanitize(card.id));
16502 __out.push(__sanitize(t('Card Ending in')));
16504 __out.push(__sanitize(card.card_number));
16505 return __out.push(' </option>\n');
16507 __out.push('\n\n');
16508 printArrear = function(arrear) {
16509 __out.push('\n<tr>\n <td>\n <a href="#!/trip/');
16510 __out.push(__sanitize(arrear.client_transaction.trip_id));
16511 __out.push('"> <img src="https://uber-static.s3.amazonaws.com/map_icon.png" alt="');
16512 __out.push(__sanitize(t('Trip Map')));
16513 __out.push('" /></a>\n <div class="arrear_info">\n <span id="amount"> ');
16514 __out.push(__sanitize(t('Amount', {
16515 amount: app.helpers.formatCurrency(Math.abs(arrear.client_transaction.amount))
16517 __out.push(' </span>\n <span id="date"> ');
16518 __out.push(__sanitize(t('Last Attempt to Bill', {
16519 date: app.helpers.parseDate(arrear.updated_at)
16521 __out.push(' </span>\n </div>\n </td>\n ');
16522 if (numCards !== 0) {
16523 __out.push('\n <td>\n <p class="error_message"></p>\n <p class="success_message"></p>\n <select id="card_to_charge">\n ');
16524 _.each(USER.payment_gateway.payment_profiles, printCardOption);
16525 __out.push('\n </select>\n <button class="button charge_arrear" id="');
16526 __out.push(__sanitize(arrear.id));
16527 __out.push('" data-theme="a"><span>');
16528 __out.push(__sanitize(t('Charge')));
16529 __out.push('</span></button>\n </td>\n ');
16531 return __out.push('\n</tr>\n');
16533 __out.push('\n\n\n\n');
16534 __out.push(require('templates/clients/modules/sub_header').call(this, {
16535 heading: t("Billing")
16537 __out.push('\n\n<div id="main_content">\n <div>\n <div id="credit_card_wrapper">\n <div id="global_status">\n <span class="success_message"></span>\n <span class="error_message"></span>\n </div>\n\n ');
16538 if (USER.payment_gateway.payment_profiles.length > 0) {
16539 __out.push('\n <h2>');
16540 __out.push(__sanitize(t('Credit Cards')));
16541 __out.push('</h2>\n <div id="cards"></div>\n <p><a id="add_card" href="">');
16542 __out.push(__sanitize(t('add a new credit card')));
16543 __out.push('</a></p>\n ');
16545 __out.push('\n <div id="add_card_wrapper"> </div>\n ');
16547 __out.push('\n </div>\n ');
16548 if (USER.credit_balance > 0) {
16549 __out.push('\n <div id="account_balance_wrapper">\n <h2>');
16550 __out.push(__sanitize(t('Account Balance')));
16551 __out.push('</h2>\n <p>\n ');
16552 __out.push(__sanitize(t("Uber Credit Balance Note", {
16553 amount: app.helpers.formatCurrency(USER.credit_balance)
16555 __out.push('\n </p>\n </div>\n ');
16558 if (arrears.length > 0) {
16559 __out.push('\n <div id="arrears_wrapper">\n <h2>');
16560 __out.push(__sanitize(t('Arrears')));
16561 __out.push('</h2>\n ');
16562 if (numCards === 0) {
16563 __out.push('\n <strong> ');
16564 __out.push(__sanitize(t('Please Add Credit Card')));
16565 __out.push(' </strong>\n ');
16567 __out.push('\n <table>\n <tbody>\n ');
16568 _.each(arrears, printArrear);
16569 __out.push('\n </tbody>\n </table>\n </div>\n ');
16571 __out.push('\n </div>\n</div>\n<div id="main_shadow"></div>\n\n');
16575 __obj.safe = __objSafe, __obj.escape = __escape;
16576 return __out.join('');
16577 }}, "templates/clients/confirm_email": function(exports, require, module) {module.exports = function(__obj) {
16578 if (!__obj) __obj = {};
16579 var __out = [], __capture = function(callback) {
16580 var out = __out, result;
16582 callback.call(this);
16583 result = __out.join('');
16585 return __safe(result);
16586 }, __sanitize = function(value) {
16587 if (value && value.ecoSafe) {
16589 } else if (typeof value !== 'undefined' && value != null) {
16590 return __escape(value);
16594 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16595 __safe = __obj.safe = function(value) {
16596 if (value && value.ecoSafe) {
16599 if (!(typeof value !== 'undefined' && value != null)) value = '';
16600 var result = new String(value);
16601 result.ecoSafe = true;
16606 __escape = __obj.escape = function(value) {
16607 return ('' + value)
16608 .replace(/&/g, '&')
16609 .replace(/</g, '<')
16610 .replace(/>/g, '>')
16611 .replace(/"/g, '"');
16616 __out.push('<div id="sub_header">\n <h1>');
16617 __out.push(__sanitize(t('Confirm Email')));
16618 __out.push('</h1>\n</div>\n\n<div id="main_content">\n <div>\n <h3 id="attempt_text">');
16619 __out.push(__sanitize(t('Confirm Email Message')));
16620 __out.push('</h3>\n <h3 class="success_message" style="display:none">');
16621 __out.push(__sanitize(t('Confirm Email Succeeded')));
16622 __out.push('</h3>\n <h3 class="already_confirmed_message" style="display:none">');
16623 __out.push(__sanitize(t('Email Already Confirmed')));
16624 __out.push('</h3>\n <h3 class="error_message" style="display:none">');
16625 __out.push(__sanitize(t('Confirm Email Failed')));
16626 __out.push('</h3>\n </div>\n</div>\n<div id="main_shadow"></div>\n\n');
16630 __obj.safe = __objSafe, __obj.escape = __escape;
16631 return __out.join('');
16632 }}, "templates/clients/dashboard": function(exports, require, module) {module.exports = function(__obj) {
16633 if (!__obj) __obj = {};
16634 var __out = [], __capture = function(callback) {
16635 var out = __out, result;
16637 callback.call(this);
16638 result = __out.join('');
16640 return __safe(result);
16641 }, __sanitize = function(value) {
16642 if (value && value.ecoSafe) {
16644 } else if (typeof value !== 'undefined' && value != null) {
16645 return __escape(value);
16649 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16650 __safe = __obj.safe = function(value) {
16651 if (value && value.ecoSafe) {
16654 if (!(typeof value !== 'undefined' && value != null)) value = '';
16655 var result = new String(value);
16656 result.ecoSafe = true;
16661 __escape = __obj.escape = function(value) {
16662 return ('' + value)
16663 .replace(/&/g, '&')
16664 .replace(/</g, '<')
16665 .replace(/>/g, '>')
16666 .replace(/"/g, '"');
16671 var printStar, trip, _i, _len, _ref, _ref2, _ref3, _ref4;
16672 printStar = function() {
16673 return __out.push('\n <img alt="Star" src="/web/img/star.png"/>\n');
16675 __out.push('\n\n');
16676 __out.push(require('templates/clients/modules/sub_header').call(this, {
16677 heading: t("Dashboard")
16679 __out.push('\n\n\n<div id="main_content">\n <div>\n <div id="confirmation">\n ');
16680 if (((_ref = USER.payment_gateway) != null ? (_ref2 = _ref.payment_profiles) != null ? _ref2.length : void 0 : void 0) > 0) {
16681 __out.push('\n <div id="confirmed_credit_card" class="true left">');
16682 __out.push(__sanitize(t('Credit Card Added')));
16683 __out.push('</div>\n ');
16685 __out.push('\n <div id="confirmed_credit_card" class="false left"><a id="card" class="confirmation" href="">');
16686 __out.push(__sanitize(t('No Credit Card')));
16687 __out.push('</a></div>\n ');
16689 __out.push('\n\n ');
16690 if (USER.confirm_mobile === true) {
16691 __out.push('\n <div id="confirmed_mobile" class="true">');
16692 __out.push(__sanitize(t('Mobile Number Confirmed')));
16693 __out.push('</div>\n ');
16695 __out.push('\n <div id="confirmed_mobile" class="false"><a id="mobile" class="confirmation" href="">');
16696 __out.push(__sanitize(t('No Confirmed Mobile')));
16697 __out.push('</a></div>\n ');
16699 __out.push('\n\n ');
16700 if (USER.confirm_email === true) {
16701 __out.push('\n <div id="confirmed_email" class="true right">');
16702 __out.push(__sanitize(t('E-mail Address Confirmed')));
16703 __out.push('</div>\n ');
16705 __out.push('\n <div id="confirmed_email" class="false right"><a id="email" class="confirmation" href="">');
16706 __out.push(__sanitize(t('No Confirmed E-mail')));
16707 __out.push('</a></div>\n ');
16709 __out.push('\n\n <div id="more_info" style="display:none;">\n <div id="mobile" class="info">\n <span>');
16710 __out.push(__sanitize(t('Reply to sign up text')));
16711 __out.push('</span>\n <a id="resend_mobile" class="resend" href="">');
16712 __out.push(__sanitize(t('Resend text message')));
16713 __out.push('</a>\n </div>\n <div id="email" class="info">\n <span>');
16714 __out.push(__sanitize(t('Click sign up link')));
16715 __out.push('</span>\n <a id="resend_email" class="resend" href="">');
16716 __out.push(__sanitize(t('Resend email')));
16717 __out.push('</a>\n </div>\n <div id="card" class="info">\n <span>');
16718 __out.push(__sanitize(t("Add a credit card to ride")));
16719 __out.push('</span>\n </div>\n </div>\n </div>\n\n <div id="dashboard_trips">\n ');
16720 if (USER.trips.length > 0) {
16721 __out.push('\n <div id="trip_details_map"></div>\n <div id="trip_details_info">\n <h2>');
16722 __out.push(__sanitize(t('Your Most Recent Trip')));
16723 __out.push('</h2>\n <span><a href="#!/trip/');
16724 __out.push(__sanitize(_.first(USER.trips.models).get('random_id')));
16726 __out.push(__sanitize(t('details')));
16727 __out.push('</a></span>\n\n <div id="avatars">\n <img alt="Driver image" height="45" src="');
16728 __out.push(__sanitize(_.first(USER.trips.models).get('driver').picture_url));
16729 __out.push('" width="45"/>\n <span>');
16730 __out.push(__sanitize("" + (_.first(USER.trips.models).get('driver').first_name)));
16731 __out.push('</span>\n <div class="clear">\n </div>\n </div>\n <h3>');
16732 __out.push(__sanitize(t('Rating')));
16733 __out.push('</h3>\n ');
16734 _(_.first(USER.trips.models).get('driver_rating')).times(printStar);
16735 __out.push('\n </div>\n <div class="clear">\n </div>\n <div class="table_wrapper">\n <h2>');
16736 __out.push(__sanitize(t('Your Trip History ')));
16737 __out.push('</h2>\n <table class="zebra">\n <colgroup>\n <col width="*" />\n <col width="200" />\n <col width="120" />\n <col width="100" />\n </colgroup>\n <thead>\n <tr>\n <td class="text">\n ');
16738 __out.push(__sanitize(t('Pickup Time')));
16739 __out.push('\n </td>\n <td class="text">\n ');
16740 __out.push(__sanitize(t('Status')));
16741 __out.push('\n </td>\n <td class="text">\n ');
16742 __out.push(__sanitize(t('Driver')));
16743 __out.push('\n </td>\n <td class="graphic">\n ');
16744 __out.push(__sanitize(t('Rating')));
16745 __out.push('\n </td>\n <td class="num">\n ');
16746 __out.push(__sanitize(t('Fare')));
16747 __out.push('\n </td>\n </tr>\n </thead>\n <tbody>\n ');
16748 _ref3 = USER.trips.models;
16749 for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
16751 __out.push('\n <tr>\n <td class="text"><a href="#!/trip/');
16752 __out.push(__sanitize(trip.get('random_id')));
16754 __out.push(__sanitize(app.helpers.formatDate(trip.get('request_at'), true, trip.get('city').timezone)));
16755 __out.push('</a></td>\n <td class="text">');
16756 __out.push(__sanitize(trip.get('status')));
16757 __out.push('</td>\n <td class="text">');
16758 __out.push(__sanitize((_ref4 = trip.get('driver')) != null ? _ref4.first_name : void 0));
16759 __out.push('</td>\n <td class="graphic">');
16760 _(trip.get('driver_rating')).times(printStar);
16761 __out.push('</td>\n <td class="num">');
16762 __out.push(__sanitize(app.helpers.formatTripFare(trip)));
16763 __out.push('</td>\n </tr>\n ');
16765 __out.push('\n </tbody>\n </table>\n <a id="show_all_trips" href="">');
16766 __out.push(__sanitize(t('Show all trips')));
16767 __out.push('</a>\n </div>\n ');
16769 __out.push('\n <p><strong>');
16770 __out.push(__sanitize(t("Here's how it works:")));
16771 __out.push('</strong></p>\n <ol class="spaced">\n <li>\n ');
16772 __out.push(__sanitize(t('Set your location:')));
16773 __out.push('\n <ul>\n <li>');
16774 __out.push(__sanitize(t('App search for address')));
16775 __out.push('</li>\n <li>');
16776 __out.push(__sanitize(t('SMS text address')));
16777 __out.push('</li>\n </ul>\n </li>\n <li>');
16778 __out.push(__sanitize(t('Confirm pickup request')));
16779 __out.push('</li>\n <li>');
16780 __out.push(__sanitize(t('Uber sends ETA')));
16781 __out.push('</li>\n <li>');
16782 __out.push(__sanitize(t('Car arrives')));
16783 __out.push('</li>\n <li>');
16784 __out.push(__sanitize(t('Ride to destination')));
16785 __out.push('</li>\n </ol>\n <p>');
16786 __out.push(__sanitize(t('Thank your driver')));
16787 __out.push('</p>\n ');
16789 __out.push('\n </div>\n\n </div>\n</div>\n<div id="main_shadow"></div>\n');
16793 __obj.safe = __objSafe, __obj.escape = __escape;
16794 return __out.join('');
16795 }}, "templates/clients/forgot_password": function(exports, require, module) {module.exports = function(__obj) {
16796 if (!__obj) __obj = {};
16797 var __out = [], __capture = function(callback) {
16798 var out = __out, result;
16800 callback.call(this);
16801 result = __out.join('');
16803 return __safe(result);
16804 }, __sanitize = function(value) {
16805 if (value && value.ecoSafe) {
16807 } else if (typeof value !== 'undefined' && value != null) {
16808 return __escape(value);
16812 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16813 __safe = __obj.safe = function(value) {
16814 if (value && value.ecoSafe) {
16817 if (!(typeof value !== 'undefined' && value != null)) value = '';
16818 var result = new String(value);
16819 result.ecoSafe = true;
16824 __escape = __obj.escape = function(value) {
16825 return ('' + value)
16826 .replace(/&/g, '&')
16827 .replace(/</g, '<')
16828 .replace(/>/g, '>')
16829 .replace(/"/g, '"');
16834 __out.push('<div id="form_container">\n ');
16836 __out.push('\n <h1>');
16837 __out.push(__sanitize(t('Password Reset')));
16838 __out.push('</h1>\n <div id="standard_form">\n\n <p>');
16839 __out.push(__sanitize(t('Please choose a new password.')));
16840 __out.push('</p>\n\n <p class="error_message" style="display:none;">');
16841 __out.push(__sanitize(t('Password Reset Error')));
16842 __out.push('</p>\n\n <form id="password_reset" action="" method="">\n\n <input id="token" type="hidden" name="token" value="');
16843 __out.push(__sanitize(this.token));
16844 __out.push('">\n\n <div class="form_label">\n <label for="password">');
16845 __out.push(__sanitize(t('New Password')));
16846 __out.push('</label>\n </div>\n\n <div class="form_input">\n <input id="password" name="password" type="password" value=""/>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="formSubmitButton"><button id="password_reset_submit" type="submit" class="button" data-theme="a"><span>Reset Password</span></button></div>\n\n </form>\n </div>\n\n ');
16848 __out.push('\n <h1>');
16849 __out.push(__sanitize(t('Forgot Password')));
16850 __out.push('</h1>\n <div id="standard_form">\n\n <p>');
16851 __out.push(t('Forgot Password Enter Email'));
16852 __out.push('\n\n <p class="error_message" style="display:none;">');
16853 __out.push(__sanitize(t('Forgot Password Error')));
16854 __out.push('</p>\n\n <p class="success_message" style="display:none;">');
16855 __out.push(__sanitize(t('Forgot Password Success')));
16856 __out.push('</p>\n\n <form id="forgot_password" action="" method="">\n\n <div class="form_label">\n <label for="login">');
16857 __out.push(__sanitize(t('Email Address')));
16858 __out.push('</label>\n </div>\n\n <div class="form_input">\n <input id="login" name="login" type="text" value=""/>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="formSubmitButton"><button type="submit" class="button" data-theme="a"><span>');
16859 __out.push(__sanitize(t('Reset Password')));
16860 __out.push('</span></button></div>\n </form>\n\n </div>\n ');
16862 __out.push('\n\n</div>\n\n<div id="small_container_shadow"><div class="left"></div><div class="right"></div></div>\n');
16866 __obj.safe = __objSafe, __obj.escape = __escape;
16867 return __out.join('');
16868 }}, "templates/clients/invite": function(exports, require, module) {module.exports = function(__obj) {
16869 if (!__obj) __obj = {};
16870 var __out = [], __capture = function(callback) {
16871 var out = __out, result;
16873 callback.call(this);
16874 result = __out.join('');
16876 return __safe(result);
16877 }, __sanitize = function(value) {
16878 if (value && value.ecoSafe) {
16880 } else if (typeof value !== 'undefined' && value != null) {
16881 return __escape(value);
16885 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16886 __safe = __obj.safe = function(value) {
16887 if (value && value.ecoSafe) {
16890 if (!(typeof value !== 'undefined' && value != null)) value = '';
16891 var result = new String(value);
16892 result.ecoSafe = true;
16897 __escape = __obj.escape = function(value) {
16898 return ('' + value)
16899 .replace(/&/g, '&')
16900 .replace(/</g, '<')
16901 .replace(/>/g, '>')
16902 .replace(/"/g, '"');
16907 __out.push(require('templates/clients/modules/sub_header').call(this, {
16908 heading: t("Invite friends")
16910 __out.push('\n\n<div id="main_content">\n <div>\n <h2>');
16911 __out.push(__sanitize(t('Give $ Get $')));
16912 __out.push('</h2>\n\n <p>\n ');
16913 __out.push(__sanitize(t('Give $ Get $ Description')));
16914 __out.push('\n </p>\n\n <p>');
16915 __out.push(__sanitize(t('What are you waiting for?')));
16916 __out.push('</p>\n <div id="social_icons">\n <div>\n <a style="float:left" href="https://twitter.com/share" class="twitter-share-button" data-url="');
16917 __out.push(__sanitize(USER.referral_url));
16918 __out.push('" data-text="Sign up for @uber with my link and get $10 off your first ride! " data-count="none">');
16919 __out.push(__sanitize(t('Tweet')));
16920 __out.push('</a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script>\n </div>\n <div>\n <div id="fb-root"></div>\n <script>(function(d, s, id) {\n var js, fjs = d.getElementsByTagName(s)[0];\n js = d.createElement(s); js.id = id;\n js.src = "//connect.facebook.net/" + window.i18n.getLocale() + "/all.js#appId=124678754298965&xfbml=1";\n fjs.parentNode.insertBefore(js, fjs);\n }(document, \'script\', \'facebook-jssdk\'));</script>\n\n <div class="fb-like" data-href="');
16921 __out.push(__sanitize(USER.referral_url));
16922 __out.push('" data-send="true" data-layout="button_count" data-width="180" data-show-faces="false" data-action="recommend" data-font="lucida grande"></div>\n </div>\n </div>\n <br>\n <p>');
16923 __out.push(__sanitize(t('Invite Link')));
16924 __out.push(' <a href="');
16925 __out.push(__sanitize(USER.referral_url));
16927 __out.push(__sanitize(USER.referral_url));
16928 __out.push('</a> </p>\n\n </div>\n</div>\n<div id="main_shadow"></div>\n\n');
16932 __obj.safe = __objSafe, __obj.escape = __escape;
16933 return __out.join('');
16934 }}, "templates/clients/login": function(exports, require, module) {module.exports = function(__obj) {
16935 if (!__obj) __obj = {};
16936 var __out = [], __capture = function(callback) {
16937 var out = __out, result;
16939 callback.call(this);
16940 result = __out.join('');
16942 return __safe(result);
16943 }, __sanitize = function(value) {
16944 if (value && value.ecoSafe) {
16946 } else if (typeof value !== 'undefined' && value != null) {
16947 return __escape(value);
16951 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
16952 __safe = __obj.safe = function(value) {
16953 if (value && value.ecoSafe) {
16956 if (!(typeof value !== 'undefined' && value != null)) value = '';
16957 var result = new String(value);
16958 result.ecoSafe = true;
16963 __escape = __obj.escape = function(value) {
16964 return ('' + value)
16965 .replace(/&/g, '&')
16966 .replace(/</g, '<')
16967 .replace(/>/g, '>')
16968 .replace(/"/g, '"');
16973 __out.push('<div id="form_container">\n\t<h1>');
16974 __out.push(__sanitize(t('Sign In')));
16975 __out.push('</h1>\n\t<div id="standard_form">\n\t\t<form method="post">\n\n\t\t\t<p class="error_message" style="display:none;"></span>\n\n\t\t\t<div class="form_label">\n\t\t\t\t<label for="login">');
16976 __out.push(__sanitize(t('Email Address')));
16977 __out.push('</label>\n\t\t\t</div>\n\t\t\t<div class="form_input">\n\t\t\t\t<input id="login" name="login" type="text" value=""/>\n\t\t\t</div>\n\n\t\t\t<div class="form_clear"></div>\n\n\t\t\t<div class="form_label">\n\t\t\t\t<label for="password">');
16978 __out.push(__sanitize(t('Password')));
16979 __out.push('</label>\n\t\t\t</div>\n\t\t\t<div class="form_input">\n\t\t\t\t<input id="password" name="password" type="password" value=""/>\n\t\t\t</div>\n\n\t\t\t<div class="form_clear"></div>\n\n <div class="formSubmitButton"><button type="submit" class="button" data-theme="a"><span>');
16980 __out.push(__sanitize(t('Sign In')));
16981 __out.push('</span></button></div>\n\n <h2><a href=\'/#!/forgot-password\'>');
16982 __out.push(__sanitize(t('Forgot Password?')));
16983 __out.push('</a></h2>\n\n\t\t</form>\n\t</div>\n</div>\n\n<div class="clear"></div>\n<div id="small_container_shadow"><div class="left"></div><div class="right"></div></div>\n');
16987 __obj.safe = __objSafe, __obj.escape = __escape;
16988 return __out.join('');
16989 }}, "templates/clients/modules/credit_card": function(exports, require, module) {module.exports = function(__obj) {
16990 if (!__obj) __obj = {};
16991 var __out = [], __capture = function(callback) {
16992 var out = __out, result;
16994 callback.call(this);
16995 result = __out.join('');
16997 return __safe(result);
16998 }, __sanitize = function(value) {
16999 if (value && value.ecoSafe) {
17001 } else if (typeof value !== 'undefined' && value != null) {
17002 return __escape(value);
17006 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17007 __safe = __obj.safe = function(value) {
17008 if (value && value.ecoSafe) {
17011 if (!(typeof value !== 'undefined' && value != null)) value = '';
17012 var result = new String(value);
17013 result.ecoSafe = true;
17018 __escape = __obj.escape = function(value) {
17019 return ('' + value)
17020 .replace(/&/g, '&')
17021 .replace(/</g, '<')
17022 .replace(/>/g, '>')
17023 .replace(/"/g, '"');
17029 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
17030 if (this.cards === "new") {
17031 __out.push('\n <div id="cc_form_wrapper" class="inline_label_form wider_inline_label_form">\n <form action="" id="credit_card_form" method="">\n <div id="top_of_form" class="error_message"></div>\n <div id="card_logos"></div>\n <div id="credit_card_number_wrapper" data-role="fieldcontain">\n <div class="error_message"></div>\n <label>');
17032 __out.push(__sanitize(t('Credit Card Number')));
17033 __out.push('</label>\n <input id="card_number" name="card_number" type="text"/>\n </div>\n <div class="clear"></div>\n <div id="expiration_wrapper" data-role="fieldcontain">\n <div class="error_message"></div>\n <label for="expiration_month">');
17034 __out.push(__sanitize(t('Expiration')));
17035 __out.push('</label>\n <select id="card_expiration_month" name="expiration_month">\n <option value="">');
17036 __out.push(__sanitize(t('month')));
17037 __out.push('</option>\n <option value="01">');
17038 __out.push(__sanitize(t('01-Jan')));
17039 __out.push('</option>\n <option value="02">');
17040 __out.push(__sanitize(t('02-Feb')));
17041 __out.push('</option>\n <option value="03">');
17042 __out.push(__sanitize(t('03-Mar')));
17043 __out.push('</option>\n <option value="04">');
17044 __out.push(__sanitize(t('04-Apr')));
17045 __out.push('</option>\n <option value="05">');
17046 __out.push(__sanitize(t('05-May')));
17047 __out.push('</option>\n <option value="06">');
17048 __out.push(__sanitize(t('06-Jun')));
17049 __out.push('</option>\n <option value="07">');
17050 __out.push(__sanitize(t('07-Jul')));
17051 __out.push('</option>\n <option value="08">');
17052 __out.push(__sanitize(t('08-Aug')));
17053 __out.push('</option>\n <option value="09">');
17054 __out.push(__sanitize(t('09-Sep')));
17055 __out.push('</option>\n <option value="10">');
17056 __out.push(__sanitize(t('10-Oct')));
17057 __out.push('</option>\n <option value="11">');
17058 __out.push(__sanitize(t('11-Nov')));
17059 __out.push('</option>\n <option value="12">');
17060 __out.push(__sanitize(t('12-Dec')));
17061 __out.push('</option>\n </select>\n </div>\n <div>\n <span style="display:inline" class="error_message"></span>\n <select id="card_expiration_year" name="expiration_year">\n <option selected="selected" value="">');
17062 __out.push(__sanitize(t('year')));
17063 __out.push('</option>\n <option value="2011">');
17064 __out.push(__sanitize(t('2011')));
17065 __out.push('</option>\n <option value="2012">');
17066 __out.push(__sanitize(t('2012')));
17067 __out.push('</option>\n <option value="2013">');
17068 __out.push(__sanitize(t('2013')));
17069 __out.push('</option>\n <option value="2014">');
17070 __out.push(__sanitize(t('2014')));
17071 __out.push('</option>\n <option value="2015">');
17072 __out.push(__sanitize(t('2015')));
17073 __out.push('</option>\n <option value="2016">');
17074 __out.push(__sanitize(t('2016')));
17075 __out.push('</option>\n <option value="2017">');
17076 __out.push(__sanitize(t('2017')));
17077 __out.push('</option>\n <option value="2018">');
17078 __out.push(__sanitize(t('2018')));
17079 __out.push('</option>\n <option value="2019">');
17080 __out.push(__sanitize(t('2019')));
17081 __out.push('</option>\n <option value="2020">');
17082 __out.push(__sanitize(t('2020')));
17083 __out.push('</option>\n </select>\n </div>\n <div class="clear"></div>\n <div id="cvv_wrapper" data-role="fieldcontain">\n <div class="error_message"></div>\n <label for="card_code">');
17084 __out.push(__sanitize(t('CVV')));
17085 __out.push('</label>\n <input id="card_code" name="card_code" type="text"/>\n </div>\n <div class="clear"></div>\n <div>\n <label for="use_case">');
17086 __out.push(__sanitize(t('Category')));
17087 __out.push('</label>\n <select id="use_case">\n <option value="personal" selected="true">');
17088 __out.push(__sanitize(t('personal')));
17089 __out.push('</option>\n <option value="business">');
17090 __out.push(__sanitize(t('business')));
17091 __out.push('</option>\n </select>\n </div>\n <div class="clear"></div>\n <div id="default_wrapper" data-role="fieldcontain">\n <label for="default">');
17092 __out.push(__sanitize(t('Default Credit Card')));
17093 __out.push('</label>\n <input id="default_check" type="checkbox" name="default" value="true"/>\n </div>\n <div class="clear"></div>\n <div>\n <button id="new_card" type="submit" class="button" data-theme="a"><span>');
17094 __out.push(__sanitize(t('Add Credit Card')));
17095 __out.push('</span></button>\n </div>\n </form>\n </div>\n');
17098 printCard = __bind(function(card, index) {
17100 __out.push('\n <tr id="');
17101 __out.push(__sanitize("d" + index));
17102 __out.push('">\n <td>\n ');
17103 style = "background-position:-173px";
17105 if (card.get("card_type") === "Visa") {
17106 style = "background-position:0px";
17109 if (card.get("card_type") === "MasterCard") {
17110 style = "background-position:-42px";
17113 if (card.get("card_type") === "American Express") {
17114 style = "background-position:-130px";
17117 if (card.get("card_type") === "Discover Card") {
17118 style = "background-position:-85px";
17120 __out.push('\n <div class="card_type" style="');
17121 __out.push(__sanitize(style));
17122 __out.push('"></div>\n </td>\n <td>\n ****');
17123 __out.push(__sanitize(card.get("card_number")));
17124 __out.push('\n </td>\n <td>\n ');
17125 if (card.get("card_expiration")) {
17127 __out.push(__sanitize(t('Expiry')));
17129 exp = card.get('card_expiration').split('-');
17131 __out.push(__sanitize("" + exp[0] + "-" + exp[1]));
17134 __out.push('\n </td>\n <td>\n <select class="use_case">\n <option ');
17135 __out.push(__sanitize(card.get("use_case") === "personal" ? "selected" : void 0));
17136 __out.push(' value="personal">');
17137 __out.push(__sanitize(t('personal')));
17138 __out.push('</option>\n <option ');
17139 __out.push(__sanitize(card.get("use_case") === "business" ? "selected" : void 0));
17140 __out.push(' value="business">');
17141 __out.push(__sanitize(t('business')));
17142 __out.push('</option>\n </select>\n </td>\n <td>\n ');
17143 if (card.get("default")) {
17144 __out.push('\n <strong>(');
17145 __out.push(__sanitize(t('default card')));
17146 __out.push(')</strong>\n ');
17149 if (this.cards.length > 1 && !card.get("default")) {
17150 __out.push('\n <a class="make_default" href="">');
17151 __out.push(__sanitize(t('make default')));
17152 __out.push('</a>\n ');
17154 __out.push('\n </td>\n <td>\n <a class="edit_card_show" href="">');
17155 __out.push(__sanitize(t('Edit')));
17156 __out.push('</a>\n </td>\n <td>\n ');
17157 if (this.cards.length > 1) {
17158 __out.push('\n <a class="delete_card" href="">');
17159 __out.push(__sanitize(t('Delete')));
17160 __out.push('</a>\n ');
17162 __out.push('\n </td>\n </tr>\n <tr id=\'');
17163 __out.push(__sanitize("e" + index));
17164 __out.push('\' style="display:none;"><td colspan="7">\n <form action="" method="">\n <div>\n <strong><label for="expiration_month">');
17165 __out.push(__sanitize(t('Expiry Month')));
17166 __out.push('</label></strong>\n <select id="card_expiration_month" name="expiration_month">\n <option value="">');
17167 __out.push(__sanitize(t('month')));
17168 __out.push('</option>\n <option value="01">');
17169 __out.push(__sanitize(t('01-Jan')));
17170 __out.push('</option>\n <option value="02">');
17171 __out.push(__sanitize(t('02-Feb')));
17172 __out.push('</option>\n <option value="03">');
17173 __out.push(__sanitize(t('03-Mar')));
17174 __out.push('</option>\n <option value="04">');
17175 __out.push(__sanitize(t('04-Apr')));
17176 __out.push('</option>\n <option value="05">');
17177 __out.push(__sanitize(t('05-May')));
17178 __out.push('</option>\n <option value="06">');
17179 __out.push(__sanitize(t('06-Jun')));
17180 __out.push('</option>\n <option value="07">');
17181 __out.push(__sanitize(t('07-Jul')));
17182 __out.push('</option>\n <option value="08">');
17183 __out.push(__sanitize(t('08-Aug')));
17184 __out.push('</option>\n <option value="09">');
17185 __out.push(__sanitize(t('09-Sep')));
17186 __out.push('</option>\n <option value="10">');
17187 __out.push(__sanitize(t('10-Oct')));
17188 __out.push('</option>\n <option value="11">');
17189 __out.push(__sanitize(t('11-Nov')));
17190 __out.push('</option>\n <option value="12">');
17191 __out.push(__sanitize(t('12-Dec')));
17192 __out.push('</option>\n </select>\n </div>\n <div>\n <strong><label for="expiration_year">');
17193 __out.push(__sanitize(t('Expiry Year')));
17194 __out.push('</label></strong>\n <select id="card_expiration_year" name="expiration_year">\n <option selected="selected" value="">');
17195 __out.push(__sanitize(t('year')));
17196 __out.push('</option>\n <option value="2011">');
17197 __out.push(__sanitize(t('2011')));
17198 __out.push('</option>\n <option value="2012">');
17199 __out.push(__sanitize(t('2012')));
17200 __out.push('</option>\n <option value="2013">');
17201 __out.push(__sanitize(t('2013')));
17202 __out.push('</option>\n <option value="2014">');
17203 __out.push(__sanitize(t('2014')));
17204 __out.push('</option>\n <option value="2015">');
17205 __out.push(__sanitize(t('2015')));
17206 __out.push('</option>\n <option value="2016">');
17207 __out.push(__sanitize(t('2016')));
17208 __out.push('</option>\n <option value="2017">');
17209 __out.push(__sanitize(t('2017')));
17210 __out.push('</option>\n <option value="2018">');
17211 __out.push(__sanitize(t('2018')));
17212 __out.push('</option>\n <option value="2019">');
17213 __out.push(__sanitize(t('2019')));
17214 __out.push('</option>\n <option value="2020">');
17215 __out.push(__sanitize(t('2020')));
17216 __out.push('</option>\n <option value="2021">');
17217 __out.push(__sanitize(t('2021')));
17218 __out.push('</option>\n <option value="2022">');
17219 __out.push(__sanitize(t('2022')));
17220 __out.push('</option>\n </select>\n </div>\n <div>\n <strong><label for="card_code">');
17221 __out.push(__sanitize(t('CVV')));
17222 __out.push('</label></strong>\n <input id="card_code" name="card_code" type="text"/>\n </div>\n <button class="button edit_card" data-theme="a"><span>');
17223 __out.push(__sanitize(t('Save')));
17224 return __out.push('</span></button>\n </form>\n </td></tr>\n ');
17226 __out.push('\n\n <div id="card_edit_form">\n <table>\n ');
17227 _.each(this.cards.models, printCard);
17228 __out.push('\n </table>\n </div>\n\n');
17234 __obj.safe = __objSafe, __obj.escape = __escape;
17235 return __out.join('');
17236 }}, "templates/clients/modules/sub_header": function(exports, require, module) {module.exports = function(__obj) {
17237 if (!__obj) __obj = {};
17238 var __out = [], __capture = function(callback) {
17239 var out = __out, result;
17241 callback.call(this);
17242 result = __out.join('');
17244 return __safe(result);
17245 }, __sanitize = function(value) {
17246 if (value && value.ecoSafe) {
17248 } else if (typeof value !== 'undefined' && value != null) {
17249 return __escape(value);
17253 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17254 __safe = __obj.safe = function(value) {
17255 if (value && value.ecoSafe) {
17258 if (!(typeof value !== 'undefined' && value != null)) value = '';
17259 var result = new String(value);
17260 result.ecoSafe = true;
17265 __escape = __obj.escape = function(value) {
17266 return ('' + value)
17267 .replace(/&/g, '&')
17268 .replace(/</g, '<')
17269 .replace(/>/g, '>')
17270 .replace(/"/g, '"');
17275 __out.push('<div id="sub_header">\n <div id="title">');
17276 __out.push(__sanitize(this.heading));
17277 __out.push('</div>\n <div id="greeting">\n ');
17278 if (window.USER.first_name) {
17280 __out.push(__sanitize(t('Hello Greeting', {
17281 name: USER.first_name
17285 __out.push('\n </div>\n</div>\n<div class="clear"></div>\n');
17289 __obj.safe = __objSafe, __obj.escape = __escape;
17290 return __out.join('');
17291 }}, "templates/clients/promotions": function(exports, require, module) {module.exports = function(__obj) {
17292 if (!__obj) __obj = {};
17293 var __out = [], __capture = function(callback) {
17294 var out = __out, result;
17296 callback.call(this);
17297 result = __out.join('');
17299 return __safe(result);
17300 }, __sanitize = function(value) {
17301 if (value && value.ecoSafe) {
17303 } else if (typeof value !== 'undefined' && value != null) {
17304 return __escape(value);
17308 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17309 __safe = __obj.safe = function(value) {
17310 if (value && value.ecoSafe) {
17313 if (!(typeof value !== 'undefined' && value != null)) value = '';
17314 var result = new String(value);
17315 result.ecoSafe = true;
17320 __escape = __obj.escape = function(value) {
17321 return ('' + value)
17322 .replace(/&/g, '&')
17323 .replace(/</g, '<')
17324 .replace(/>/g, '>')
17325 .replace(/"/g, '"');
17330 var promo, _i, _len, _ref;
17331 __out.push(require('templates/clients/modules/sub_header').call(this, {
17332 heading: t("Promotions")
17334 __out.push('\n\n<div id="main_content">\n <div>\n <div id="global_status">\n <span class="success_message"></span>\n <span class="error_message"></span>\n </div>\n <form action="/dashboard/promotions/create" method="post">\n <label for="code">');
17335 __out.push(__sanitize(t('Enter Promotion Code')));
17336 __out.push('</label>\n <input id="code" name="code" type="text" />\n\n <button type="submit" class="button"><span>');
17337 __out.push(__sanitize(t('Submit')));
17338 __out.push('</span></button>\n </form>\n ');
17339 if (this.promos.length > 0) {
17340 __out.push('\n <div class="table_wrapper">\n <h2>');
17341 __out.push(__sanitize(t('Your Available Promotions')));
17342 __out.push('</h2>\n <table>\n <thead>\n\n <tr>\n <td>');
17343 __out.push(__sanitize(t('Code')));
17344 __out.push('</td>\n <td>');
17345 __out.push(__sanitize(t('Details')));
17346 __out.push('</td>\n <td>');
17347 __out.push(__sanitize(t('Starts')));
17348 __out.push('</td>\n <td>');
17349 __out.push(__sanitize(t('Expires')));
17350 __out.push('</td>\n </tr>\n </thead>\n <tbody>\n ');
17351 _ref = this.promos;
17352 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
17354 __out.push('\n <tr>\n <td>');
17355 __out.push(__sanitize(promo.code));
17356 __out.push('</td>\n <td>');
17357 __out.push(__sanitize(promo.description));
17358 __out.push('</td>\n <td>');
17359 __out.push(__sanitize(app.helpers.formatDate(promo.starts_at, true, "America/Los_Angeles")));
17360 __out.push('</td>\n <td>');
17361 __out.push(__sanitize(app.helpers.formatDate(promo.ends_at, true, "America/Los_Angeles")));
17362 __out.push('</td>\n </tr>\n ');
17364 __out.push('\n </tbody>\n </table>\n </div>\n ');
17366 __out.push('\n\n <p>');
17367 __out.push(__sanitize(t('No Active Promotions')));
17368 __out.push('</p>\n ');
17370 __out.push('\n\n </div>\n</div>\n<div id="main_shadow"></div>\n');
17374 __obj.safe = __objSafe, __obj.escape = __escape;
17375 return __out.join('');
17376 }}, "templates/clients/request": function(exports, require, module) {module.exports = function(__obj) {
17377 if (!__obj) __obj = {};
17378 var __out = [], __capture = function(callback) {
17379 var out = __out, result;
17381 callback.call(this);
17382 result = __out.join('');
17384 return __safe(result);
17385 }, __sanitize = function(value) {
17386 if (value && value.ecoSafe) {
17388 } else if (typeof value !== 'undefined' && value != null) {
17389 return __escape(value);
17393 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17394 __safe = __obj.safe = function(value) {
17395 if (value && value.ecoSafe) {
17398 if (!(typeof value !== 'undefined' && value != null)) value = '';
17399 var result = new String(value);
17400 result.ecoSafe = true;
17405 __escape = __obj.escape = function(value) {
17406 return ('' + value)
17407 .replace(/&/g, '&')
17408 .replace(/</g, '<')
17409 .replace(/>/g, '>')
17410 .replace(/"/g, '"');
17415 var showFavoriteLocation;
17416 showFavoriteLocation = function(location, index) {
17419 alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
17420 __out.push('\n <tr id="f');
17421 __out.push(__sanitize(index));
17422 __out.push('" class="location_row">\n <td class="marker_logo">\n <img src="https://www.google.com/mapfiles/marker');
17423 __out.push(__sanitize(alphabet[index]));
17424 __out.push('.png" />\n </td>\n <td class="location_nickname_wrapper">\n <span >');
17425 __out.push(__sanitize(location.nickname));
17426 return __out.push('</span>\n </td>\n </tr>\n');
17428 __out.push('\n\n');
17429 __out.push(require('templates/clients/modules/sub_header').call(this, {
17430 heading: t("Ride Request")
17432 __out.push('\n\n\n<div id="main_content">\n <div>\n <div id="top_bar">\n <form id="search_form" action="" method="post">\n <label for="address">');
17433 __out.push(__sanitize(t('Where do you want us to pick you up?')));
17434 __out.push('</label>\n <input id="address" name="address" type="text" placeholder="');
17435 __out.push(__sanitize(t('Address to search')));
17436 __out.push('"/>\n <button type="submit" id="address" class="button"><span>');
17437 __out.push(__sanitize(t('Search')));
17438 __out.push('</span></button>\n </form>\n </div>\n\n <div id="sidebar">\n <div id="waiting_riding" class="panel">\n <table>\n <tr>\n <td>\n <p class="label">');
17439 __out.push(__sanitize(t('Driver Name:')));
17440 __out.push('</p>\n <p id="rideName"></p>\n </td>\n </tr>\n <tr>\n <td>\n <p class="label">');
17441 __out.push(__sanitize(t('Driver #:')));
17442 __out.push('</p>\n <p id="ridePhone"></p>\n </td>\n </tr>\n <tr id="ride_address_wrapper">\n <td>\n <p class="label">');
17443 __out.push(__sanitize(t('Pickup Address:')));
17444 __out.push('</p>\n <p id="rideAddress"></p>\n </td>\n <td id="favShow">\n <img alt="');
17445 __out.push(__sanitize(t('Add to Favorite Locations')));
17446 __out.push('" id="addToFavButton" src="/web/img/button_plus_gray.png"/>\n </td>\n </tr>\n <tr>\n <td>\n <form id="favLoc_form" action="" method="post">\n <p class="error_message"></p>\n <span class="label">');
17447 __out.push(__sanitize(t('Nickname:')));
17448 __out.push('</span>\n <input type="hidden" value="" id="pickupLat" />\n <input type="hidden" value="" id="pickupLng" />\n <input id="favLocNickname" name="nickname" type="text"/>\n <button type="submit" class="button"><span>');
17449 __out.push(__sanitize(t('Add')));
17450 __out.push('</span></button>\n </form>\n </td>\n </tr>\n </table>\n </div>\n <div id="trip_completed_panel" class="panel">\n <h2>');
17451 __out.push(__sanitize(t('Your last trip')));
17452 __out.push('</h2>\n <form id="rating_form">\n <label>');
17453 __out.push(__sanitize(t('Please rate your driver:')));
17454 __out.push('</label>\n <img alt="');
17455 __out.push(__sanitize(t('Star')));
17456 __out.push('" class="stars" id="1" src="/web/img/star_inactive.png"/>\n <img alt="');
17457 __out.push(__sanitize(t('Star')));
17458 __out.push('" class="stars" id="2" src="/web/img/star_inactive.png"/>\n <img alt="');
17459 __out.push(__sanitize(t('Star')));
17460 __out.push('" class="stars" id="3" src="/web/img/star_inactive.png"/>\n <img alt="');
17461 __out.push(__sanitize(t('Star')));
17462 __out.push('" class="stars" id="4" src="/web/img/star_inactive.png"/>\n <img alt="');
17463 __out.push(__sanitize(t('Star')));
17464 __out.push('" class="stars" id="5" src="/web/img/star_inactive.png"/>\n <label>');
17465 __out.push(__sanitize(t('Comments: (optional)')));
17466 __out.push('</label>\n <textarea id="comments" name="comments" type="text"/>\n <button type="submit" id="rating" class="button"><span>');
17467 __out.push(__sanitize(t('Rate Trip')));
17468 __out.push('</span></button>\n </form>\n <table>\n <tr>\n <td class="label">');
17469 __out.push(__sanitize(t('Pickup time:')));
17470 __out.push('</td>\n <td id="tripTime"></td>\n </tr>\n <tr>\n <td class="label">');
17471 __out.push(__sanitize(t('Miles:')));
17472 __out.push('</td>\n <td id="tripDist"></td>\n </tr>\n <tr>\n <td class="label">');
17473 __out.push(__sanitize(t('Trip time:')));
17474 __out.push('</td>\n <td id="tripDur"></td>\n </tr>\n <tr>\n <td class="label">');
17475 __out.push(__sanitize(t('Fare:')));
17476 __out.push('</td>\n <td id="tripFare"></td>\n </tr>\n </table>\n </div>\n <div id="location_panel_control" class="panel">\n <a id="favorite" style="font-weight:bold;" class="locations_link" >');
17477 __out.push(__sanitize(t('Favorite Locations')));
17478 __out.push('</a> |\n <a href="" id="search" class="locations_link">');
17479 __out.push(__sanitize(t('Search Results')));
17480 __out.push('</a>\n </div>\n <div id="location_panel" class="panel">\n <div id="favorite_results">\n ');
17481 if (USER.locations) {
17482 __out.push('\n <table>\n ');
17483 _.each(USER.locations, showFavoriteLocation);
17484 __out.push('\n </table>\n ');
17486 __out.push('\n <p>');
17487 __out.push(__sanitize(t('You have no favorite locations saved.')));
17488 __out.push('</p>\n ');
17490 __out.push('\n </div>\n <div id="search_results">\n </div>\n </div>\n </div>\n <span id="status_message" >');
17491 __out.push(__sanitize(t('Loading...')));
17492 __out.push('</span>\n <div id="map_wrapper_right"></div>\n <a id="pickupHandle" type="submit" class="button_green"><span>');
17493 __out.push(__sanitize(t('Request Pickup')));
17494 __out.push('</span></a>\n <div class="clear"></div>\n </div>\n</div>\n<div id="main_shadow"></div>\n');
17498 __obj.safe = __objSafe, __obj.escape = __escape;
17499 return __out.join('');
17500 }}, "templates/clients/settings": function(exports, require, module) {module.exports = function(__obj) {
17501 if (!__obj) __obj = {};
17502 var __out = [], __capture = function(callback) {
17503 var out = __out, result;
17505 callback.call(this);
17506 result = __out.join('');
17508 return __safe(result);
17509 }, __sanitize = function(value) {
17510 if (value && value.ecoSafe) {
17512 } else if (typeof value !== 'undefined' && value != null) {
17513 return __escape(value);
17517 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17518 __safe = __obj.safe = function(value) {
17519 if (value && value.ecoSafe) {
17522 if (!(typeof value !== 'undefined' && value != null)) value = '';
17523 var result = new String(value);
17524 result.ecoSafe = true;
17529 __escape = __obj.escape = function(value) {
17530 return ('' + value)
17531 .replace(/&/g, '&')
17532 .replace(/</g, '<')
17533 .replace(/>/g, '>')
17534 .replace(/"/g, '"');
17540 __out.push(require('templates/clients/modules/sub_header').call(this, {
17541 heading: t("settings")
17543 __out.push('\n\n<div id="tabs">\n <ul>\n <li><a href="info_div" class="setting_change">');
17544 __out.push(__sanitize(t('Information')));
17545 __out.push('</a></li>\n <li><a href="pic_div" class="setting_change">');
17546 __out.push(__sanitize(t('Picture')));
17547 __out.push('</a></li>\n </ul>\n</div>\n<div class="clear"></div>\n\n<div id="main_content">\n <div>\n <div id="global_status">\n <span class="error_message"></span>\n <span class="success_message"></span>\n </div>\n <div id="info_div" style="display:none;">\n\n <div id="form_container">\n <div id="standard_form">\n\n <form id="edit_info_form">\n\n <h2>');
17548 __out.push(__sanitize(t('Account Information')));
17549 __out.push('</h2>\n\n <div class="form_label">\n <label for="first_name">');
17550 __out.push(__sanitize(t('First Name')));
17551 __out.push('</label>\n </div>\n\n <div class="form_input">\n <input id="first_name" name="first_name" type="text" value="');
17552 __out.push(__sanitize(USER.first_name));
17553 __out.push('"/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="last_name">');
17554 __out.push(__sanitize(t('Last Name')));
17555 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="last_name" name="last_name" type="text" value="');
17556 __out.push(__sanitize(USER.last_name));
17557 __out.push('"/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="email">');
17558 __out.push(__sanitize(t('Email Address')));
17559 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="email" name="email" type="text" value="');
17560 __out.push(__sanitize(USER.email));
17561 __out.push('"/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="password">');
17562 __out.push(__sanitize(t('Password')));
17563 __out.push('</label>\n </div>\n <div class="form_input">\n <a id="change_password" href="">');
17564 __out.push(__sanitize(t('Change Your Password')));
17565 __out.push('</a>\n <input style="display:none" id="password" name="password" type="password" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="country">');
17566 __out.push(__sanitize(t('Country')));
17567 __out.push('</label>\n </div>\n <div class="form_input">\n ');
17569 selected: USER['country_id']
17572 __out.push(app.helpers.countrySelector("country_id", args));
17573 __out.push('\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n <div class="form_label">\n <label for="location">Zip/Postal Code</label>\n </div>\n <div class="form_input">\n <input id="location" name="location" class="half" type="text" value="');
17574 __out.push(__sanitize(USER.location));
17575 __out.push('"/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="language_id">');
17576 __out.push(__sanitize(t('Language')));
17577 __out.push('</label>\n </div>\n <div class="form_input">\n <select name="language_id" id="language_id">\n <option value="1" ');
17578 __out.push(__sanitize(USER.language_id === 1 ? 'selected="selected"' : ""));
17579 __out.push('>English</option>\n <option value="2" ');
17580 __out.push(__sanitize(USER.language_id === 2 ? 'selected="selected"' : ""));
17581 __out.push('>Francais</option>\n </select>\n <span class="erro_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <h2>');
17582 __out.push(__sanitize(t('Mobile Phone Information')));
17583 __out.push('</h2>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="country">');
17584 __out.push(__sanitize(t('Country')));
17585 __out.push('</label>\n </div>\n <div class="form_input">\n ');
17587 countryCodePrefix: 'mobile_country_code'
17590 args['selected'] = USER['mobile_country_code'];
17592 __out.push(app.helpers.countrySelector("mobile_country_id", args));
17593 __out.push('\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="mobile">');
17594 __out.push(__sanitize(t('Mobile Number')));
17595 __out.push('</label>\n </div>\n <div class="form_input">\n <div id="mobile_country_code" class="phone_country_code">');
17596 __out.push(__sanitize(USER['mobile_country_code']));
17597 __out.push('</div>\n <input id="mobile" name="mobile" class="phone" type="text" value="');
17598 __out.push(__sanitize(USER.mobile));
17599 __out.push('"/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div>\n <button id="submit_info" type="submit" class="button"><span>');
17600 __out.push(__sanitize(t('Submit')));
17601 __out.push('</span></button>\n </div>\n </form>\n </div>\n </div>\n </div>\n\n <div id="pic_div" style="display:none;">\n <form id="profile_pic_form" enctype="multipart/form-data" method="POST" target="">\n <input type="file" name="picture" id="picture">\n <button id="submit_pic" type="submit" class="button"><span>');
17602 __out.push(__sanitize(t('Upload')));
17603 __out.push('</span></button>\n </form>\n <p>');
17604 __out.push(__sanitize(t('Your current Picture')));
17605 __out.push('</p>\n <img id="settingsProfPic" src="');
17606 __out.push(__sanitize("" + USER.picture_url + "?" + (new Date().getTime())));
17607 __out.push('" />\n <div id="test"></div>\n </div>\n\n <div class="clear"></div>\n </div>\n</div>\n\n<div class="clear"></div>\n<div id="main_shadow"></div>\n');
17611 __obj.safe = __objSafe, __obj.escape = __escape;
17612 return __out.join('');
17613 }}, "templates/clients/sign_up": function(exports, require, module) {module.exports = function(__obj) {
17614 if (!__obj) __obj = {};
17615 var __out = [], __capture = function(callback) {
17616 var out = __out, result;
17618 callback.call(this);
17619 result = __out.join('');
17621 return __safe(result);
17622 }, __sanitize = function(value) {
17623 if (value && value.ecoSafe) {
17625 } else if (typeof value !== 'undefined' && value != null) {
17626 return __escape(value);
17630 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17631 __safe = __obj.safe = function(value) {
17632 if (value && value.ecoSafe) {
17635 if (!(typeof value !== 'undefined' && value != null)) value = '';
17636 var result = new String(value);
17637 result.ecoSafe = true;
17642 __escape = __obj.escape = function(value) {
17643 return ('' + value)
17644 .replace(/&/g, '&')
17645 .replace(/</g, '<')
17646 .replace(/>/g, '>')
17647 .replace(/"/g, '"');
17652 __out.push('<div id="form_container">\n <h1>');
17653 __out.push(__sanitize(t('Sign Up')));
17654 __out.push('</h1>\n <div id="standard_form">\n <form action="/" method="">\n\n <h2>');
17655 __out.push(__sanitize(t('Personal Information')));
17656 __out.push('</h2>\n\n <div class="form_label">\n <label for="first_name">');
17657 __out.push(__sanitize(t('First Name')));
17658 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="first_name" name="first_name" type="text" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="last_name">');
17659 __out.push(__sanitize(t('Last Name')));
17660 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="last_name" name="last_name" type="text" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="email">');
17661 __out.push(__sanitize(t('Email Address')));
17662 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="email" name="email" type="text" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="password">');
17663 __out.push(__sanitize(t('Password')));
17664 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="password" name="password" type="password" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="country">');
17665 __out.push(__sanitize(t('Country')));
17666 __out.push('</label>\n </div>\n <div class="form_input">\n ');
17667 __out.push(app.helpers.countrySelector('location_country'));
17668 __out.push('\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n <div class="form_label">\n <label for="location">');
17669 __out.push(__sanitize(t('Zip/Postal Code')));
17670 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="location" name="location" class="half" type="text" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_clear"></div>\n <div class="form_label">\n <label for="language">');
17671 __out.push(__sanitize(t('Language')));
17672 __out.push('</label>\n </div>\n <div class="form_input">\n <select id="language" name="language">\n <option value="en">English (US)</option>\n <option value="fr">Français</option>\n </select>\n </div>\n\n <div class="form_clear"></div>\n\n <h2>');
17673 __out.push(__sanitize(t('Mobile Phone Information')));
17674 __out.push('</h2>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="country">');
17675 __out.push(__sanitize(t('Country')));
17676 __out.push('</label>\n </div>\n <div class="form_input">\n ');
17677 __out.push(app.helpers.countrySelector('mobile_country', {
17678 countryCodePrefix: 'mobile_country_code'
17680 __out.push('\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="mobile">');
17681 __out.push(__sanitize(t('Mobile Number')));
17682 __out.push('</label>\n </div>\n <div class="form_input">\n <div id="mobile_country_code" class="phone_country_code">+1</div>\n <input id="mobile" name="mobile" class="phone" type="text" value=""/>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <h2>');
17683 __out.push(__sanitize(t('Payment Information')));
17684 __out.push('</h2>\n\n <div class="form_clear"></div>\n\n <span><span id="top_of_form" class="error_message"></span></span>\n\n\n <div class="form_label">\n <label for="card_number">');
17685 __out.push(__sanitize(t('Credit Card Number')));
17686 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="card_number" name="card_number" type="text" value=""/>\n <!--img id="card_icon" src="/web/img/cc_mastercard_24.png"-->\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="card_expiration_month">');
17687 __out.push(__sanitize(t('Expiration Date')));
17688 __out.push('</label>\n </div>\n <div class="form_input">\n <select id="card_expiration_month" name="card_expiration_month">\n <option value="01">01</option>\n <option value="02">02</option>\n <option value="03">03</option>\n <option value="04">04</option>\n <option value="05">05</option>\n <option value="06">06</option>\n <option value="07">07</option>\n <option value="08">08</option>\n <option value="09">09</option>\n <option value="10">10</option>\n <option value="11">11</option>\n <option value="12">12</option>\n </select>\n\n <select id="card_expiration_year" name="card_expiration_year">\n <option value="2011">2011</option>\n <option value="2012">2012</option>\n <option value="2013">2013</option>\n <option value="2014">2014</option>\n <option value="2015">2015</option>\n <option value="2016">2016</option>\n <option value="2017">2017</option>\n <option value="2018">2018</option>\n <option value="2019">2019</option>\n <option value="2020">2020</option>\n <option value="2021">2021</option>\n </select>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="card_number">');
17689 __out.push(__sanitize(t('Security Code')));
17690 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="card_code" name="card_code" type="text" value="" class="half" />\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <div class="form_label">\n <label for="use_case">');
17691 __out.push(__sanitize(t('Type of Card')));
17692 __out.push('</label>\n </div>\n <div class="form_input">\n <select id="use_case" name="use_case">\n <option value="personal">');
17693 __out.push(__sanitize(t('Personal')));
17694 __out.push('</option>\n <option value="business">');
17695 __out.push(__sanitize(t('Business')));
17696 __out.push('</option>\n </select>\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <h2>');
17697 __out.push(__sanitize(t('Promotion Code')));
17698 __out.push('</h2>\n\n <div class="form_label">\n <label for="promotion_code">');
17699 __out.push(__sanitize(t('Code')));
17700 __out.push('</label>\n </div>\n <div class="form_input">\n <input id="promotion_code" name="promotion_code" type="text" value="');
17701 __out.push(__sanitize(this.invite));
17702 __out.push('">\n <span class="error_message"></span>\n </div>\n\n <div class="form_clear"></div>\n\n <h2>');
17703 __out.push(__sanitize(t('Legal Information')));
17704 __out.push('</h2>\n\n <p>');
17705 __out.push(t('Sign Up Agreement', {
17706 terms_link: "<a href='https://www.uber.com/terms' target='_blank' style='line-height:11px;'>" + (t('Terms and Conditions')) + "</a>",
17707 privacy_link: "<a href='https://www.uber.com/privacy' target='_blank' style='line-height:11px;'>" + (t('Privacy Policy')) + "</a>"
17709 __out.push('</p>\n\n <p>');
17710 __out.push(t('Message and Data Rates Disclosure', {
17711 help_string: "<strong>" + (t('HELP')) + "</strong>",
17712 stop_string: "<strong>" + (t('STOP')) + "</strong>"
17714 __out.push('</p>\n\n <p style="display:none" id="terms_error" class="error_message">');
17715 __out.push(__sanitize(t('Sign Up Agreement Error')));
17716 __out.push('</p>\n\n <div id="signup_terms">\n <p>\n <input type="checkbox" name="signup_terms_agreement" />\n <label for="signup_terms_agreement"><strong>');
17717 __out.push(t('I Agree'));
17718 __out.push('</strong></label>\n </p>\n </div>\n\n <div class="formSubmitButton"><button type="submit" class="button" data-theme="a" id="sign_up_submit_button"><span>');
17719 __out.push(__sanitize(t('Sign Up')));
17720 __out.push('</span></button></div>\n\n </form>\n </div>\n</div>\n\n<div id="small_container_shadow"></div>\n');
17724 __obj.safe = __objSafe, __obj.escape = __escape;
17725 return __out.join('');
17726 }}, "templates/clients/trip_detail": function(exports, require, module) {module.exports = function(__obj) {
17727 if (!__obj) __obj = {};
17728 var __out = [], __capture = function(callback) {
17729 var out = __out, result;
17731 callback.call(this);
17732 result = __out.join('');
17734 return __safe(result);
17735 }, __sanitize = function(value) {
17736 if (value && value.ecoSafe) {
17738 } else if (typeof value !== 'undefined' && value != null) {
17739 return __escape(value);
17743 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17744 __safe = __obj.safe = function(value) {
17745 if (value && value.ecoSafe) {
17748 if (!(typeof value !== 'undefined' && value != null)) value = '';
17749 var result = new String(value);
17750 result.ecoSafe = true;
17755 __escape = __obj.escape = function(value) {
17756 return ('' + value)
17757 .replace(/&/g, '&')
17758 .replace(/</g, '<')
17759 .replace(/>/g, '>')
17760 .replace(/"/g, '"');
17765 var distance, fareBreakdown, printFares, printStar, _ref, _ref2, _ref3, _ref4, _ref5, _ref6;
17766 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
17767 printStar = function() {
17768 return __out.push('\n <img alt="Star" src="/web/img/star.png"/>\n');
17771 fareBreakdown = this.trip.get('fare_breakdown');
17772 __out.push('\n\n');
17773 printFares = __bind(function(fare, index, list) {
17775 __out.push('\n\n <li>\n <span class="fare">');
17776 __out.push(__sanitize(app.helpers.formatCurrency(fare['amount'], false, (_ref = this.trip.get('fare_breakdown_local')) != null ? _ref.currency : void 0)));
17777 __out.push('</span><br/>\n <span class="subtext">');
17778 __out.push(__sanitize(fare['name']));
17779 __out.push('</span>\n ');
17780 if (fare['variable_rate'] !== 0) {
17781 __out.push('\n <br><span class="subtext">');
17782 __out.push(__sanitize("" + (app.helpers.formatCurrency(fare['variable_rate'], false, this.trip.get('fare_breakdown_local'))) + " x " + (app.helpers.roundNumber(fare['input_amount'], 3)) + " " + fare['input_type']));
17783 __out.push('</span>\n ');
17785 __out.push('\n </li>\n ');
17786 if (index !== list.length - 1) {
17787 __out.push('\n <li class="math">+</li>\n ');
17789 return __out.push('\n');
17791 __out.push('\n\n');
17792 __out.push(require('templates/clients/modules/sub_header').call(this, {
17793 heading: t("Trip Details")
17795 __out.push('\n\n\n<div id="main_content">\n <div class="clear"></div>\n <div>\n <div id="trip_details_map"></div>\n <div id="trip_details_info">\n <h2>\n ');
17796 __out.push(__sanitize(t('Your Trip')));
17797 __out.push('\n </h2>\n\n <div id="avatars">\n <h3>');
17798 __out.push(__sanitize(t('Driver')));
17799 __out.push('</h3>\n <img alt="Driver image" height="45" src="');
17800 __out.push(__sanitize((_ref = this.trip.get('driver')) != null ? _ref.picture_url : void 0));
17801 __out.push('" width="45" />\n <span>');
17802 __out.push(__sanitize((_ref2 = this.trip.get('driver')) != null ? _ref2.first_name : void 0));
17803 __out.push('</span>\n\n <div class="clear"></div>\n </div>\n\n <h3>');
17804 __out.push(__sanitize(t('Rating')));
17805 __out.push('</h3>\n ');
17806 _(this.trip.get('driver_rating')).times(printStar);
17807 __out.push('\n <h3>');
17808 __out.push(__sanitize(t('Trip Info')));
17809 __out.push('</h3>\n <table>\n <tr class="first">\n <td class="label">');
17810 __out.push(__sanitize(t('Pickup time:')));
17811 __out.push('</td>\n <td>');
17812 __out.push(__sanitize(app.helpers.formatDate(this.trip.get('begintrip_at'), true, this.trip.get('city').timezone)));
17813 __out.push('</td>\n </tr>\n <tr>\n <td class="label">');
17814 __out.push(__sanitize(t("" + (app.helpers.capitaliseFirstLetter((_ref3 = this.trip.get('city')) != null ? (_ref4 = _ref3.country) != null ? _ref4.distance_unit : void 0 : void 0)) + "s:")));
17815 __out.push('</td>\n ');
17816 distance = this.trip.get('distance', 0);
17818 if (((_ref5 = this.trip.get('city')) != null ? (_ref6 = _ref5.country) != null ? _ref6.distance_unit : void 0 : void 0) === "kilometer") {
17820 distance = distance * 1.609344;
17823 __out.push('\n <td>');
17824 __out.push(__sanitize(app.helpers.roundNumber(distance, 2)));
17825 __out.push('</td>\n </tr>\n <tr>\n <td class="label">');
17826 __out.push(__sanitize(t('Trip time:')));
17827 __out.push('</td>\n <td>');
17828 __out.push(__sanitize(app.helpers.formatSeconds(this.trip.get('duration'))));
17829 __out.push('</td>\n </tr>\n <tr>\n <td class="label">');
17830 __out.push(__sanitize(t('Fare:')));
17831 __out.push('</td>\n <td>');
17832 __out.push(__sanitize(app.helpers.formatTripFare(this.trip)));
17833 __out.push('</td>\n </tr>\n </table>\n\n <p><button class="resendReceipt"><span>Resend Receipt</span></button> <span class="resendReceiptSuccess success"></span><span class="resendReceiptError error"></span></p>\n\n <p><a id="fare_review" href="">');
17834 __out.push(__sanitize(t('Request a fare review')));
17835 __out.push('</a></p>\n </div>\n <div class="clear"></div>\n\n <div id="fare_review_box">\n\n <span class="success_message" style="display:none;">');
17836 __out.push(__sanitize(t("Fare Review Submitted")));
17837 __out.push('</span>\n <div id="fare_review_form_wrapper">\n <p>');
17838 __out.push(__sanitize(t("Fair Price Consideration")));
17839 __out.push('</p>\n <div id="pricing_breakdown">\n <h3>');
17840 __out.push(__sanitize(t('Your Fare Calculation')));
17841 __out.push('</h3>\n\n <h4>');
17842 __out.push(__sanitize(t('Charges')));
17843 __out.push('</h4>\n <ul>\n ');
17844 _.each(fareBreakdown['charges'], printFares);
17845 __out.push('\n <div class="clear"></div>\n </ul>\n\n <h4>');
17846 __out.push(__sanitize(t('Discounts')));
17847 __out.push('</h4>\n <ul>\n ');
17848 _.each(fareBreakdown['discounts'], printFares);
17849 __out.push('\n <div class="clear"></div>\n </ul>\n\n <h4>');
17850 __out.push(__sanitize(t('Total Charge')));
17851 __out.push('</h4>\n <ul>\n <li class="math">=</li>\n <li class="valign"><span>$');
17852 __out.push(__sanitize(this.trip.get('fare')));
17853 __out.push('</span></li>\n <div class="clear"></div>\n </ul>\n </div>\n <ul>\n <li>');
17854 __out.push(t('Uber Pricing Information Message', {
17855 learn_link: "<a href='" + (app.config.get('url')) + "/learn'>" + (t('Uber pricing information')) + "</a>"
17857 __out.push('</li>\n <li>');
17858 __out.push(__sanitize(t('GPS Point Capture Disclosure')));
17859 __out.push('</li>\n </ul>\n\n <p>');
17860 __out.push(__sanitize(t('Fare Review Note')));
17861 __out.push('</p>\n <span class="error_message" style="display:none;">');
17862 __out.push(__sanitize(t('Fare Review Error')));
17863 __out.push('</span>\n <form id="form_review_form" action="" method="">\n <input type="hidden" id="tripid" name="tripid" value="');
17864 __out.push(__sanitize(this.trip.get('id')));
17865 __out.push('">\n <textarea id="form_review_message" name="message"></textarea>\n <div class="clear"></div>\n <button id="submit_fare_review" type="submit" class="button" data-theme="a"><span>');
17866 __out.push(__sanitize(t('Submit')));
17867 __out.push('</span></button>\n </form>\n <button class="button" id="fare_review_hide" data-theme="a"><span>');
17868 __out.push(__sanitize(t('Cancel')));
17869 __out.push('</span></button>\n </div>\n </div>\n <div class="clear"></div>\n </div>\n</div>\n<div id="main_shadow"></div>\n');
17873 __obj.safe = __objSafe, __obj.escape = __escape;
17874 return __out.join('');
17875 }}, "templates/shared/menu": function(exports, require, module) {module.exports = function(__obj) {
17876 if (!__obj) __obj = {};
17877 var __out = [], __capture = function(callback) {
17878 var out = __out, result;
17880 callback.call(this);
17881 result = __out.join('');
17883 return __safe(result);
17884 }, __sanitize = function(value) {
17885 if (value && value.ecoSafe) {
17887 } else if (typeof value !== 'undefined' && value != null) {
17888 return __escape(value);
17892 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
17893 __safe = __obj.safe = function(value) {
17894 if (value && value.ecoSafe) {
17897 if (!(typeof value !== 'undefined' && value != null)) value = '';
17898 var result = new String(value);
17899 result.ecoSafe = true;
17904 __escape = __obj.escape = function(value) {
17905 return ('' + value)
17906 .replace(/&/g, '&')
17907 .replace(/</g, '<')
17908 .replace(/>/g, '>')
17909 .replace(/"/g, '"');
17914 __out.push('<div id="menu_main">\n <div class="logo">\n <a href="/"><img src="/web/img/logo-charcoal.png"></a>\n </div>\n <div class="nav">\n <ul>\n ');
17915 if (this.type === 'guest') {
17916 __out.push('\n <li><a class="" href="/#!/sign-up" id="">');
17917 __out.push(__sanitize(t("Sign Up")));
17918 __out.push('</a></li>\n <li><a class="" href="https://www.uber.com/learn" id="">');
17919 __out.push(__sanitize(t("Learn More")));
17920 __out.push('</a></li>\n <li><a class="" href="http://blog.uber.com" id="">');
17921 __out.push(__sanitize(t("Blog")));
17922 __out.push('</a></li>\n <li><a class="" href="/#!/sign-in">');
17923 __out.push(__sanitize(t("Sign In")));
17924 __out.push(' »</a></li>\n ');
17927 if (this.type === 'client') {
17929 if ($.cookie('user') && JSON.parse($.cookie('user')).is_admin) {
17930 __out.push('\n <li><a class="" href="/#!/request" id="">');
17931 __out.push(__sanitize(t("Ride Request")));
17932 __out.push('</a></li>\n ');
17934 __out.push('\n <li><a class="" href="/#!/dashboard" id="">');
17935 __out.push(__sanitize(t("Dashboard")));
17936 __out.push('</a></li>\n <li><a class="" href="/#!/invite" id="">');
17937 __out.push(__sanitize(t("Invite Friends")));
17938 __out.push('</a></li>\n <li><a class="" href="/#!/promotions" id="">');
17939 __out.push(__sanitize(t("Promotions")));
17940 __out.push('</a></li>\n <li><a class="" href="/#!/billing" id="">');
17941 __out.push(__sanitize(t("Billing")));
17942 __out.push('</a></li>\n <li><a class="" href="/#!/settings/information" id="">');
17943 __out.push(__sanitize(t("Settings")));
17944 __out.push('</a></li>\n <li><a class="" href="/#!/sign-out">');
17945 __out.push(__sanitize(t("Sign Out")));
17946 __out.push(' »</a></li>\n ');
17948 __out.push('\n </ul>\n </div>\n</div>\n');
17952 __obj.safe = __objSafe, __obj.escape = __escape;
17953 return __out.join('');
17954 }}, "translations/en": function(exports, require, module) {(function() {
17955 exports.translations = {
17957 "Sign Up": "Sign Up",
17958 "Ride Request": "Ride Request",
17959 "Invite Friends": "Invite Friends",
17960 "Promotions": "Promotions",
17961 "Billing": "Billing",
17962 "Settings": "Settings",
17963 "Forgot Password?": "Forgot Password?",
17964 "Password Recovery": "Password Recovery",
17966 "Trip Detail": "Trip Detail",
17967 "Password Reset": "Password Reset",
17968 "Confirm Email": "Confirm Email",
17969 "Request Ride": "Request Ride",
17970 "Credit Card Number": "Credit Card Number",
17972 "01-Jan": "01-Jan",
17973 "02-Feb": "02-Feb",
17974 "03-Mar": "03-Mar",
17975 "04-Apr": "04-Apr",
17976 "05-May": "05-May",
17977 "06-Jun": "06-Jun",
17978 "07-Jul": "07-Jul",
17979 "08-Aug": "08-Aug",
17980 "09-Sep": "09-Sep",
17981 "10-Oct": "10-Oct",
17982 "11-Nov": "11-Nov",
17983 "12-Dec": "12-Dec",
17986 "Category": "Category",
17987 "personal": "personal",
17988 "business": "business",
17989 "Default Credit Card": "Default Credit Card",
17990 "Add Credit Card": "Add Credit Card",
17991 "Expiry": "Expiry",
17992 "default card": "default card",
17993 "make default": "make default",
17995 "Delete": "Delete",
17996 "Expiry Month": "Expiry Month",
17997 "Expiry Year": "Expiry Year",
17998 "Unable to Verify Card": "Unable to verify card at this time. Please try again later.",
17999 "Credit Card Update Succeeded": "Your card has been successfully updated!",
18000 "Credit Card Update Failed": "We couldn't save your changes. Please try again in a few minutes.",
18001 "Credit Card Delete Succeeded": "Your card has been deleted!",
18002 "Credit Card Delete Failed": "We were unable to delete your card. Please try again later.",
18003 "Credit Card Update Category Succeeded": "Successfully changed card category!",
18004 "Credit Card Update Category Failed": "We couldn't change your card category. Please try again in a few minutes.",
18005 "Credit Card Update Default Succeeded": "Successfully changed default card!",
18006 "Credit Card Update Default Failed": "We couldn't change your default card. Please try again in a few minutes.",
18007 "Hello Greeting": "Hello, <%= name %>",
18008 "Card Ending in": "Card Ending in",
18009 "Trip Map": "Trip Map",
18010 "Amount": "Amount: <%= amount %>",
18011 "Last Attempt to Bill": "Last Attempt to Bill: <%= date %>",
18012 "Charge": "Charge",
18013 "Uber Credit Balance Note": "Your account has an UberCredit balance of <%= amount %>. When billing for trips, we'll deplete your UberCredit balance before applying charges to your credit card.",
18014 "Please Add Credit Card": "Please add a credit card to bill your outstanding charges.",
18015 "Credit Cards": "Credit Cards",
18016 "add a new credit card": "add a new credit card",
18017 "Account Balance": "Account Balance",
18018 "Arrears": "Arrears",
18019 "Billing Succeeded": "Your card was successfully billed.",
18020 "Confirm Email Succeeded": "Successfully confirmed email token, redirecting to log in page...",
18021 "Confirm Email Failed": "Unable to confirm email. Please contact support@uber.com if this problem persists.",
18022 "Email Already Confirmed": "Your email address has already been confirmed, redirecting to log in page...",
18023 "Credit Card Added": "Credit Card Added",
18024 "No Credit Card": "No Credit Card",
18025 "Mobile Number Confirmed": "Mobile Number Confirmed",
18026 "No Confirmed Mobile": "No Confirmed Mobile",
18027 "E-mail Address Confirmed": "E-mail Address Confirmed",
18028 "No Confirmed E-mail": "No Confirmed E-mail",
18029 'Reply to sign up text': 'Reply "GO" to the text message you received at sign up.',
18030 "Resend text message": "Resend text message",
18031 "Click sign up link": "Click the link in the email you received at sign up.",
18032 "Resend email": "Resend email",
18033 "Add a credit card to ride": "Add a credit card and you'll be ready to ride Uber.",
18034 "Your Most Recent Trip": "Your Most Recent Trip",
18035 "details": "details",
18036 "Your Trip History ": "Your Trip History ",
18037 "Status": "Status",
18038 "Here's how it works:": "Here's how it works:",
18039 "Show all trips": "Show all trips",
18040 "Set your location:": "Set your location:",
18041 "App search for address": "iPhone/Android app: fix the pin or search for an address",
18042 "SMS text address": "SMS: text your address to UBRCAB (827222)",
18043 "Confirm pickup request": "Confirm your pickup request",
18044 "Uber sends ETA": "Uber will send you an ETA (usually within 5-10 minutes)",
18045 "Car arrives": "When your car is arriving, Uber will inform you again.",
18046 "Ride to destination": "Hop in the car and tell the driver your destination.",
18047 "Thank your driver": "That’s it! Please thank your driver but remember that your tip is included and no cash is necessary.",
18048 "Trip started here": "Trip started here",
18049 "Trip ended here": "Trip ended here",
18050 "Sending Email": "Sending email...",
18051 "Resend Email Succeeded": "We just sent the email. Please click on the confirmation link you recieve.",
18052 "Resend Email Failed": "There was an error sending the email. Please contact support if the problem persists.",
18053 "Resend Text Succeeded": 'We just sent the text message. Please reply "GO" to the message you recieve. It may take a few minutes for the message to reach you phone.',
18054 "Resend Text Failed": "There was an error sending the text message. Please contact support if the problem persists.",
18055 "Password Reset Error": "There was an error processing your password reset request.",
18056 "New Password": "New Password",
18057 "Forgot Password": "Forgot Password",
18058 "Forgot Password Error": "Your email address could not be found. Please make sure to use the same email address you used when you signed up.",
18059 "Forgot Password Success": "Please check your email for a link to reset your password.",
18060 "Forgot Password Enter Email": 'Enter your email address and Uber will send you a link to reset your password. If you remember your password, you can <a href="/#!/sign-in">sign in here</a>.',
18061 "Invite friends": "Invite friends",
18062 "Give $ Get $": "Give $10, Get $10",
18063 "Give $ Get $ Description": "Every friend you invite to Uber gets $10 of Uber credit. After someone you’ve invited takes his/her first ride, you get $10 of Uber credits too!",
18064 "What are you waiting for?": "So, what are you waiting for? Invite away!",
18066 "Invite Link": "Email or IM this link to your friends:",
18067 "Email Address": "Email Address",
18068 "Reset Password": "Reset Password",
18069 "Enter Promotion Code": "If you have a promotion code, enter it here:",
18070 "Your Active Promotions": "Your Active Promotions",
18072 "Details": "Details",
18073 "Trips Remaining": "Trips Remaining",
18074 "Expires": "Expires",
18075 "No Active Promotions": "There are no active promotions on your account.",
18076 "Your Available Promotions": "Your Available Promotions",
18077 "Where do you want us to pick you up?": "Where do you want us to pick you up?",
18078 "Address to search": "Address to search",
18079 "Search": "Search",
18080 "Driver Name:": "Driver Name:",
18081 "Driver #:": "Driver #:",
18082 "Pickup Address:": "Pickup Address:",
18083 "Add to Favorite Locations": "Add to Favorite Locations",
18085 "Nickname:": "Nickname:",
18087 "Your last trip": "Your last trip",
18088 "Please rate your driver:": "Please rate your driver:",
18089 "Comments: (optional)": "Comments: (optional)",
18090 "Rate Trip": "Rate Trip",
18091 "Pickup time:": "Pickup time:",
18092 "Miles:": "Miles:",
18093 "Trip time:": "Trip time:",
18095 "Favorite Locations": "Favorite Locations",
18096 "Search Results": "Search Results",
18097 "You have no favorite locations saved.": "You have no favorite locations saved.",
18098 "Loading...": "Loading...",
18099 "Request Pickup": "Request Pickup",
18100 "Cancel Pickup": "Cancel Pickup",
18101 "Requesting Closest Driver": "Requesting the closest driver to pick you up...",
18102 "En Route": "You are currently en route...",
18103 "Rate Last Trip": "Please rate your trip to make another request",
18104 "Rate Before Submitting": "Please rate your trip before submitting the form",
18105 "Address too short": "Address too short",
18106 "or did you mean": "or did you mean",
18107 "Search Address Failed": "Unable to find the given address. Please enter another address close to your location.",
18108 "Sending pickup request...": "Sending pickup request...",
18109 "Cancel Request Prompt": "Are you sure you want to cancel your request?",
18110 "Cancel Request Arrived Prompt": 'Are you sure you want to cancel your request? Your driver has arrived so there is a $10 cancellation fee. It may help to call your driver now',
18111 "Favorite Location Nickname Length Error": "Nickname has to be atleast 3 characters",
18112 "Favorite Location Save Succeeded": "Location Saved!",
18113 "Favorite Location Save Failed": "Unable to save your location. Please try again later.",
18114 "Favorite Location Title": "Favorite Location <%= id %>",
18115 "Search Location Title": "Search Location <%= id %>",
18116 "ETA Message": "ETA: Around <%= minutes %> Minutes",
18117 "Nearest Cab Message": "The closest driver is approximately <%= minutes %> minute(s) away",
18118 "Arrival ETA Message": "Your Uber will arrive in about <%= minutes %> minute(s)",
18119 "Arriving Now Message": "Your Uber is arriving now...",
18120 "Rating Driver Failed": "Unable to contact server. Please try again later or email support if this issue persists.",
18121 "Account Information": "Account Information",
18122 "Mobile Phone Information": "Mobile Phone Information",
18123 "settings": "settings",
18124 "Information": "Information",
18125 "Picture": "Picture",
18126 "Change password": "Change password",
18127 "Your current Picture": "Your current Picture",
18128 "Your Favorite Locations": "Your Favorite Locations",
18129 "You have no favorite locations saved.": "You have no favorite locations saved.",
18130 "Purpose of Mobile": "We send text messages to your mobile phone to tell you when your driver is arriving. You can also request trips using text messages.",
18131 "Country": "Country",
18132 "Mobile Number": "Mobile Number",
18133 "Submit": "Submit",
18134 "Favorite Location": "Favorite Location",
18135 "No Approximate Address": "Could not find an approximate address",
18136 "Address:": "Address:",
18137 "Information Update Succeeded": "Your information has been updated!",
18138 "Information Update Failed": "We couldn't update your information. Please try again in few minutes or contact support if the problem persists.",
18139 "Location Delete Succeeded": "Location deleted!",
18140 "Location Delete Failed": "We were unable to delete your favorite location. Please try again later or contact support of the issue persists.",
18141 "Location Edit Succeeded": "Changes Saved!",
18142 "Location Edit Failed": "We couldn't save your changes. Please try again in a few minutes.",
18143 "Picture Update Succeeded": "Your picture has been updated!",
18144 "Picture Update Failed": "We couldn't change your picture. Please try again in a few minutes.",
18145 "Personal Information": "Personal Information",
18146 "Mobile Phone Number": "Mobile Phone Number",
18147 "Payment Information": "Payment Information",
18148 "Purpose of Credit Card": "We keep your credit card on file so that your trip go as fast as possible. You will not be charged until you take a trip.",
18149 "Your card will not be charged until you take a trip.": "Your card will not be charged until you take a trip.",
18150 "Credit Card Number": "Credit Card Number",
18151 "Expiration Date": "Expiration Date",
18152 "Promotion Code": "Promotion Code",
18153 "Enter Promo Here": "If you have a code for a promotion, invitation or group deal, you can enter it here.",
18154 "Promotion Code Input Label": "Promotion, Invite or Groupon Code (optional)",
18155 "Terms and Conditions": "Terms and Conditions",
18158 "Legal Information": "Legal Information",
18159 "Sign Up Agreement": "By signing up, I agree to the Uber <%= terms_link %> and <%= privacy_link %> and understand that Uber is a request tool, not a transportation carrier.",
18160 "Sign Up Agreement Error": "You must agree to the Uber Terms and Conditions and Privacy Policy to continue.",
18161 "Message and Data Rates Disclosure": "Message and Data Rates May Apply. Reply <%= help_string %> to 827-222 for help. Reply <%= stop_string %> to 827-222 to stop texts. For additional assistance, visit support.uber.com or call (866) 576-1039. Supported Carriers: AT&T, Sprint, Verizon, and T-Mobile.",
18162 "I Agree": "I agree to the Terms & Conditions and Privacy Policy",
18163 "Security Code": "Security Code",
18164 "Type of Card": "Type of Card",
18165 "Personal": "Personal",
18166 "Business": "Business",
18168 "Zip or Postal Code": "Zip or Postal Code",
18169 "Your Trip": "Your Trip",
18170 "Trip Info": "Trip Info",
18171 "Request a fare review": "Request a fare review",
18172 "Fare Review Submitted": "Your fare review has been submitted. We'll get back to you soon about your request. Sorry for any inconvenience this may have caused!",
18173 "Fair Price Consideration": "We're committed to delivering Uber service at a fair price. Before requesting a fare review, please consider:",
18174 "Your Fare Calculation": "Your Fare Calculation",
18175 "Charges": "Charges",
18176 "Discounts": "Discounts",
18177 "Total Charge": "Total Charge",
18178 "Uber pricing information": "Uber pricing information",
18179 "Uber Pricing Information Message": "<%= learn_link %> is published on our website.",
18180 "GPS Point Capture Disclosure": "Due to a finite number of GPS point captures, corners on your trip map may appear cut off or rounded. These minor inaccuracies result in a shorter measured distance, which always results in a cheaper trip.",
18181 "Fare Review Note": "Please elaborate on why this trip requires a fare review. Your comments below will help us better establish the correct price for your trip:",
18182 "Fare Review Error": "There was an error submitting the review. Please ensure that you have a message.",
18183 "Sign In": "Sign In"
18186 }, "translations/fr": function(exports, require, module) {(function() {
18187 exports.translations = {
18189 "Sign Up": "Inscription",
18190 "Ride Request": "Passer une Commande",
18191 "Invite Friends": "Inviter vos Amis",
18192 "Promotions": "Promotions",
18193 "Billing": "Paiement",
18194 "Settings": "Paramètres",
18195 "Forgot Password?": "Mot de passe oublié ?",
18196 "Password Recovery": "Récupération du mot de passe",
18197 "Login": "Connexion",
18198 "Trip Detail": "Détail de la Course",
18199 "Password Reset": "Réinitialisation du mot de passe",
18200 "Confirm Email": "Confirmation de l’e-mail",
18201 "Request Ride": "Passer une Commande",
18202 "Credit Card Number": "Numéro de Carte de Crédit",
18204 "01-Jan": "01-Jan",
18205 "02-Feb": "02-Fév",
18206 "03-Mar": "03-Mar",
18207 "04-Apr": "04-Avr",
18208 "05-May": "05-Mai",
18209 "06-Jun": "06-Juin",
18210 "07-Jul": "07-Jui",
18211 "08-Aug": "08-Aoû",
18212 "09-Sep": "09-Sep",
18213 "10-Oct": "10-Oct",
18214 "11-Nov": "11-Nov",
18215 "12-Dec": "12-Déc",
18217 "CVV": "Code de Sécurité",
18218 "Category": "Type",
18219 "personal": "personnel",
18220 "business": "entreprise",
18221 "Default Credit Card": "Carte par Défaut",
18222 "Add Credit Card": "Ajouter une Carte",
18223 "Expiry": "Expire",
18224 "default card": "carte par défaut",
18225 "make default": "choisir par défaut",
18226 "Edit": "Modifier",
18227 "Delete": "Supprimer",
18228 "Expiry Month": "Mois d’Expiration",
18229 "Expiry Year": "Année d’Expiration",
18230 "Unable to Verify Card": "Impossible de vérifier la carte pour le moment. Merci de réessayer un peu plus tard.",
18231 "Credit Card Update Succeeded": "Votre carte a été mise à jour avec succès !",
18232 "Credit Card Update Failed": "Nous ne pouvons enregistrer vos changements. Merci de réessayer dans quelques minutes.",
18233 "Credit Card Delete Succeeded": "Votre carte a été supprimée !",
18234 "Credit Card Delete Failed": "Nous n’avons pas été en mesure de supprimer votre carte. Merci de réessayer plus tard.",
18235 "Credit Card Update Category Succeeded": "Changement de catégorie de carte réussi !",
18236 "Credit Card Update Category Failed": "Nous ne pouvons pas changer la catégorie de votre carte. Merci de réessayer dans quelques minutes.",
18237 "Credit Card Update Default Succeeded": "Carte par défaut changée avec succès !",
18238 "Credit Card Update Default Failed": "Nous ne pouvons pas changer votre carte par défaut. Merci de réessayer dans quelques minutes.",
18239 "Hello Greeting": "Bonjour, <%= name %>",
18240 "Card Ending in": "La carte expire dans",
18241 "Trip Map": "Carte des Courses",
18242 "Amount": "Montant: <%= amount %>",
18243 "Last Attempt to Bill": "Dernière tentative de prélèvement : <%= date %>",
18245 "Uber Credit Balance Note": "Votre compte a un solde de <%= amount %> UberCredits. Lorsque nous facturons des courses, nous réduirons votre solde d’UberCredits avant de prélever votre carte de crédit.",
18246 "Please Add Credit Card": "Merci d’ajouter une carte de crédit pour que nous puissions vous facturer.",
18247 "Credit Cards": "Cartes de crédit",
18248 "add a new credit card": "Ajouter une nouvelle carte de crédit",
18249 "Account Balance": "Solde du compte",
18250 "Arrears": "Arriérés",
18251 "Billing Succeeded": "Votre carte a été correctement débitée.",
18252 "Confirm Email Succeeded": "L’adresse e-mail a bien été validée, vous êtes redirigé vers le tableau de bord...",
18253 "Confirm Email Failed": "Impossible de confirmer l’adresse e-mail. Merci de contacter support@uber.com si le problème persiste.",
18254 "Credit Card Added": "Carte de crédit ajoutée",
18255 "No Credit Card": "Pas de carte de crédit",
18256 "Mobile Number Confirmed": "Numéro de téléphone confirmé",
18257 "No Confirmed Mobile": "Pas de numéro de téléphone confirmé",
18258 "E-mail Address Confirmed": "Adresse e-mail confirmée",
18259 "No Confirmed E-mail": "Pas d’adresse e-mail confirmée",
18260 'Reply to sign up text': 'Répondre "GO" au SMS que vous avez reçu à l’inscription.',
18261 "Resend text message": "Renvoyer le SMS",
18262 "Click sign up link": "Cliquez sur le lien contenu dans l’e-mail reçu à l’inscription.",
18263 "Resend email": "Renvoyer l’e-mail",
18264 "Add a credit card to ride": "Ajouter une carte de crédit et vous serez prêt à voyager avec Uber.",
18265 "Your Most Recent Trip": "Votre course la plus récente",
18266 "details": "détails",
18267 "Your Trip History": "Historique de votre trajet",
18268 "Status": "Statut",
18269 "Here's how it works:": "Voici comment ça marche :",
18270 "Show all trips": "Montrer toutes les courses",
18271 "Set your location:": "Définir votre position :",
18272 "App search for address": "Application iPhone/Android : positionner la punaise ou rechercher une adresse",
18273 "SMS text address": "SMS : envoyez votre adresse à UBRCAB (827222)",
18274 "Confirm pickup request": "Validez la commande",
18275 "Uber sends ETA": "Uber envoie un temps d’attente estimé (habituellement entre 5 et 10 minutes)",
18276 "Car arrives": "Lorsque votre voiture arrive, Uber vous en informera encore..",
18277 "Ride to destination": "Montez dans la voiture et donnez votre destination au chauffeur.",
18278 "Thank your driver": "C’est tout ! Remerciez le chauffeur mais souvenez-vous que les pourboires sont compris et qu’il n’est pas nécessaire d’avoir du liquide sur soi.",
18279 "Trip started here": "La course a commencé ici.",
18280 "Trip ended here": "La course s’est terminée ici.",
18281 "Sending Email": "Envoi de l’e-mail...",
18282 "Resend Email Succeeded": "Nous venons d’envoyer l’e-mail. Merci de cliquer sur le lien de confirmation que vous avez reçu.",
18283 "Resend Email Failed": "Il y a eu un problème lors de l’envoi de l’email. Merci de contacter le support si le problème persiste.",
18284 "Resend Text Succeeded": 'Nous venons d’envoyer le SMS. Merci de répondre "GO" au message que vous avez reçu. Il se peut que cela prenne quelques minutes pour que le message arrive sur votre téléphone.',
18285 "Resend Text Failed": "Il y a eu un problème lors de l’envoi du SMS. Merci de contacter le support si le problème persiste.",
18286 "Password Reset Error": "Il y a eu une error lors de la réinitialisation de votre mot de passe.",
18287 "New Password:": "Nouveau mot de passe:",
18288 "Forgot Password Error": "Votre nom d’utilisateur / adresse email ne peut être trouvé. Merci d’utiliser la même qu’à l’inscription.",
18289 "Forgot Password Success": "Merci de consulter votre boîte mail pour suivre la demande de ‘réinitialisation de mot de passe.",
18290 "Forgot Password Enter Email": "Merci de saisir votre adresse email et nous vous enverrons un lien vous permettant de réinitialiser votre mot de passe :",
18291 "Invite friends": "Inviter vos amis",
18292 "Give $ Get $": "Donnez $10, Recevez $10",
18293 "Give $ Get $ Description": "Chaque ami que vous invitez à Uber recevra $10 de crédits Uber. Dès lors qu’une personne que vous aurez invité aura utilisé Uber pour la première, vous recevrez $10 de crédits Uber également !",
18294 "What are you waiting for?": "N’attendez plus ! Lancez les invitations !",
18295 "Tweet": "Tweeter",
18296 "Invite Link": "Envoyez ce lien par email ou messagerie instantanée à vos amis :",
18297 "Enter Promotion Code": "Si vous avez un code promo, saisissez-le ici:",
18298 "Your Active Promotions": "Vos Codes Promos Actifs",
18300 "Details": "Détails",
18301 "Trips Remaining": "Courses restantes",
18302 "Expires": "Expire",
18303 "No Active Promotions": "Vous n’avez pas de code promo actif.",
18304 "Your Available Promotions": "Votres Promos Disponibles",
18305 "Where do you want us to pick you up?": "Où souhaitez-vous que nous vous prenions en charge ?",
18306 "Address to search": "Adresse à rechercher",
18307 "Search": "Chercher",
18308 "Driver Name:": "Nom du chauffeur:",
18309 "Driver #:": "# Chauffeur:",
18310 "Pickup Address:": "Lieu de prise en charge:",
18311 "Add to Favorite Locations": "Ajoutez aux Lieux Favoris",
18313 "Nickname:": "Pseudo",
18315 "Your last trip": "Votre dernière course",
18316 "Please rate your driver:": "Merci de noter votre chauffeur :",
18317 "Comments: (optional)": "Commentaires: (optionnel)",
18318 "Rate Trip": "Notez votre course",
18319 "Pickup time:": "Heure de Prise en Charge :",
18320 "Miles:": "Kilomètres :",
18321 "Trip time:": "Temps de course :",
18322 "Fare:": "Tarif :",
18323 "Favorite Locations": "Lieux Favoris",
18324 "Search Results": "Résultats",
18325 "You have no favorite locations saved.": "Vous n’avez pas de lieux de prise en charge favoris.",
18326 "Loading...": "Chargement...",
18327 "Request Pickup": "Commander ici",
18328 "Cancel Pickup": "Annuler",
18329 "Requesting Closest Driver": "Nous demandons au chauffeur le plus proche de vous prendre en charge...",
18330 "En Route": "Vous êtes actuellement en route...",
18331 "Rate Last Trip": "Merci de noter votre précédent trajet pour faire une autre course.",
18332 "Rate Before Submitting": "Merci de noter votre trajet avant de le valider.",
18333 "Address too short": "L’adresse est trop courte",
18334 "or did you mean": "ou vouliez-vous dire",
18335 "Search Address Failed": "Impossible de trouver l’adresse spécifiée. Merci de saisir une autre adresse proche de l’endroit où vous vous trouvez.",
18336 "Sending pickup request...": "Envoi de la demande de prise en charge...",
18337 "Cancel Request Prompt": "Voulez-vous vraiment annuler votre demande ?",
18338 "Cancel Request Arrived Prompt": 'Voulez-vous vraiment annuler votre demande ? Votre chauffeur est arrivé, vous serez donc facturé de $10 de frais d’annulation. Il pourrait être utile que vous appeliez votre chauffeur maintenant.',
18339 "Favorite Location Nickname Length Error": "Le pseudo doit faire au moins 3 caractères de long",
18340 "Favorite Location Save Succeeded": "Adresse enregistrée !",
18341 "Favorite Location Save Failed": "Impossible d’enregistrer votre adresse. Merci de réessayer ultérieurement.",
18342 "Favorite Location Title": "Adresse favorie <%= id %>",
18343 "Search Location Title": "Recherche d’adresse <%= id %>",
18344 "ETA Message": "Temps d’attente estimé: environ <%= minutes %> minutes",
18345 "Nearest Cab Message": "Le chauffeur le plus proche sera là dans <%= minutes %> minute(s)",
18346 "Arrival ETA Message": "Votre chauffeur arrivera dans <%= minutes %> minute(s)",
18347 "Arriving Now Message": "Votre chauffeur est en approche...",
18348 "Rating Driver Failed": "Impossible de contacter le serveur. Merci de réessayer ultérieurement ou de contacter le support si le problème persiste.",
18349 "settings": "Paramètres",
18350 "Information": "Information",
18351 "Picture": "Photo",
18352 "Change password": "Modifier votre mot de passe",
18353 "Your current Picture": "Votre photo",
18354 "Your Favorite Locations": "Vos lieux favoris",
18355 "You have no favorite locations saved.": "Vous n’avez pas de lieu favori",
18356 "Account Information": "Informations Personnelles",
18357 "Mobile Phone Information": "Informations de Mobile",
18358 "Change Your Password": "Changez votre mot de passe.",
18360 "Language": "Langue",
18361 "Favorite Location": "Lieu favori",
18362 "No Approximate Address": "Impossible de trouver une adresse même approximative",
18363 "Address:": "Adresse :",
18364 "Information Update Succeeded": "Vos informations ont été mises à jour !",
18365 "Information Update Failed": "Nous n’avons pas pu mettre à jour vos informations. Merci de réessayer dans quelques instants ou de contacter le support si le problème persiste.",
18366 "Location Delete Succeeded": "Adresse supprimée !",
18367 "Location Delete Failed": "Nous n’avons pas pu supprimée votre adresse favorie. Merci de réessayer plus tard ou de contacter le support si le problème persiste.",
18368 "Location Edit Succeeded": "Modifications sauvegardées !",
18369 "Location Edit Failed": "Nous n’avons pas pu sauvegarder vos modifications. Merci de réessayer dans quelques minutes.",
18370 "Picture Update Succeeded": "Votre photo a été mise à jour !",
18371 "Picture Update Failed": "Nous n’avons pas pu mettre à jour votre photo. Merci de réessayer dans quelques instants.",
18372 "Personal Information": "Informations Personnelles",
18373 "Mobile Phone Number": "Numéro de Téléphone Portable",
18374 "Payment Information": "Informations de Facturation",
18375 "Your card will not be charged until you take a trip.": "Votre carte ne sera pas débitée avant votre premier trajet.",
18376 "Card Number": "Numéro de Carte",
18377 "Promotion Code Input Label": "Code promo, code d’invitation ou “deal” acheté en ligne (optionnel)",
18378 "Terms and Conditions": "Conditions Générales",
18381 "Sign Up Agreement": "En souscrivant, j’accepte les <%= terms_link %> et <%= privacy_link %> et comprends qu’Uber est un outil de commande de chauffeur, et non un transporteur.",
18382 "Sign Up Agreement Error": "Vous devez accepter les Conditions Générales d’utilisation d’Uber Terms and Conditions et la Politique de Confidentialité pour continuer.",
18383 "Message and Data Rates Disclosure": "Les frais d’envoi de SMS et de consommation de données peuvent s’appliquer. Répondez <%= help_string %> au 827-222 pour obtenir de l’aide. Répondez <%= stop_string %> au 827-222 pour ne plus recevoir de SMS. Pour plus d’aide, visitez support.uber.com ou appelez le (866) 576-1039. Opérateurs supportés: AT&T, Sprint, Verizon, T-Mobile, Orange, SFR et Bouygues Telecom.",
18384 "Zip/Postal Code": "Code Postal",
18385 "Expiration Date": "Date D'expiration",
18386 "Security Code": "Code de Sécurité",
18387 "Type of Card": "Type",
18388 "Personal": "Personnel",
18389 "Business": "Entreprise",
18390 "Promotion Code": "Code Promo",
18391 "Legal Information": "Mentions Légales",
18392 "I Agree": "J'accepte.",
18393 "Your Trip": "Votre Course",
18394 "Trip Info": "Informations de la Course",
18395 "Request a fare review": "Demander un contrôle du tarif",
18396 "Fare Review Submitted": "Votre demande de contrôle du tarif a été soumis. Nous reviendrons vers vous rapidement concernant cette demande. Nous nous excusons pour les dérangements éventuellement occasionnés !",
18397 "Fair Price Consideration": "Nous nous engageons à proposer Uber à un tarif juste. Avant de demander un contrôle du tarif, merci de prendre en compte :",
18398 "Your Fare Calculation": "Calcul du Prix",
18399 "Charges": "Coûts",
18400 "Discounts": "Réductions",
18401 "Total Charge": "Coût total",
18402 "Uber pricing information": "Information sur les prix d’Uber",
18403 "Uber Pricing Information Message": "<%= learn_link %> est disponible sur notre site web.",
18404 "GPS Point Capture Disclosure": "A cause d’un nombre limité de coordonnées GPS sauvegardées, les angles de votre trajet sur la carte peuvent apparaître coupés ou arrondis. Ces légères incohérences débouchent sur des distances mesurées plus courtes, ce qui implique toujours un prix du trajet moins élevé.",
18405 "Fare Review Note": "Merci de nous expliquer pourquoi le tarif de cette course nécessite d’être contrôlé. Vos commentaires ci-dessous nous aideront à établir un prix plus juste si nécessaire :",
18406 "Fare Review Error": "Il y a eu une erreur lors de l’envoi de la demande. Assurez-vous d’avoir bien ajouté une description à votre demande."
18409 }, "views/clients/billing": function(exports, require, module) {(function() {
18410 var clientsBillingTemplate;
18411 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18412 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18413 function ctor() { this.constructor = child; }
18414 ctor.prototype = parent.prototype;
18415 child.prototype = new ctor;
18416 child.__super__ = parent.prototype;
18418 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
18419 clientsBillingTemplate = require('templates/clients/billing');
18420 exports.ClientsBillingView = (function() {
18421 __extends(ClientsBillingView, UberView);
18422 function ClientsBillingView() {
18423 ClientsBillingView.__super__.constructor.apply(this, arguments);
18425 ClientsBillingView.prototype.id = 'billing_view';
18426 ClientsBillingView.prototype.className = 'view_container';
18427 ClientsBillingView.prototype.events = {
18428 'click a#add_card': 'addCard',
18429 'click .charge_arrear': 'chargeArrear'
18431 ClientsBillingView.prototype.render = function() {
18432 this.RefreshUserInfo(__bind(function() {
18433 var cards, newForm;
18434 this.HideSpinner();
18435 $(this.el).html(clientsBillingTemplate());
18436 if (USER.payment_gateway.payment_profiles.length === 0) {
18437 newForm = new app.views.clients.modules.creditcard;
18438 $(this.el).find("#add_card_wrapper").html(newForm.render(0).el);
18440 cards = new app.views.clients.modules.creditcard;
18441 $("#cards").html(cards.render("all").el);
18443 return this.delegateEvents();
18447 ClientsBillingView.prototype.addCard = function(e) {
18449 e.preventDefault();
18450 newCard = new app.views.clients.modules.creditcard;
18451 $('#cards').append(newCard.render("new").el);
18452 return $("a#add_card").hide();
18454 ClientsBillingView.prototype.chargeArrear = function(e) {
18455 var $el, arrearId, attrs, cardId, options, tryCharge;
18456 e.preventDefault();
18457 $(".error_message").text("");
18458 $el = $(e.currentTarget);
18459 arrearId = $el.attr('id');
18460 cardId = $el.parent().find('#card_to_charge').val();
18461 this.ShowSpinner('submit');
18462 tryCharge = new app.models.clientbills({
18466 payment_profile_id: cardId,
18470 success: __bind(function(data, textStatus, jqXHR) {
18471 $el.parent().find(".success_message").text(t("Billing Succeeded"));
18473 return $el.parent().find('#card_to_charge').hide();
18475 error: __bind(function(jqXHR, status, errorThrown) {
18476 return $el.parent().find(".error_message").text(JSON.parse(status.responseText).error);
18478 complete: __bind(function() {
18479 return this.HideSpinner();
18482 return tryCharge.save(attrs, options);
18484 return ClientsBillingView;
18487 }, "views/clients/confirm_email": function(exports, require, module) {(function() {
18488 var clientsConfirmEmailTemplate;
18489 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18490 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18491 function ctor() { this.constructor = child; }
18492 ctor.prototype = parent.prototype;
18493 child.prototype = new ctor;
18494 child.__super__ = parent.prototype;
18496 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
18497 clientsConfirmEmailTemplate = require('templates/clients/confirm_email');
18498 exports.ClientsConfirmEmailView = (function() {
18499 __extends(ClientsConfirmEmailView, UberView);
18500 function ClientsConfirmEmailView() {
18501 ClientsConfirmEmailView.__super__.constructor.apply(this, arguments);
18503 ClientsConfirmEmailView.prototype.id = 'confirm_email_view';
18504 ClientsConfirmEmailView.prototype.className = 'view_container';
18505 ClientsConfirmEmailView.prototype.render = function(token) {
18507 $(this.el).html(clientsConfirmEmailTemplate());
18512 success: __bind(function(data, textStatus, jqXHR) {
18513 var show_dashboard;
18514 this.HideSpinner();
18515 show_dashboard = function() {
18516 return app.routers.clients.navigate('!/dashboard', true);
18518 if (data.status === 'OK') {
18519 $('.success_message').show();
18520 return _.delay(show_dashboard, 3000);
18521 } else if (data.status === 'ALREADY_COMFIRMED') {
18522 $('.already_confirmed_message').show();
18523 return _.delay(show_dashboard, 3000);
18525 return $('.error_message').show();
18528 error: __bind(function(e) {
18529 this.HideSpinner();
18530 return $('.error_message').show();
18532 complete: function(status) {
18533 return $('#attempt_text').hide();
18537 url: "" + API + "/users/self"
18540 this.ShowSpinner('submit');
18543 return ClientsConfirmEmailView;
18546 }, "views/clients/dashboard": function(exports, require, module) {(function() {
18547 var clientsDashboardTemplate;
18548 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18549 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18550 function ctor() { this.constructor = child; }
18551 ctor.prototype = parent.prototype;
18552 child.prototype = new ctor;
18553 child.__super__ = parent.prototype;
18556 clientsDashboardTemplate = require('templates/clients/dashboard');
18557 exports.ClientsDashboardView = (function() {
18558 var displayFirstTrip;
18559 __extends(ClientsDashboardView, UberView);
18560 function ClientsDashboardView() {
18561 this.showAllTrips = __bind(this.showAllTrips, this);
18562 this.render = __bind(this.render, this);
18563 ClientsDashboardView.__super__.constructor.apply(this, arguments);
18565 ClientsDashboardView.prototype.id = 'dashboard_view';
18566 ClientsDashboardView.prototype.className = 'view_container';
18567 ClientsDashboardView.prototype.events = {
18568 'click a.confirmation': 'confirmationClick',
18569 'click #resend_email': 'resendEmail',
18570 'click #resend_mobile': 'resendMobile',
18571 'click #show_all_trips': 'showAllTrips'
18573 ClientsDashboardView.prototype.render = function() {
18574 var displayPage, downloadTrips;
18575 this.HideSpinner();
18576 displayPage = __bind(function() {
18577 $(this.el).html(clientsDashboardTemplate());
18578 this.confirmationsSetup();
18579 return this.RequireMaps(__bind(function() {
18580 if (USER.trips.models[0]) {
18581 if (!USER.trips.models[0].get("points")) {
18582 return USER.trips.models[0].fetch({
18584 relationships: 'points'
18586 success: __bind(function() {
18587 this.CacheData("USERtrips", USER.trips);
18588 return displayFirstTrip();
18592 return displayFirstTrip();
18597 downloadTrips = __bind(function() {
18598 return this.DownloadUserTrips(displayPage, false, 10);
18600 this.RefreshUserInfo(downloadTrips);
18603 displayFirstTrip = __bind(function() {
18604 var bounds, endPos, map, myOptions, path, polyline, startPos;
18607 mapTypeId: google.maps.MapTypeId.ROADMAP,
18608 zoomControl: false,
18609 rotateControl: false,
18611 mapTypeControl: false,
18614 if (USER.trips.length === 10) {
18615 $("#show_all_trips").show();
18617 if (USER.trips.length > 0) {
18618 map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions);
18619 bounds = new google.maps.LatLngBounds();
18621 _.each(USER.trips.models[0].get('points'), __bind(function(point) {
18622 path.push(new google.maps.LatLng(point.lat, point.lng));
18623 return bounds.extend(_.last(path));
18625 map.fitBounds(bounds);
18626 startPos = new google.maps.Marker({
18627 position: _.first(path),
18629 title: t('Trip started here'),
18630 icon: 'https://uber-static.s3.amazonaws.com/marker_start.png'
18632 endPos = new google.maps.Marker({
18633 position: _.last(path),
18635 title: t('Trip ended here'),
18636 icon: 'https://uber-static.s3.amazonaws.com/marker_end.png'
18638 polyline = new google.maps.Polyline({
18640 strokeColor: '#003F87',
18644 return polyline.setMap(map);
18646 }, ClientsDashboardView);
18647 ClientsDashboardView.prototype.confirmationsSetup = function() {
18648 var blink, cardForm, element, _ref, _ref2, _ref3, _ref4, _ref5;
18649 blink = function(element) {
18652 if (element.css('opacity') === "0.5") {
18655 return element.fadeTo(2000, opacity, function() {
18656 return blink(element);
18659 if (((_ref = window.USER) != null ? (_ref2 = _ref.payment_gateway) != null ? (_ref3 = _ref2.payment_profiles) != null ? _ref3.length : void 0 : void 0 : void 0) === 0) {
18660 element = $('#confirmed_credit_card');
18661 cardForm = new app.views.clients.modules.creditcard;
18662 $('#card.info').append(cardForm.render().el);
18665 if (((_ref4 = window.USER) != null ? _ref4.confirm_email : void 0) === false) {
18666 element = $('#confirmed_email');
18669 if ((((_ref5 = window.USER) != null ? _ref5.confirm_mobile : void 0) != null) === false) {
18670 element = $('#confirmed_mobile');
18671 return blink(element);
18674 ClientsDashboardView.prototype.confirmationClick = function(e) {
18675 e.preventDefault();
18677 $('#more_info').show();
18678 switch (e.currentTarget.id) {
18680 return $('#card.info').slideToggle();
18682 return $('#mobile.info').slideToggle();
18684 return $('#email.info').slideToggle();
18687 ClientsDashboardView.prototype.resendEmail = function(e) {
18689 e.preventDefault();
18690 $el = $(e.currentTarget);
18691 $el.removeAttr('href').prop({
18694 $el.html(t("Sending Email"));
18697 url: API + '/users/request_confirm_email',
18702 success: __bind(function(data, textStatus, jqXHR) {
18703 return $el.html(t("Resend Email Succeeded"));
18705 error: __bind(function(jqXHR, textStatus, errorThrown) {
18706 return $el.html(t("Resend Email Failed"));
18710 ClientsDashboardView.prototype.resendMobile = function(e) {
18712 e.preventDefault();
18713 $el = $(e.currentTarget);
18714 $el.removeAttr('href').prop({
18717 $el.html("Sending message...");
18720 url: API + '/users/request_confirm_mobile',
18725 success: __bind(function(data, textStatus, jqXHR) {
18726 return $el.html(t("Resend Text Succeeded"));
18728 error: __bind(function(jqXHR, textStatus, errorThrown) {
18729 return $el.html(t("Resend Text Failed"));
18733 ClientsDashboardView.prototype.showAllTrips = function(e) {
18734 e.preventDefault();
18735 $(e.currentTarget).hide();
18736 return this.DownloadUserTrips(this.render, true, 1000);
18738 return ClientsDashboardView;
18741 }, "views/clients/forgot_password": function(exports, require, module) {(function() {
18742 var clientsForgotPasswordTemplate;
18743 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18744 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18745 function ctor() { this.constructor = child; }
18746 ctor.prototype = parent.prototype;
18747 child.prototype = new ctor;
18748 child.__super__ = parent.prototype;
18750 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
18751 clientsForgotPasswordTemplate = require('templates/clients/forgot_password');
18752 exports.ClientsForgotPasswordView = (function() {
18753 __extends(ClientsForgotPasswordView, UberView);
18754 function ClientsForgotPasswordView() {
18755 ClientsForgotPasswordView.__super__.constructor.apply(this, arguments);
18757 ClientsForgotPasswordView.prototype.id = 'forgotpassword_view';
18758 ClientsForgotPasswordView.prototype.className = 'view_container modal_view_container';
18759 ClientsForgotPasswordView.prototype.events = {
18760 "submit #password_reset": "passwordReset",
18761 "click #password_reset_submit": "passwordReset",
18762 "submit #forgot_password": "forgotPassword",
18763 "click #forgot_password_submit": "forgotPassword"
18765 ClientsForgotPasswordView.prototype.render = function(token) {
18766 this.HideSpinner();
18767 $(this.el).html(clientsForgotPasswordTemplate({
18770 this.delegateEvents();
18773 ClientsForgotPasswordView.prototype.forgotPassword = function(e) {
18775 e.preventDefault();
18776 $('.success_message').hide();
18777 $(".error_message").hide();
18780 login: $("#login").val()
18782 success: __bind(function(data, textStatus, jqXHR) {
18783 this.HideSpinner();
18784 $('.success_message').show();
18785 return $("#forgot_password").hide();
18787 error: __bind(function(e) {
18788 this.HideSpinner();
18789 return $('.error_message').show();
18793 url: "" + API + "/users/forgot_password"
18796 return this.ShowSpinner('submit');
18798 ClientsForgotPasswordView.prototype.passwordReset = function(e) {
18800 e.preventDefault();
18803 email_token: $("#token").val(),
18804 password: $("#password").val()
18806 success: __bind(function(data, textStatus, jqXHR) {
18807 this.HideSpinner();
18808 $.cookie('token', data.token);
18809 amplify.store('USERjson', data);
18811 return location.hash = '!/dashboard';
18813 error: __bind(function(e) {
18814 this.HideSpinner();
18815 return $('#error_reset').show();
18819 url: "" + API + "/users/self"
18822 return this.ShowSpinner('submit');
18824 return ClientsForgotPasswordView;
18827 }, "views/clients/invite": function(exports, require, module) {(function() {
18828 var clientsInviteTemplate;
18829 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18830 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18831 function ctor() { this.constructor = child; }
18832 ctor.prototype = parent.prototype;
18833 child.prototype = new ctor;
18834 child.__super__ = parent.prototype;
18837 clientsInviteTemplate = require('templates/clients/invite');
18838 exports.ClientsInviteView = (function() {
18839 __extends(ClientsInviteView, UberView);
18840 function ClientsInviteView() {
18841 ClientsInviteView.__super__.constructor.apply(this, arguments);
18843 ClientsInviteView.prototype.id = 'invite_view';
18844 ClientsInviteView.prototype.className = 'view_container';
18845 ClientsInviteView.prototype.render = function() {
18846 this.ReadUserInfo();
18847 this.HideSpinner();
18848 $(this.el).html(clientsInviteTemplate());
18849 console.log(screen);
18852 return ClientsInviteView;
18855 }, "views/clients/login": function(exports, require, module) {(function() {
18856 var clientsLoginTemplate;
18857 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18858 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18859 function ctor() { this.constructor = child; }
18860 ctor.prototype = parent.prototype;
18861 child.prototype = new ctor;
18862 child.__super__ = parent.prototype;
18865 clientsLoginTemplate = require('templates/clients/login');
18866 exports.ClientsLoginView = (function() {
18867 __extends(ClientsLoginView, UberView);
18868 function ClientsLoginView() {
18869 ClientsLoginView.__super__.constructor.apply(this, arguments);
18871 ClientsLoginView.prototype.id = 'login_view';
18872 ClientsLoginView.prototype.className = 'view_container modal_view_container';
18873 ClientsLoginView.prototype.events = {
18874 'submit form': 'authenticate',
18875 'click button': 'authenticate'
18877 ClientsLoginView.prototype.initialize = function() {
18878 _.bindAll(this, 'render');
18879 return this.render();
18881 ClientsLoginView.prototype.render = function() {
18882 this.HideSpinner();
18883 $(this.el).html(clientsLoginTemplate());
18884 this.delegateEvents();
18885 return this.place();
18887 ClientsLoginView.prototype.authenticate = function(e) {
18888 e.preventDefault();
18891 url: API + '/auth/web_login/client',
18893 login: $("#login").val(),
18894 password: $("#password").val()
18897 success: function(data, textStatus, jqXHR) {
18898 $.cookie('user', JSON.stringify(data));
18899 $.cookie('token', data.token);
18900 amplify.store('USERjson', data);
18901 $('header').html(app.views.shared.menu.render().el);
18902 return app.routers.clients.navigate('!/dashboard', true);
18904 error: function(jqXHR, textStatus, errorThrown) {
18905 $.cookie('user', null);
18906 $.cookie('token', null);
18907 if (jqXHR.status === 403) {
18908 $.cookie('redirected_user', JSON.stringify(JSON.parse(jqXHR.responseText).error_obj), {
18909 domain: '.uber.com'
18911 window.location = 'http://partners.uber.com/';
18913 return $('.error_message').html(JSON.parse(jqXHR.responseText).error).hide().fadeIn();
18917 return ClientsLoginView;
18920 }, "views/clients/modules/credit_card": function(exports, require, module) {(function() {
18921 var creditCardTemplate;
18922 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
18923 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
18924 function ctor() { this.constructor = child; }
18925 ctor.prototype = parent.prototype;
18926 child.prototype = new ctor;
18927 child.__super__ = parent.prototype;
18929 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
18930 creditCardTemplate = require('templates/clients/modules/credit_card');
18931 exports.CreditCardView = (function() {
18932 __extends(CreditCardView, UberView);
18933 function CreditCardView() {
18934 CreditCardView.__super__.constructor.apply(this, arguments);
18936 CreditCardView.prototype.id = 'creditcard_view';
18937 CreditCardView.prototype.className = 'module_container';
18938 CreditCardView.prototype.events = {
18939 'submit #credit_card_form': 'processNewCard',
18940 'click #new_card': 'processNewCard',
18941 'change #card_number': 'showCardType',
18942 'click .edit_card_show': 'showEditCard',
18943 'click .edit_card': 'editCard',
18944 'click .delete_card': 'deleteCard',
18945 'click .make_default': 'makeDefault',
18946 'change .use_case': 'saveUseCase'
18948 CreditCardView.prototype.initialize = function() {
18949 return app.collections.paymentprofiles.bind("refresh", __bind(function() {
18950 return this.RefreshUserInfo(__bind(function() {
18951 this.render("all");
18952 return this.HideSpinner();
18956 CreditCardView.prototype.render = function(cards) {
18957 if (cards == null) {
18960 if (cards === "all") {
18961 app.collections.paymentprofiles.reset(USER.payment_gateway.payment_profiles);
18962 cards = app.collections.paymentprofiles;
18964 $(this.el).html(creditCardTemplate({
18969 CreditCardView.prototype.processNewCard = function(e) {
18970 var $el, attrs, model, options;
18971 e.preventDefault();
18972 this.ClearGlobalStatus();
18973 $el = $("#credit_card_form");
18974 $el.find('.error_message').html("");
18976 card_number: $el.find('#card_number').val(),
18977 card_code: $el.find('#card_code').val(),
18978 card_expiration_month: $el.find('#card_expiration_month').val(),
18979 card_expiration_year: $el.find('#card_expiration_year').val(),
18980 use_case: $el.find('#use_case').val(),
18981 "default": $el.find('#default_check').prop("checked")
18985 200: __bind(function(e) {
18986 this.HideSpinner();
18987 $('#cc_form_wrapper').hide();
18988 app.collections.paymentprofiles.trigger("refresh");
18989 $(this.el).remove();
18990 $("a#add_card").show();
18991 return $('section').html(app.views.clients.billing.render().el);
18993 406: __bind(function(e) {
18994 var error, errors, _i, _len, _ref, _results;
18995 this.HideSpinner();
18996 errors = JSON.parse(e.responseText);
18997 _ref = _.keys(errors);
18999 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
19001 _results.push(error === "top_of_form" ? $("#top_of_form").html(errors[error]) : $("#credit_card_form").find("#" + error).parent().find(".error_message").html(errors[error]));
19005 420: __bind(function(e) {
19006 this.HideSpinner();
19007 return $("#top_of_form").html(t("Unable to Verify Card"));
19011 this.ShowSpinner("submit");
19012 model = new app.models.paymentprofile;
19013 model.save(attrs, options);
19014 return app.collections.paymentprofiles.add(model);
19016 CreditCardView.prototype.showCardType = function(e) {
19017 var $el, reAmerica, reDiscover, reMaster, reVisa, validCard;
19018 reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
19019 reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
19020 reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
19021 reDiscover = /^3[4,7]\d{13}$/;
19022 $el = $("#card_logos");
19024 if (e.currentTarget.value.match(reVisa)) {
19026 } else if (e.currentTarget.value.match(reMaster)) {
19027 $el.css('background-position', "-60px");
19029 } else if (e.currentTarget.value.match(reAmerica)) {
19030 $el.css('background-position', "-120px");
19032 } else if (e.currentTarget.value.match(reDiscover)) {
19033 $el.css('background-position', "-180px");
19037 $el.css('width', "60px");
19038 return $el.css('margin-left', "180px");
19040 $el.css('width', "250px");
19041 return $el.css('margin-left', "80px");
19044 CreditCardView.prototype.showEditCard = function(e) {
19046 e.preventDefault();
19047 $el = $(e.currentTarget);
19048 if ($el.html() === t("Edit")) {
19049 id = $el.html(t("Cancel")).parents("tr").attr("id").substring(1);
19050 return $("#e" + id).show();
19052 id = $el.html(t("Edit")).parents("tr").attr("id").substring(1);
19053 return $("#e" + id).hide();
19056 CreditCardView.prototype.editCard = function(e) {
19057 var $el, attrs, id, options;
19058 e.preventDefault();
19059 this.ClearGlobalStatus();
19060 $el = $(e.currentTarget).parents("td");
19061 id = $el.parents("tr").attr("id").substring(1);
19062 $el.attr('disabled', 'disabled');
19063 this.ShowSpinner('submit');
19065 card_expiration_month: $el.find('#card_expiration_month').val(),
19066 card_expiration_year: $el.find('#card_expiration_year').val(),
19067 card_code: $el.find('#card_code').val()
19070 success: __bind(function(response) {
19071 this.HideSpinner();
19072 this.ShowSuccess(t("Credit Card Update Succeeded"));
19073 $("#e" + id).hide();
19074 $("#d" + id).find(".edit_card_show").html(t("Edit"));
19075 return app.collections.paymentprofiles.trigger("refresh");
19077 error: __bind(function(e) {
19078 this.HideSpinner();
19079 this.ShowError(t("Credit Card Update Failed"));
19080 return $el.removeAttr('disabled');
19083 app.collections.paymentprofiles.models[id].set(attrs);
19084 return app.collections.paymentprofiles.models[id].save({}, options);
19086 CreditCardView.prototype.deleteCard = function(e) {
19087 var $el, id, options;
19088 e.preventDefault();
19089 $el = $(e.currentTarget).parents("td");
19090 id = $el.parents("tr").attr("id").substring(1);
19091 this.ClearGlobalStatus();
19092 this.ShowSpinner('submit');
19094 success: __bind(function(response) {
19095 this.ShowSuccess(t("Credit Card Delete Succeeded"));
19097 app.collections.paymentprofiles.trigger("refresh");
19098 return $('section').html(app.views.clients.billing.render().el);
19100 error: __bind(function(xhr, e) {
19101 this.HideSpinner();
19102 return this.ShowError(t("Credit Card Delete Failed"));
19105 return app.collections.paymentprofiles.models[id].destroy(options);
19107 CreditCardView.prototype.saveUseCase = function(e) {
19108 var $el, attrs, id, options, use_case;
19109 this.ClearGlobalStatus();
19110 $el = $(e.currentTarget);
19111 use_case = $el.val();
19112 id = $el.parents("tr").attr("id").substring(1);
19117 success: __bind(function(response) {
19118 return this.ShowSuccess(t("Credit Card Update Category Succeeded"));
19120 error: __bind(function(e) {
19121 return this.ShowError(t("Credit Card Update Category Failed"));
19124 app.collections.paymentprofiles.models[id].set(attrs);
19125 return app.collections.paymentprofiles.models[id].save({}, options);
19127 CreditCardView.prototype.makeDefault = function(e) {
19128 var $el, attrs, id, options;
19129 e.preventDefault();
19130 this.ClearGlobalStatus();
19131 $el = $(e.currentTarget).parents("td");
19132 id = $el.parents("tr").attr("id").substring(1);
19137 success: __bind(function(response) {
19138 this.ShowSuccess(t("Credit Card Update Default Succeeded"));
19139 return app.collections.paymentprofiles.trigger("refresh");
19141 error: __bind(function(e) {
19142 return this.ShowError(t("Credit Card Update Default Failed"));
19145 app.collections.paymentprofiles.models[id].set(attrs);
19146 return app.collections.paymentprofiles.models[id].save({}, options);
19148 return CreditCardView;
19151 }, "views/clients/promotions": function(exports, require, module) {(function() {
19152 var clientsPromotionsTemplate;
19153 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
19154 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
19155 function ctor() { this.constructor = child; }
19156 ctor.prototype = parent.prototype;
19157 child.prototype = new ctor;
19158 child.__super__ = parent.prototype;
19161 clientsPromotionsTemplate = require('templates/clients/promotions');
19162 exports.ClientsPromotionsView = (function() {
19163 __extends(ClientsPromotionsView, UberView);
19164 function ClientsPromotionsView() {
19165 this.render = __bind(this.render, this);
19166 ClientsPromotionsView.__super__.constructor.apply(this, arguments);
19168 ClientsPromotionsView.prototype.id = 'promotions_view';
19169 ClientsPromotionsView.prototype.className = 'view_container';
19170 ClientsPromotionsView.prototype.events = {
19171 'submit form': 'submitPromo',
19172 'click button': 'submitPromo'
19174 ClientsPromotionsView.prototype.initialize = function() {
19176 return this.RefreshUserInfo(this.render);
19179 ClientsPromotionsView.prototype.render = function() {
19180 var renderTemplate;
19181 this.ReadUserInfo();
19182 renderTemplate = __bind(function() {
19183 $(this.el).html(clientsPromotionsTemplate({
19184 promos: window.USER.unexpired_client_promotions || []
19186 return this.HideSpinner();
19188 this.DownloadUserPromotions(renderTemplate);
19191 ClientsPromotionsView.prototype.submitPromo = function(e) {
19192 var attrs, model, options, refreshTable;
19193 e.preventDefault();
19194 this.ClearGlobalStatus();
19195 refreshTable = __bind(function() {
19196 $('section').html(this.render().el);
19197 return this.HideSpinner();
19200 code: $('#code').val()
19203 success: __bind(function(response) {
19204 this.HideSpinner();
19205 if (response.get('first_name')) {
19206 return this.ShowSuccess("Your promotion has been applied in the form of an account credit. <a href='#!/billing'>Click here</a> to check your balance.");
19208 this.ShowSuccess("Your promotion has successfully been applied");
19209 return this.RefreshUserInfo(this.render, true);
19213 400: __bind(function(e) {
19214 this.ShowError(JSON.parse(e.responseText).error);
19215 return this.HideSpinner();
19219 this.ShowSpinner("submit");
19220 model = new app.models.promotions;
19221 return model.save(attrs, options);
19223 return ClientsPromotionsView;
19226 }, "views/clients/request": function(exports, require, module) {(function() {
19227 var clientsRequestTemplate;
19228 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
19229 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
19230 function ctor() { this.constructor = child; }
19231 ctor.prototype = parent.prototype;
19232 child.prototype = new ctor;
19233 child.__super__ = parent.prototype;
19236 clientsRequestTemplate = require('templates/clients/request');
19237 exports.ClientsRequestView = (function() {
19238 __extends(ClientsRequestView, UberView);
19239 function ClientsRequestView() {
19240 this.AjaxCall = __bind(this.AjaxCall, this);
19241 this.AskDispatch = __bind(this.AskDispatch, this);
19242 this.removeMarkers = __bind(this.removeMarkers, this);
19243 this.displaySearchLoc = __bind(this.displaySearchLoc, this);
19244 this.displayFavLoc = __bind(this.displayFavLoc, this);
19245 this.showFavLoc = __bind(this.showFavLoc, this);
19246 this.addToFavLoc = __bind(this.addToFavLoc, this);
19247 this.removeCabs = __bind(this.removeCabs, this);
19248 this.requestRide = __bind(this.requestRide, this);
19249 this.rateTrip = __bind(this.rateTrip, this);
19250 this.locationChange = __bind(this.locationChange, this);
19251 this.panToLocation = __bind(this.panToLocation, this);
19252 this.clickLocation = __bind(this.clickLocation, this);
19253 this.searchLocation = __bind(this.searchLocation, this);
19254 this.mouseoutLocation = __bind(this.mouseoutLocation, this);
19255 this.mouseoverLocation = __bind(this.mouseoverLocation, this);
19256 this.fetchTripDetails = __bind(this.fetchTripDetails, this);
19257 this.submitRating = __bind(this.submitRating, this);
19258 this.setStatus = __bind(this.setStatus, this);
19259 this.initialize = __bind(this.initialize, this);
19260 ClientsRequestView.__super__.constructor.apply(this, arguments);
19262 ClientsRequestView.prototype.id = 'request_view';
19263 ClientsRequestView.prototype.className = 'view_container';
19264 ClientsRequestView.prototype.pollInterval = 2 * 1000;
19265 ClientsRequestView.prototype.events = {
19266 "submit #search_form": "searchAddress",
19267 "click .locations_link": "locationLinkHandle",
19268 "mouseover .location_row": "mouseoverLocation",
19269 "mouseout .location_row": "mouseoutLocation",
19270 "click .location_row": "clickLocation",
19271 "click #search_location": "searchLocation",
19272 "click #pickupHandle": "pickupHandle",
19273 "click .stars": "rateTrip",
19274 "submit #rating_form": "submitRating",
19275 "click #addToFavButton": "showFavLoc",
19276 "click #favLocNickname": "selectInputText",
19277 "submit #favLoc_form": "addToFavLoc"
19279 ClientsRequestView.prototype.status = "";
19280 ClientsRequestView.prototype.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png";
19281 ClientsRequestView.prototype.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png";
19282 ClientsRequestView.prototype.initialize = function() {
19284 displayCabs = __bind(function() {
19285 return this.AskDispatch("NearestCab");
19287 this.showCabs = _.throttle(displayCabs, this.pollInterval);
19288 return this.numSearchToDisplay = 1;
19290 ClientsRequestView.prototype.setStatus = function(status) {
19292 if (this.status === status) {
19296 google.maps.event.trigger(this.map, 'resize');
19300 this.AskDispatch("StatusClient");
19301 this.status = "init";
19302 return this.ShowSpinner("load");
19304 this.HideSpinner();
19305 $(".panel").hide();
19306 $("#top_bar").fadeIn();
19307 $("#location_panel").fadeIn();
19308 $("#location_panel_control").fadeIn();
19309 $("#pickupHandle").attr("class", "button_green").fadeIn().find("span").html(t("Request Pickup"));
19310 this.pickup_icon.setDraggable(true);
19311 this.map.panTo(this.pickup_icon.getPosition());
19314 this.pickup_icon.setMap(this.map);
19315 this.displayFavLoc();
19316 autocomplete = new google.maps.places.Autocomplete(document.getElementById('address'), {
19319 autocomplete.bindTo('bounds', this.map);
19321 return this.status = "ready";
19323 this.HideSpinner();
19324 this.removeMarkers();
19325 $(".panel").hide();
19326 $("#top_bar").fadeOut();
19327 $("#status_message").html(t("Requesting Closest Driver"));
19328 $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup"));
19329 this.pickup_icon.setDraggable(false);
19330 this.pickup_icon.setMap(this.map);
19331 return this.status = "searching";
19333 this.HideSpinner();
19334 this.removeMarkers();
19335 $(".panel").hide();
19336 $("#top_bar").fadeOut();
19337 $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup"));
19338 $("#waiting_riding").fadeIn();
19339 this.pickup_icon.setDraggable(false);
19340 this.pickup_icon.setMap(this.map);
19341 return this.status = "waiting";
19343 this.HideSpinner();
19344 this.removeMarkers();
19345 $(".panel").hide();
19346 $("#top_bar").fadeOut();
19347 $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup"));
19348 $("#waiting_riding").fadeIn();
19349 this.pickup_icon.setDraggable(false);
19350 this.pickup_icon.setMap(this.map);
19351 return this.status = "arriving";
19353 this.HideSpinner();
19354 this.removeMarkers();
19355 $(".panel").hide();
19356 $("#top_bar").fadeOut();
19357 $("#pickupHandle").fadeIn().attr("class", "button_red").find("span").html(t("Cancel Pickup"));
19358 $("#waiting_riding").fadeIn();
19359 this.pickup_icon.setDraggable(false);
19360 this.status = "riding";
19361 return $("#status_message").html(t("En Route"));
19363 this.HideSpinner();
19364 $(".panel").hide();
19365 $("#pickupHandle").fadeOut();
19366 $("#trip_completed_panel").fadeIn();
19367 $('#status_message').html(t("Rate Last Trip"));
19368 return this.status = "rate";
19371 ClientsRequestView.prototype.render = function() {
19372 this.ReadUserInfo();
19373 this.HideSpinner();
19374 this.ShowSpinner("load");
19375 $(this.el).html(clientsRequestTemplate());
19377 this.RequireMaps(__bind(function() {
19378 var center, myOptions, streetViewPano;
19379 center = new google.maps.LatLng(37.7749295, -122.4194155);
19381 this.pickup_icon = new google.maps.Marker({
19385 icon: this.pickupMarker
19387 this.geocoder = new google.maps.Geocoder();
19391 mapTypeId: google.maps.MapTypeId.ROADMAP,
19392 rotateControl: false,
19393 rotateControl: false,
19396 this.map = new google.maps.Map($(this.el).find("#map_wrapper_right")[0], myOptions);
19397 if (this.status === "ready") {
19398 this.pickup_icon.setMap(this.map);
19400 if (geo_position_js.init()) {
19401 geo_position_js.getCurrentPosition(__bind(function(data) {
19403 location = new google.maps.LatLng(data.coords.latitude, data.coords.longitude);
19404 this.pickup_icon.setPosition(location);
19405 this.map.panTo(location);
19406 return this.map.setZoom(16);
19409 this.setStatus("init");
19410 streetViewPano = this.map.getStreetView();
19411 google.maps.event.addListener(streetViewPano, 'visible_changed', __bind(function() {
19412 if (streetViewPano.getVisible()) {
19413 this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker_large.png";
19414 this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker_large.png";
19416 this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png";
19417 this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png";
19419 this.pickup_icon.setIcon(this.pickupMarker);
19420 return _.each(this.cabs, __bind(function(cab) {
19421 return cab.setIcon(this.cabMarker);
19424 if (this.status === "ready") {
19425 return this.displayFavLoc();
19430 ClientsRequestView.prototype.submitRating = function(e) {
19431 var $el, message, rating;
19432 e.preventDefault();
19433 $el = $(e.currentTarget);
19435 _(5).times(function(num) {
19436 if ($el.find(".stars#" + (num + 1)).attr("src") === "/web/img/star_active.png") {
19437 return rating = num + 1;
19440 if (rating === 0) {
19441 $("#status_message").html("").html(t("Rate Before Submitting"));
19443 this.ShowSpinner("submit");
19444 this.AskDispatch("RatingDriver", {
19448 message = $el.find("#comments").val().toString();
19449 if (message.length > 5) {
19450 return this.AskDispatch("Feedback", {
19455 ClientsRequestView.prototype.fetchTripDetails = function(id) {
19457 trip = new app.models.trip({
19460 return trip.fetch({
19462 relationships: 'points,driver,city'
19465 success: __bind(function() {
19466 var bounds, endPos, path, polyline, startPos;
19467 bounds = new google.maps.LatLngBounds();
19469 _.each(trip.get('points'), __bind(function(point) {
19470 path.push(new google.maps.LatLng(point.lat, point.lng));
19471 return bounds.extend(_.last(path));
19473 startPos = new google.maps.Marker({
19474 position: _.first(path),
19476 title: t("Trip started here"),
19477 icon: 'https://uber-static.s3.amazonaws.com/carstart.png'
19479 endPos = new google.maps.Marker({
19480 position: _.last(path),
19482 title: t("Trip ended here"),
19483 icon: 'https://uber-static.s3.amazonaws.com/carstop.png'
19485 polyline = new google.maps.Polyline({
19487 strokeColor: '#003F87',
19491 polyline.setMap(this.map);
19492 this.map.fitBounds(bounds);
19493 $("#tripTime").html(app.helpers.parseDateTime(trip.get('pickup_local_time'), trip.get('city.timezone')));
19494 $("#tripDist").html(app.helpers.RoundNumber(trip.get('distance'), 2));
19495 $("#tripDur").html(app.helpers.FormatSeconds(trip.get('duration')));
19496 return $("#tripFare").html(app.helpers.FormatCurrency(trip.get('fare')));
19500 ClientsRequestView.prototype.searchAddress = function(e) {
19501 var $locationsDiv, address, alphabet, bounds, showResults;
19502 alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
19504 e.preventDefault();
19506 $('.error_message').html("");
19507 $locationsDiv = $("<table></table>");
19508 address = $('#address').val();
19509 bounds = new google.maps.LatLngBounds();
19510 if (address.length < 5) {
19511 $('#status_message').html(t("Address too short")).fadeIn();
19514 showResults = __bind(function(address, index) {
19515 var first_cell, row, second_cell;
19516 if (index < this.numSearchToDisplay) {
19517 first_cell = "<td class='marker_logo'><img src='https://www.google.com/mapfiles/marker" + alphabet[index] + ".png' /></td>";
19518 second_cell = "<td class='location_nickname_wrapper'>" + address.formatted_address + "</td>";
19519 row = $("<tr></tr>").attr("id", "s" + index).attr("class", "location_row").html(first_cell + second_cell);
19520 $locationsDiv.append(row);
19522 if (index === this.numSearchToDisplay) {
19523 $locationsDiv.append("<tr><td colspan=2>" + (t('or did you mean')) + " </td></tr>");
19524 return $locationsDiv.append("<tr><td colspan=2><a id='search_location' href=''>" + address.formatted_address + "</a></td></tr>");
19527 return this.geocoder.geocode({
19529 }, __bind(function(result, status) {
19530 if (status !== "OK") {
19531 $('.error_message').html(t("Search Address Failed")).fadeIn();
19534 _.each(result, showResults);
19535 $("#search_results").html($locationsDiv);
19536 this.locationChange("search");
19537 this.searchResults = result;
19538 return this.displaySearchLoc();
19541 ClientsRequestView.prototype.mouseoverLocation = function(e) {
19542 var $el, id, marker;
19543 $el = $(e.currentTarget);
19544 id = $el.attr("id").substring(1);
19545 marker = this.markers[id];
19546 return marker.setAnimation(google.maps.Animation.BOUNCE);
19548 ClientsRequestView.prototype.mouseoutLocation = function(e) {
19549 var $el, id, marker;
19550 $el = $(e.currentTarget);
19551 id = $el.attr("id").substring(1);
19552 marker = this.markers[id];
19553 return marker.setAnimation(null);
19555 ClientsRequestView.prototype.searchLocation = function(e) {
19556 e.preventDefault();
19557 $("#address").val($(e.currentTarget).html());
19558 return this.searchAddress();
19560 ClientsRequestView.prototype.favoriteClick = function(e) {
19561 var index, location;
19562 e.preventDefault();
19563 $(".favorites").attr("href", "");
19564 index = $(e.currentTarget).removeAttr("href").attr("id");
19565 location = new google.maps.LatLng(USER.locations[index].latitude, USER.locations[index].longitude);
19566 return this.panToLocation(location);
19568 ClientsRequestView.prototype.clickLocation = function(e) {
19570 id = $(e.currentTarget).attr("id").substring(1);
19571 return this.panToLocation(this.markers[id].getPosition());
19573 ClientsRequestView.prototype.panToLocation = function(location) {
19574 this.map.panTo(location);
19575 this.map.setZoom(16);
19576 return this.pickup_icon.setPosition(location);
19578 ClientsRequestView.prototype.locationLinkHandle = function(e) {
19580 e.preventDefault();
19581 panelName = $(e.currentTarget).attr("id");
19582 return this.locationChange(panelName);
19584 ClientsRequestView.prototype.locationChange = function(type) {
19585 $(".locations_link").attr("href", "").css("font-weight", "normal");
19588 $(".search_results").attr("href", "");
19589 $(".locations_link#favorite").removeAttr("href").css("font-weight", "bold");
19590 $("#search_results").hide();
19591 $("#favorite_results").fadeIn();
19592 return this.displayFavLoc();
19594 $(".favorites").attr("href", "");
19595 $(".locations_link#search").removeAttr("href").css("font-weight", "bold");
19596 $("#favorite_results").hide();
19597 $("#search_results").fadeIn();
19598 return this.displaySearchLoc();
19601 ClientsRequestView.prototype.rateTrip = function(e) {
19603 rating = $(e.currentTarget).attr("id");
19604 $(".stars").attr("src", "/web/img/star_inactive.png");
19605 return _(rating).times(function(index) {
19606 return $(".stars#" + (index + 1)).attr("src", "/web/img/star_active.png");
19609 ClientsRequestView.prototype.pickupHandle = function(e) {
19610 var $el, callback, message;
19611 e.preventDefault();
19612 $el = $(e.currentTarget).find("span");
19613 switch ($el.html()) {
19614 case t("Request Pickup"):
19615 _.delay(this.requestRide, 3000);
19616 $("#status_message").html(t("Sending pickup request..."));
19617 $el.html(t("Cancel Pickup")).parent().attr("class", "button_red");
19618 this.pickup_icon.setDraggable(false);
19619 this.map.panTo(this.pickup_icon.getPosition());
19620 return this.map.setZoom(18);
19621 case t("Cancel Pickup"):
19622 if (this.status === "ready") {
19623 $el.html(t("Request Pickup")).parent().attr("class", "button_green");
19624 return this.pickup_icon.setDraggable(true);
19626 callback = __bind(function(v, m, f) {
19628 this.AskDispatch("PickupCanceledClient");
19629 return this.setStatus("ready");
19632 message = t("Cancel Request Prompt");
19633 if (this.status === "arriving") {
19634 message = 'Cancel Request Arrived Prompt';
19636 return $.prompt(message, {
19646 ClientsRequestView.prototype.requestRide = function() {
19647 if ($("#pickupHandle").find("span").html() === t("Cancel Pickup")) {
19648 this.AskDispatch("Pickup");
19649 return this.setStatus("searching");
19652 ClientsRequestView.prototype.removeCabs = function() {
19653 _.each(this.cabs, __bind(function(point) {
19654 return point.setMap(null);
19656 return this.cabs = [];
19658 ClientsRequestView.prototype.addToFavLoc = function(e) {
19659 var $el, lat, lng, nickname;
19660 e.preventDefault();
19661 $el = $(e.currentTarget);
19662 $el.find(".error_message").html("");
19663 nickname = $el.find("#favLocNickname").val().toString();
19664 lat = $el.find("#pickupLat").val().toString();
19665 lng = $el.find("#pickupLng").val().toString();
19666 if (nickname.length < 3) {
19667 $el.find(".error_message").html(t("Favorite Location Nickname Length Error"));
19670 this.ShowSpinner("submit");
19673 url: API + "/locations",
19677 nickname: nickname,
19681 success: __bind(function(data, textStatus, jqXHR) {
19682 return $el.html(t("Favorite Location Save Succeeded"));
19684 error: __bind(function(jqXHR, textStatus, errorThrown) {
19685 return $el.find(".error_message").html(t("Favorite Location Save Failed"));
19687 complete: __bind(function(data) {
19688 return this.HideSpinner();
19692 ClientsRequestView.prototype.showFavLoc = function(e) {
19693 $(e.currentTarget).fadeOut();
19694 return $("#favLoc_form").fadeIn();
19696 ClientsRequestView.prototype.selectInputText = function(e) {
19697 e.currentTarget.focus();
19698 return e.currentTarget.select();
19700 ClientsRequestView.prototype.displayFavLoc = function() {
19701 var alphabet, bounds;
19702 alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
19703 this.removeMarkers();
19704 bounds = new google.maps.LatLngBounds();
19705 _.each(USER.locations, __bind(function(location, index) {
19707 marker = new google.maps.Marker({
19708 position: new google.maps.LatLng(location.latitude, location.longitude),
19710 title: t("Favorite Location Title", {
19711 id: alphabet != null ? alphabet[index] : void 0
19713 icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png"
19715 this.markers.push(marker);
19716 bounds.extend(marker.getPosition());
19717 return google.maps.event.addListener(marker, 'click', __bind(function() {
19718 return this.pickup_icon.setPosition(marker.getPosition());
19721 this.pickup_icon.setPosition(_.first(this.markers).getPosition());
19722 return this.map.fitBounds(bounds);
19724 ClientsRequestView.prototype.displaySearchLoc = function() {
19726 alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
19727 this.removeMarkers();
19728 return _.each(this.searchResults, __bind(function(result, index) {
19730 if (index < this.numSearchToDisplay) {
19731 marker = new google.maps.Marker({
19732 position: result.geometry.location,
19734 title: t("Search Location Title", {
19735 id: alphabet != null ? alphabet[index] : void 0
19737 icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png"
19739 this.markers.push(marker);
19740 return this.panToLocation(result.geometry.location);
19744 ClientsRequestView.prototype.removeMarkers = function() {
19745 _.each(this.markers, __bind(function(marker) {
19746 return marker.setMap(null);
19748 return this.markers = [];
19750 ClientsRequestView.prototype.AskDispatch = function(ask, options) {
19751 var attrs, lowestETA, processData, showCab;
19755 if (options == null) {
19761 latitude: this.pickup_icon.getPosition().lat(),
19762 longitude: this.pickup_icon.getPosition().lng()
19765 showCab = __bind(function(cab) {
19767 point = new google.maps.Marker({
19768 position: new google.maps.LatLng(cab.latitude, cab.longitude),
19770 icon: this.cabMarker,
19771 title: t("ETA Message", {
19772 minutes: app.helpers.FormatSeconds(cab != null ? cab.eta : void 0, true)
19775 if (cab.eta < lowestETA) {
19776 lowestETA = cab.eta;
19778 return this.cabs.push(point);
19780 processData = __bind(function(data, textStatus, jqXHR) {
19781 if (this.status === "ready") {
19784 $("#status_message").html(data.sorry).fadeIn();
19786 _.each(data.driverLocations, showCab);
19787 $("#status_message").html(t("Nearest Cab Message", {
19788 minutes: app.helpers.FormatSeconds(lowestETA, true)
19791 if (Backbone.history.fragment === "!/request") {
19792 return _.delay(this.showCabs, this.pollInterval);
19796 return this.AjaxCall(ask, processData, attrs);
19797 case "StatusClient":
19798 processData = __bind(function(data, textStatus, jqXHR) {
19799 var bounds, cabLocation, locationSaved, point, userLocation;
19800 if (data.messageType === "OK") {
19801 switch (data.status) {
19804 this.setStatus("rate");
19805 return this.fetchTripDetails(data.tripID);
19807 return this.setStatus("ready");
19809 this.setStatus("riding");
19810 cabLocation = new google.maps.LatLng(data.latitude, data.longitude);
19812 this.pickup_icon.setMap(null);
19813 point = new google.maps.Marker({
19814 position: cabLocation,
19816 icon: this.cabMarker
19818 this.cabs.push(point);
19819 this.map.panTo(point.getPosition());
19820 $("#rideName").html(data.driverName);
19821 $("#ridePhone").html(data.driverMobile);
19822 $("#ride_address_wrapper").hide();
19823 if (Backbone.history.fragment === "!/request") {
19824 return _.delay(this.AskDispatch, this.pollInterval, "StatusClient");
19828 this.setStatus("searching");
19829 if (Backbone.history.fragment === "!/request") {
19830 return _.delay(this.AskDispatch, this.pollInterval, "StatusClient");
19835 if (data.status === "accepted") {
19836 this.setStatus("waiting");
19837 $("#status_message").html(t("Arrival ETA Message", {
19838 minutes: app.helpers.FormatSeconds(data.eta, true)
19841 this.setStatus("arriving");
19842 $("#status_message").html(t("Arriving Now Message"));
19844 userLocation = new google.maps.LatLng(data.pickupLocation.latitude, data.pickupLocation.longitude);
19845 cabLocation = new google.maps.LatLng(data.latitude, data.longitude);
19846 this.pickup_icon.setPosition(userLocation);
19848 $("#rideName").html(data.driverName);
19849 $("#ridePhone").html(data.driverMobile);
19850 if ($("#rideAddress").html() === "") {
19851 locationSaved = false;
19852 _.each(USER.locations, __bind(function(location) {
19853 if (parseFloat(location.latitude) === parseFloat(data.pickupLocation.latitude) && parseFloat(location.longitude) === parseFloat(data.pickupLocation.longitude)) {
19854 return locationSaved = true;
19857 if (locationSaved) {
19858 $("#addToFavButton").hide();
19860 $("#pickupLat").val(data.pickupLocation.latitude);
19861 $("#pickupLng").val(data.pickupLocation.longitude);
19862 this.geocoder.geocode({
19863 location: userLocation
19864 }, __bind(function(result, status) {
19865 $("#rideAddress").html(result[0].formatted_address);
19866 return $("#favLocNickname").val("" + result[0].address_components[0].short_name + " " + result[0].address_components[1].short_name);
19869 point = new google.maps.Marker({
19870 position: cabLocation,
19872 icon: this.cabMarker
19874 this.cabs.push(point);
19875 bounds = bounds = new google.maps.LatLngBounds();
19876 bounds.extend(cabLocation);
19877 bounds.extend(userLocation);
19878 this.map.fitBounds(bounds);
19879 if (Backbone.history.fragment === "!/request") {
19880 return _.delay(this.AskDispatch, this.pollInterval, "StatusClient");
19885 return this.AjaxCall(ask, processData);
19888 latitude: this.pickup_icon.getPosition().lat(),
19889 longitude: this.pickup_icon.getPosition().lng()
19891 processData = __bind(function(data, textStatus, jqXHR) {
19892 if (data.messageType === "Error") {
19893 return $("#status_message").html(data.description);
19895 return this.AskDispatch("StatusClient");
19898 return this.AjaxCall(ask, processData, attrs);
19899 case "PickupCanceledClient":
19900 processData = __bind(function(data, textStatus, jqXHR) {
19901 if (data.messageType === "OK") {
19902 return this.setStatus("ready");
19904 return $("#status_message").html(data.description);
19907 return this.AjaxCall(ask, processData, attrs);
19908 case "RatingDriver":
19910 rating: options.rating
19912 processData = __bind(function(data, textStatus, jqXHR) {
19913 if (data.messageType === "OK") {
19914 this.setStatus("init");
19916 $("status_message").html(t("Rating Driver Failed"));
19918 return this.HideSpinner();
19920 return this.AjaxCall(ask, processData, attrs);
19923 message: options.message
19925 processData = __bind(function(data, textStatus, jqXHR) {
19926 if (data.messageType === "OK") {
19927 return alert("rated");
19930 return this.AjaxCall(ask, processData, attrs);
19933 ClientsRequestView.prototype.AjaxCall = function(type, successCallback, attrs) {
19934 if (attrs == null) {
19946 url: DISPATCH + "/",
19947 processData: false,
19948 data: JSON.stringify(attrs),
19949 success: successCallback,
19951 error: __bind(function(jqXHR, textStatus, errorThrown) {
19952 $("#status_message").html(errorThrown);
19953 return this.HideSpinner();
19957 return ClientsRequestView;
19960 }, "views/clients/settings": function(exports, require, module) {(function() {
19961 var clientsSettingsTemplate;
19962 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
19963 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
19964 function ctor() { this.constructor = child; }
19965 ctor.prototype = parent.prototype;
19966 child.prototype = new ctor;
19967 child.__super__ = parent.prototype;
19970 clientsSettingsTemplate = require('templates/clients/settings');
19971 exports.ClientsSettingsView = (function() {
19972 __extends(ClientsSettingsView, UberView);
19973 function ClientsSettingsView() {
19974 this.render = __bind(this.render, this);
19975 this.initialize = __bind(this.initialize, this);
19976 ClientsSettingsView.__super__.constructor.apply(this, arguments);
19978 ClientsSettingsView.prototype.id = 'settings_view';
19979 ClientsSettingsView.prototype.className = 'view_container';
19980 ClientsSettingsView.prototype.events = {
19981 'submit #profile_pic_form': 'processPicUpload',
19982 'click #submit_pic': 'processPicUpload',
19983 'click a.setting_change': "changeTab",
19984 'submit #edit_info_form': "submitInfo",
19985 'click #change_password': 'changePass'
19987 ClientsSettingsView.prototype.divs = {
19988 'info_div': "Information",
19989 'pic_div': "Picture"
19991 ClientsSettingsView.prototype.pageTitle = t("Settings") + " | " + t("Uber");
19992 ClientsSettingsView.prototype.tabTitle = {
19993 'info_div': t("Information"),
19994 'pic_div': t("Picture")
19996 ClientsSettingsView.prototype.initialize = function() {
19997 return this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm);
19999 ClientsSettingsView.prototype.render = function(type) {
20000 if (type == null) {
20003 this.RefreshUserInfo(__bind(function() {
20005 this.delegateEvents();
20006 this.HideSpinner();
20007 alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
20009 $(this.el).html(clientsSettingsTemplate({
20012 $el.find("#" + type + "_div").show();
20013 $el.find("a[href='" + type + "_div']").parent().addClass("active");
20014 return document.title = "" + this.tabTitle[type + '_div'] + " " + this.pageTitle;
20016 this.delegateEvents();
20019 ClientsSettingsView.prototype.changeTab = function(e) {
20020 var $eTarget, $el, div, link, pageDiv, _i, _j, _len, _len2, _ref, _ref2;
20021 e.preventDefault();
20022 $eTarget = $(e.currentTarget);
20023 this.ClearGlobalStatus();
20025 _ref = $el.find(".setting_change");
20026 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
20028 $(link).parent().removeClass("active");
20030 $eTarget.parent().addClass("active");
20031 _ref2 = _.keys(this.divs);
20032 for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
20034 $el.find("#" + div).hide();
20036 pageDiv = $eTarget.attr('href');
20037 $el.find("#" + pageDiv).show();
20038 Backbone.history.navigate("!/settings/" + (this.divs[pageDiv].toLowerCase().replace(" ", "-")), false);
20039 document.title = "" + this.tabTitle[pageDiv] + " " + this.pageTitle;
20040 if (pageDiv === "loc_div") {
20042 google.maps.event.trigger(this.map, 'resize');
20043 return this.map.fitBounds(this.bounds);
20047 ClientsSettingsView.prototype.submitInfo = function(e) {
20048 var $e, attrs, client, options;
20049 $('#global_status').find('.success_message').text('');
20050 $('#global_status').find('.error_message').text('');
20051 $('.error_message').text('');
20052 e.preventDefault();
20053 $e = $(e.currentTarget);
20054 attrs = $e.serializeToJson();
20055 attrs['mobile_country_id'] = this.$('#mobile_country_id').val();
20056 if (attrs['password'] === '') {
20057 delete attrs['password'];
20060 success: __bind(function(response) {
20061 this.ShowSuccess(t("Information Update Succeeded"));
20062 return this.RefreshUserInfo();
20064 error: __bind(function(model, data) {
20066 if (data.status === 406) {
20067 errors = JSON.parse(data.responseText);
20068 return _.each(_.keys(errors), function(field) {
20069 return $("#" + field).parent().find('span.error_message').text(errors[field]);
20072 return this.ShowError(t("Information Update Failed"));
20077 client = new app.models.client({
20080 return client.save(attrs, options);
20082 ClientsSettingsView.prototype.changePass = function(e) {
20083 e.preventDefault();
20084 $(e.currentTarget).hide();
20085 return $("#password").show();
20087 ClientsSettingsView.prototype.processPicUpload = function(e) {
20088 e.preventDefault();
20089 this.ShowSpinner("submit");
20090 return $.ajaxFileUpload({
20091 url: API + '/user_pictures',
20093 fileElementId: 'picture',
20098 complete: __bind(function(data, status) {
20099 this.HideSpinner();
20100 if (status === 'success') {
20101 this.ShowSuccess(t("Picture Update Succeeded"));
20102 return this.RefreshUserInfo(__bind(function() {
20103 return $("#settingsProfPic").attr("src", USER.picture_url + ("?" + (Math.floor(Math.random() * 1000))));
20107 return this.ShowError(data.error);
20109 return this.ShowError("Picture Update Failed");
20115 return ClientsSettingsView;
20118 }, "views/clients/sign_up": function(exports, require, module) {(function() {
20119 var clientsSignUpTemplate;
20120 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
20121 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
20122 function ctor() { this.constructor = child; }
20123 ctor.prototype = parent.prototype;
20124 child.prototype = new ctor;
20125 child.__super__ = parent.prototype;
20127 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
20128 clientsSignUpTemplate = require('templates/clients/sign_up');
20129 exports.ClientsSignUpView = (function() {
20130 __extends(ClientsSignUpView, UberView);
20131 function ClientsSignUpView() {
20132 ClientsSignUpView.__super__.constructor.apply(this, arguments);
20134 ClientsSignUpView.prototype.id = 'signup_view';
20135 ClientsSignUpView.prototype.className = 'view_container';
20136 ClientsSignUpView.prototype.initialize = function() {
20137 this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm);
20138 return $('#location_country').live('change', function() {
20139 if (!$('#mobile').val()) {
20140 return $('#mobile_country').find("option[value=" + ($(this).val()) + "]").attr('selected', 'selected').end().trigger('change');
20144 ClientsSignUpView.prototype.events = {
20145 'submit form': 'signup',
20146 'click button': 'signup',
20147 'change #card_number': 'showCardType',
20148 'change #location_country': 'countryChange'
20150 ClientsSignUpView.prototype.render = function(invite) {
20151 this.HideSpinner();
20152 $(this.el).html(clientsSignUpTemplate({
20157 ClientsSignUpView.prototype.signup = function(e) {
20158 var $el, attrs, client, error_messages, options;
20159 e.preventDefault();
20161 $el.find('#terms_error').hide();
20162 if (!$el.find('#signup_terms input[type=checkbox]').attr('checked')) {
20163 $('#spinner.submit').hide();
20164 $el.find('#terms_error').show();
20167 error_messages = $el.find('.error_message').html("");
20169 first_name: $el.find('#first_name').val(),
20170 last_name: $el.find('#last_name').val(),
20171 email: $el.find('#email').val(),
20172 password: $el.find('#password').val(),
20173 location_country: $el.find('#location_country option:selected').attr('data-iso2'),
20174 location: $el.find('#location').val(),
20175 language: $el.find('#language').val(),
20176 mobile_country: $el.find('#mobile_country option:selected').attr('data-iso2'),
20177 mobile: $el.find('#mobile').val(),
20178 card_number: $el.find('#card_number').val(),
20179 card_expiration_month: $el.find('#card_expiration_month').val(),
20180 card_expiration_year: $el.find('#card_expiration_year').val(),
20181 card_code: $el.find('#card_code').val(),
20182 use_case: $el.find('#use_case').val(),
20183 promotion_code: $el.find('#promotion_code').val()
20187 200: function(response) {
20188 $.cookie('token', response.token);
20189 amplify.store('USERjson', response);
20191 return app.routers.clients.navigate('!/dashboard', true);
20194 var error, errors, _i, _len, _ref, _results;
20195 errors = JSON.parse(e.responseText);
20196 _ref = _.keys(errors);
20198 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
20200 _results.push($('#' + error).parent().find('span').html($('#' + error).parent().find('span').html() + " " + errors[error]));
20205 complete: __bind(function(response) {
20206 return this.HideSpinner();
20209 client = new app.models.client;
20210 $('.spinner#submit').show();
20211 return client.save(attrs, options);
20213 ClientsSignUpView.prototype.countryChange = function(e) {
20215 $e = $(e.currentTarget);
20216 return $("#mobile_country").val($e.val()).trigger('change');
20218 ClientsSignUpView.prototype.showCardType = function(e) {
20219 var $el, reAmerica, reDiscover, reMaster, reVisa, validCard;
20220 reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
20221 reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
20222 reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
20223 reDiscover = /^3[4,7]\d{13}$/;
20224 $el = $("#card_logos_signup");
20226 if (e.currentTarget.value.match(reVisa)) {
20227 $el.find("#overlay_left").css('width', "0px");
20228 return $el.find("#overlay_right").css('width', "75%");
20229 } else if (e.currentTarget.value.match(reMaster)) {
20230 $el.find("#overlay_left").css('width', "25%");
20231 return $el.find("#overlay_right").css('width', "50%");
20232 } else if (e.currentTarget.value.match(reAmerica)) {
20233 $el.find("#overlay_left").css('width', "75%");
20234 $el.find("#overlay_right").css('width', "0px");
20235 return console.log("amex");
20236 } else if (e.currentTarget.value.match(reDiscover)) {
20237 $el.find("#overlay_left").css('width', "50%");
20238 return $el.find("#overlay_right").css('width', "25%");
20240 $el.find("#overlay_left").css('width', "0px");
20241 return $el.find("#overlay_right").css('width', "0px");
20244 return ClientsSignUpView;
20247 }, "views/clients/trip_detail": function(exports, require, module) {(function() {
20248 var clientsTripDetailTemplate;
20249 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
20250 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
20251 function ctor() { this.constructor = child; }
20252 ctor.prototype = parent.prototype;
20253 child.prototype = new ctor;
20254 child.__super__ = parent.prototype;
20257 clientsTripDetailTemplate = require('templates/clients/trip_detail');
20258 exports.TripDetailView = (function() {
20259 __extends(TripDetailView, UberView);
20260 function TripDetailView() {
20261 this.resendReceipt = __bind(this.resendReceipt, this);
20262 TripDetailView.__super__.constructor.apply(this, arguments);
20264 TripDetailView.prototype.id = 'trip_detail_view';
20265 TripDetailView.prototype.className = 'view_container';
20266 TripDetailView.prototype.events = {
20267 'click a#fare_review': 'showFareReview',
20268 'click #fare_review_hide': 'hideFareReview',
20269 'submit #form_review_form': 'submitFareReview',
20270 'click #submit_fare_review': 'submitFareReview',
20271 'click .resendReceipt': 'resendReceipt'
20273 TripDetailView.prototype.render = function(id) {
20277 this.ReadUserInfo();
20278 this.HideSpinner();
20279 this.model = new app.models.trip({
20284 relationships: 'points,driver,city.country'
20287 success: __bind(function() {
20290 $(this.el).html(clientsTripDetailTemplate({
20293 this.RequireMaps(__bind(function() {
20294 var bounds, endPos, map, myOptions, path, polyline, startPos;
20295 bounds = new google.maps.LatLngBounds();
20297 _.each(this.model.get('points'), __bind(function(point) {
20298 path.push(new google.maps.LatLng(point.lat, point.lng));
20299 return bounds.extend(_.last(path));
20304 mapTypeId: google.maps.MapTypeId.ROADMAP,
20305 zoomControl: false,
20306 rotateControl: false,
20308 mapTypeControl: false,
20311 map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions);
20312 map.fitBounds(bounds);
20313 startPos = new google.maps.Marker({
20314 position: _.first(path),
20316 title: t("Trip started here"),
20317 icon: 'https://uber-static.s3.amazonaws.com/marker_start.png'
20319 endPos = new google.maps.Marker({
20320 position: _.last(path),
20322 title: t("Trip ended here"),
20323 icon: 'https://uber-static.s3.amazonaws.com/marker_end.png'
20325 startPos.setMap(map);
20326 endPos.setMap(map);
20327 polyline = new google.maps.Polyline({
20329 strokeColor: '#003F87',
20333 return polyline.setMap(map);
20335 return this.HideSpinner();
20338 this.ShowSpinner('load');
20339 this.delegateEvents();
20342 TripDetailView.prototype.showFareReview = function(e) {
20343 e.preventDefault();
20344 $('#fare_review_box').slideDown();
20345 return $('#fare_review').hide();
20347 TripDetailView.prototype.hideFareReview = function(e) {
20348 e.preventDefault();
20349 $('#fare_review_box').slideUp();
20350 return $('#fare_review').show();
20352 TripDetailView.prototype.submitFareReview = function(e) {
20353 var attrs, errorMessage, id, options;
20354 e.preventDefault();
20355 errorMessage = $(".error_message");
20356 errorMessage.hide();
20357 id = $("#tripid").val();
20358 this.model = new app.models.trip({
20362 note: $('#form_review_message').val(),
20363 note_type: 'client_fare_review'
20366 success: __bind(function(response) {
20367 $(".success_message").fadeIn();
20368 return $("#fare_review_form_wrapper").slideUp();
20370 error: __bind(function(error) {
20371 return errorMessage.fadeIn();
20374 return this.model.save(attrs, options);
20376 TripDetailView.prototype.resendReceipt = function(e) {
20378 e.preventDefault();
20379 $e = $(e.currentTarget);
20380 this.$(".resendReceiptSuccess").empty().show();
20381 this.$(".resentReceiptError").empty().show();
20382 e.preventDefault();
20383 $('#spinner').show();
20384 return $.ajax('/api/trips/func/resend_receipt', {
20386 token: $.cookie('token'),
20387 trip_id: this.model.id
20390 complete: __bind(function(xhr) {
20392 response = JSON.parse(xhr.responseText);
20393 $('#spinner').hide();
20394 switch (xhr.status) {
20396 this.$(".resendReceiptSuccess").html("Receipt has been emailed");
20397 return this.$(".resendReceiptSuccess").fadeOut(2000);
20399 this.$(".resendReceiptError").html("Receipt has failed to be emailed");
20400 return this.$(".resendReceiptError").fadeOut(2000);
20405 return TripDetailView;
20408 }, "views/shared/menu": function(exports, require, module) {(function() {
20410 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
20411 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
20412 function ctor() { this.constructor = child; }
20413 ctor.prototype = parent.prototype;
20414 child.prototype = new ctor;
20415 child.__super__ = parent.prototype;
20418 menuTemplate = require('templates/shared/menu');
20419 exports.SharedMenuView = (function() {
20420 __extends(SharedMenuView, Backbone.View);
20421 function SharedMenuView() {
20422 SharedMenuView.__super__.constructor.apply(this, arguments);
20424 SharedMenuView.prototype.id = 'menu_view';
20425 SharedMenuView.prototype.render = function() {
20427 if ($.cookie('token') === null) {
20432 $(this.el).html(menuTemplate({
20437 return SharedMenuView;
20440 }, "web-lib/collections/countries": function(exports, require, module) {(function() {
20441 var UberCollection;
20442 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
20443 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
20444 function ctor() { this.constructor = child; }
20445 ctor.prototype = parent.prototype;
20446 child.prototype = new ctor;
20447 child.__super__ = parent.prototype;
20450 UberCollection = require('web-lib/uber_collection').UberCollection;
20451 exports.CountriesCollection = (function() {
20452 __extends(CountriesCollection, UberCollection);
20453 function CountriesCollection() {
20454 CountriesCollection.__super__.constructor.apply(this, arguments);
20456 CountriesCollection.prototype.model = app.models.country;
20457 CountriesCollection.prototype.url = '/countries';
20458 return CountriesCollection;
20461 }, "web-lib/collections/vehicle_types": function(exports, require, module) {(function() {
20462 var UberCollection, vehicleType, _ref;
20463 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
20464 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
20465 function ctor() { this.constructor = child; }
20466 ctor.prototype = parent.prototype;
20467 child.prototype = new ctor;
20468 child.__super__ = parent.prototype;
20471 UberCollection = require('web-lib/uber_collection').UberCollection;
20472 vehicleType = (typeof app !== "undefined" && app !== null ? (_ref = app.models) != null ? _ref.vehicleType : void 0 : void 0) || require('models/vehicle_type').VehicleType;
20473 exports.VehicleTypesCollection = (function() {
20474 __extends(VehicleTypesCollection, UberCollection);
20475 function VehicleTypesCollection() {
20476 VehicleTypesCollection.__super__.constructor.apply(this, arguments);
20478 VehicleTypesCollection.prototype.model = vehicleType;
20479 VehicleTypesCollection.prototype.url = '/vehicle_types';
20480 VehicleTypesCollection.prototype.defaultColumns = ['id', 'created_at', 'updated_at', 'deleted_at', 'created_by_user_id', 'updated_by_user_id', 'city_id', 'type', 'make', 'model', 'capacity', 'minimum_year', 'actions'];
20481 VehicleTypesCollection.prototype.tableColumns = function(cols) {
20482 var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, headerRow, id, make, minimum_year, model, type, updated_at, updated_by_user_id, _i, _len;
20487 sTitle: 'Created At (UTC)',
20491 sTitle: 'Updated At (UTC)',
20495 sTitle: 'Deleted At (UTC)',
20498 created_by_user_id = {
20499 sTitle: 'Created By'
20501 updated_by_user_id = {
20502 sTitle: 'Updated By'
20520 sTitle: 'Min. Year'
20527 created_at: created_at,
20528 updated_at: updated_at,
20529 deleted_at: deleted_at,
20530 created_by_user_id: created_by_user_id,
20531 updated_by_user_id: updated_by_user_id,
20536 capacity: capacity,
20537 minimum_year: minimum_year,
20541 for (_i = 0, _len = cols.length; _i < _len; _i++) {
20543 if (columnValues[c]) {
20544 headerRow.push(columnValues[c]);
20549 return VehicleTypesCollection;
20552 }, "web-lib/helpers": function(exports, require, module) {(function() {
20553 var __indexOf = Array.prototype.indexOf || function(item) {
20554 for (var i = 0, l = this.length; i < l; i++) {
20555 if (this[i] === item) return i;
20558 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
20559 exports.helpers = {
20560 pin: function(num, color) {
20561 if (color == null) {
20564 return "<img src=\"http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=" + num + "|" + color + "|000000\" width=\"14\" height=\"22\" />";
20566 reverseGeocode: function(latitude, longitude) {
20567 if (latitude && longitude) {
20568 return "<span data-point=" + (JSON.stringify({
20569 latitude: latitude,
20570 longitude: longitude
20571 })) + ">" + latitude + ", " + longitude + "</span>";
20576 linkedName: function(model) {
20577 var first_name, id, last_name, role, url;
20578 role = model.role || model.get('role');
20579 id = model.id || model.get('id');
20580 first_name = model.first_name || model.get('first_name');
20581 last_name = model.last_name || model.get('last_name');
20582 url = "/" + role + "s/" + id;
20583 return "<a href=\"#" + url + "\">" + first_name + " " + last_name + "</a>";
20585 linkedVehicle: function(vehicle, vehicleType) {
20586 return "<a href=\"/#/vehicles/" + vehicle.id + "\"> " + (vehicleType != null ? vehicleType.get('make') : void 0) + " " + (vehicleType != null ? vehicleType.get('model') : void 0) + " " + (vehicle.get('year')) + " </a>";
20588 linkedUserId: function(userType, userId) {
20589 return "<a href=\"#!/" + userType + "/" + userId + "\" data-user-type=\"" + userType + "\" data-user-id=\"" + userId + "\">" + userType + " " + userId + "</a>";
20591 timeDelta: function(start, end) {
20593 if (typeof start === 'string') {
20594 start = this.parseDate(start);
20596 if (typeof end === 'string') {
20597 end = this.parseDate(end);
20599 if (end && start) {
20600 delta = end.getTime() - start.getTime();
20601 return this.formatSeconds(delta / 1000);
20606 formatSeconds: function(s) {
20607 var minutes, seconds;
20609 minutes = Math.floor(s / 60);
20610 seconds = s - minutes * 60;
20611 return "" + (this.leadingZero(minutes)) + ":" + (this.leadingZero(seconds));
20613 formatCurrency: function(strValue, reverseSign, currency) {
20614 var currency_locale, lc, mf;
20615 if (reverseSign == null) {
20616 reverseSign = false;
20618 if (currency == null) {
20621 strValue = String(strValue);
20623 strValue = ~strValue.indexOf('-') ? strValue.split('-').join('') : ['-', strValue].join('');
20625 currency_locale = i18n.currencyToLocale[currency];
20627 if (!(currency_locale != null) || currency_locale === i18n.locale) {
20628 return i18n.jsworld.mf.format(strValue);
20630 lc = new jsworld.Locale(POSIX_LC[currency_locale]);
20631 mf = new jsworld.MonetaryFormatter(lc);
20632 return mf.format(strValue);
20639 formatTripFare: function(trip, type) {
20641 if (type == null) {
20644 if (!trip.get('fare')) {
20647 if (((_ref = trip.get('fare_breakdown_local')) != null ? _ref.currency : void 0) != null) {
20648 return app.helpers.formatCurrency(trip.get("" + type + "_local"), false, (_ref2 = trip.get('fare_breakdown_local')) != null ? _ref2.currency : void 0);
20649 } else if (trip.get("" + type + "_string") != null) {
20650 return trip.get("" + type + "_string");
20651 } else if (trip.get("" + type + "_local") != null) {
20652 return trip.get("" + type + "_local");
20657 formatPhoneNumber: function(phoneNumber, countryCode) {
20658 if (countryCode == null) {
20659 countryCode = "+1";
20661 if (phoneNumber != null) {
20662 phoneNumber = String(phoneNumber);
20663 switch (countryCode) {
20665 return countryCode + ' ' + phoneNumber.substring(0, 3) + '-' + phoneNumber.substring(3, 6) + '-' + phoneNumber.substring(6, 10);
20667 return countryCode + ' ' + phoneNumber.substring(0, 1) + ' ' + phoneNumber.substring(1, 3) + ' ' + phoneNumber.substring(3, 5) + ' ' + phoneNumber.substring(5, 7) + ' ' + phoneNumber.substring(7, 9);
20669 countryCode + phoneNumber;
20672 return "" + countryCode + " " + phoneNumber;
20674 parseDate: function(d, cityTime, tz) {
20675 var city_filter, parsed, _ref;
20676 if (cityTime == null) {
20682 if (((_ref = !d.substr(-6, 1)) === '+' || _ref === '-') || d.length === 19) {
20685 if (/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.test(d)) {
20686 parsed = d.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);
20688 d.setUTCFullYear(parsed[1]);
20689 d.setUTCMonth(parsed[2] - 1);
20690 d.setUTCDate(parsed[3]);
20691 d.setUTCHours(parsed[4]);
20692 d.setUTCMinutes(parsed[5]);
20693 d.setUTCSeconds(parsed[6]);
20697 if (typeof d === 'number') {
20700 d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC');
20702 d.convertToTimezone(tz);
20703 } else if (cityTime) {
20704 city_filter = $.cookie('city_filter');
20706 tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone');
20708 d.convertToTimezone(tz);
20714 dateToTimezone: function(d) {
20715 var city_filter, tz;
20716 d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC');
20717 city_filter = $.cookie('city_filter');
20719 tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone');
20720 d.convertToTimezone(tz);
20724 fixAMPM: function(d, formatted) {
20725 if (d.hours >= 12) {
20726 return formatted.replace(/\b[AP]M\b/, 'PM');
20728 return formatted.replace(/\b[AP]M\b/, 'AM');
20731 formatDate: function(d, time, timezone) {
20733 if (time == null) {
20736 if (timezone == null) {
20739 d = this.parseDate(d, true, timezone);
20740 formatted = time ? ("" + (i18n.jsworld.dtf.formatDate(d)) + " ") + this.formatTime(d, d.getTimezoneInfo()) : i18n.jsworld.dtf.formatDate(d);
20741 return this.fixAMPM(d, formatted);
20743 formatDateLong: function(d, time, timezone) {
20744 if (time == null) {
20747 if (timezone == null) {
20750 d = this.parseDate(d, true, timezone);
20751 timezone = d.getTimezoneInfo().tzAbbr;
20753 return (i18n.jsworld.dtf.formatDateTime(d)) + (" " + timezone);
20755 return i18n.jsworld.dtf.formatDate(d);
20758 formatTimezoneJSDate: function(d) {
20759 var day, hours, jsDate, minutes, month, year;
20760 year = d.getFullYear();
20761 month = this.leadingZero(d.getMonth());
20762 day = this.leadingZero(d.getDate());
20763 hours = this.leadingZero(d.getHours());
20764 minutes = this.leadingZero(d.getMinutes());
20765 jsDate = new Date(year, month, day, hours, minutes, 0);
20766 return jsDate.toDateString();
20768 formatTime: function(d, timezone) {
20770 if (timezone == null) {
20773 formatted = ("" + (i18n.jsworld.dtf.formatTime(d))) + (timezone != null ? " " + (timezone != null ? timezone.tzAbbr : void 0) : "");
20774 return this.fixAMPM(d, formatted);
20776 formatISODate: function(d) {
20778 pad = function(n) {
20784 return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z';
20786 formatExpDate: function(d) {
20788 d = this.parseDate(d);
20789 year = d.getFullYear();
20790 month = this.leadingZero(d.getMonth() + 1);
20791 return "" + year + "-" + month;
20793 formatLatLng: function(lat, lng, precision) {
20794 if (precision == null) {
20797 return parseFloat(lat).toFixed(precision) + ',' + parseFloat(lng).toFixed(precision);
20799 leadingZero: function(num) {
20806 roundNumber: function(num, dec) {
20807 return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
20809 notesToHTML: function(notes) {
20810 var i, note, notesHTML, _i, _len;
20814 for (_i = 0, _len = notes.length; _i < _len; _i++) {
20816 notesHTML += "<strong>" + note['userid'] + "</strong> " + (this.formatDate(note['created_at'])) + "<p>" + note['note'] + "</p>";
20817 notesHTML += "<br>";
20820 return notesHTML.replace("'", '"e');
20822 formatPhone: function(n) {
20823 var parts, phone, regexObj;
20825 regexObj = /^(?:\+?1[-. ]?)?(?:\(?([0-9]{3})\)?[-. ]?)?([0-9]{3})[-. ]?([0-9]{4})$/;
20826 if (regexObj.test(n)) {
20827 parts = n.match(regexObj);
20830 phone += "(" + parts[1] + ") ";
20832 phone += "" + parts[2] + "-" + parts[3];
20838 usStates: ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'],
20839 onboardingPages: ['applied', 'ready_to_interview', 'pending_interview', 'interviewed', 'accepted', 'ready_to_onboard', 'pending_onboarding', 'active', 'waitlisted', 'rejected'],
20840 driverBreadCrumb: function(loc, model) {
20841 var onboardingPage, out, _i, _len, _ref;
20842 out = "<a href='#/driver_ops/summary'>Drivers</a> > ";
20843 if (!(model != null)) {
20844 out += "<select name='onboardingPage' id='onboardingPageSelector'>";
20845 _ref = this.onboardingPages;
20846 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
20847 onboardingPage = _ref[_i];
20848 out += "<option value='" + onboardingPage + "' " + (onboardingPage === loc ? "selected" : void 0) + ">" + (this.onboardingUrlToName(onboardingPage)) + "</option>";
20850 out += "</select>";
20852 out += "<a href='#/driver_ops/" + (model.get('driver_status')) + "'>" + (this.onboardingUrlToName(model.get('driver_status'))) + "</a>";
20853 out += " > " + (this.linkedName(model)) + " (" + (model.get('role')) + ") #" + (model.get('id'));
20857 onboardingUrlToName: function(url) {
20858 return url != null ? url.replace(/_/g, " ").replace(/(^|\s)([a-z])/g, function(m, p1, p2) {
20859 return p1 + p2.toUpperCase();
20862 formatVehicle: function(vehicle) {
20863 if (vehicle.get('make') && vehicle.get('model') && vehicle.get('license_plate')) {
20864 return "" + (vehicle.get('make')) + " " + (vehicle.get('model')) + " (" + (vehicle.get('license_plate')) + ")";
20867 docArbitraryFields: function(docName, cityDocs) {
20868 var doc, field, out, _i, _j, _len, _len2, _ref;
20870 for (_i = 0, _len = cityDocs.length; _i < _len; _i++) {
20871 doc = cityDocs[_i];
20872 if (doc.name === docName && __indexOf.call(_.keys(doc), "metaFields") >= 0) {
20873 _ref = doc.metaFields;
20874 for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
20876 out += "" + field.label + ": <input type='text' name='" + field.name + "' class='arbitraryField'><br>";
20882 capitaliseFirstLetter: function(string) {
20883 return string.charAt(0).toUpperCase() + string.slice(1);
20885 createDocUploadForm: function(docName, driverId, vehicleId, cityMeta, vehicleName, expirationRequired) {
20886 var ddocs, expDropdowns, pdocs, vdocs;
20887 if (driverId == null) {
20890 if (vehicleId == null) {
20891 vehicleId = "None";
20893 if (cityMeta == null) {
20896 if (vehicleName == null) {
20897 vehicleName = false;
20899 if (expirationRequired == null) {
20900 expirationRequired = false;
20902 ddocs = cityMeta["driverRequiredDocs"] || [];
20903 pdocs = cityMeta["partnerRequiredDocs"] || [];
20904 vdocs = cityMeta["vehicleRequiredDocs"] || [];
20905 expDropdowns = "Expiration Date:\n<select name=\"expiration-year\">\n <option value=\"2011\">2011</option>\n <option value=\"2012\">2012</option>\n <option value=\"2013\">2013</option>\n <option value=\"2014\">2014</option>\n <option value=\"2015\">2015</option>\n <option value=\"2016\">2016</option>\n <option value=\"2017\">2017</option>\n <option value=\"2018\">2018</option>\n</select> -\n<select name=\"expiration-month\">\n <option value=\"01\">01</option>\n <option value=\"02\">02</option>\n <option value=\"03\">03</option>\n <option value=\"04\">04</option>\n <option value=\"05\">05</option>\n <option value=\"06\">06</option>\n <option value=\"07\">07</option>\n <option value=\"08\">08</option>\n <option value=\"09\">09</option>\n <option value=\"10\">10</option>\n <option value=\"11\">11</option>\n <option value=\"12\">12</option>\n</select>";
20906 return " <form class=\"documentuploadform\">\n <div>\n <input type=\"hidden\" name=\"fileName\" value=\"" + docName + "\">\n <input type=\"hidden\" name=\"driver_id\" value=\"" + driverId + "\">\n <input type=\"hidden\" name=\"vehicle_id\" value=\"" + vehicleId + "\">\n\n <div>\n <strong>" + (vehicleName ? vehicleName : "") + " " + docName + "</strong>\n </div>\n\n <div>\n <input type=\"file\" name=\"uploadContent\" id=\"" + (vehicleId !== "None" ? "vehicle_" + vehicleId + "_" : "") + "doc_upload_" + (docName.replace(/[\W]/g, "_")) + "\">\n </div>\n\n <div class=\"expiration\">\n " + (expirationRequired ? expDropdowns : "") + "\n </div>\n\n <div>\n " + (app.helpers.docArbitraryFields(docName, _.union(ddocs, pdocs, vdocs))) + "\n </div>\n\n <div>\n <input type=\"submit\" value=\"Upload\">\n </div>\n\n </div>\n</form>";
20908 countrySelector: function(name, options) {
20909 var countries, countryCodePrefix, defaultOptions;
20910 if (options == null) {
20914 selectedKey: 'telephone_code',
20915 selectedValue: '+1',
20918 _.extend(defaultOptions, options);
20919 options = defaultOptions;
20920 countries = new app.collections.countries();
20925 success: function(countries) {
20926 var $option, $select, country, selected, _i, _len, _ref;
20928 _ref = countries.models || [];
20929 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
20930 country = _ref[_i];
20931 $select = $("select[name=" + name + "]");
20932 $option = $('<option></option>').val(country.id).attr('data-iso2', country.get('iso2')).attr('data-prefix', country.get('telephone_code')).html(country.get('name'));
20933 if (country.get(options.selectedKey) === options.selectedValue && !selected) {
20935 $option.attr('selected', 'selected');
20937 $select.append($option);
20939 if (selected && !options.silent) {
20940 return $select.val(options.selected).trigger('change');
20944 countryCodePrefix = options.countryCodePrefix ? "data-country-code-prefix='" + options.countryCodePrefix + "'" : '';
20945 return "<select name='" + name + "' id='" + name + "' " + countryCodePrefix + " " + (options.disabled ? 'disabled="disabled"' : "") + "></select>";
20947 missingDocsOnDriver: function(driver) {
20948 var city, docsReq, documents, partnerDocs;
20949 city = driver.get('city');
20950 documents = driver.get('documents');
20951 if ((city != null) && (documents != null)) {
20952 docsReq = _.pluck(city != null ? city.get('meta')["driverRequiredDocs"] : void 0, "name");
20953 if (driver.get('role') === "partner") {
20954 partnerDocs = _.pluck(city != null ? city.get('meta')["partnerRequiredDocs"] : void 0, "name");
20955 docsReq = _.union(docsReq, partnerDocs);
20957 return _.reject(docsReq, __bind(function(doc) {
20958 return __indexOf.call((documents != null ? documents.pluck("name") : void 0) || [], doc) >= 0;
20966 }, "web-lib/i18n": function(exports, require, module) {(function() {
20968 defaultLocale: 'en_US',
20969 cookieName: '_LOCALE_',
20971 'en_US': "English (US)",
20972 'fr_FR': "Français"
20974 currencyToLocale: {
20978 logglyKey: 'd2d5a9bc-7ebe-4538-a180-81e62c705b1b',
20979 logglyHost: 'https://logs.loggly.com',
20981 this.castor = new window.loggly({
20982 url: this.logglyHost + '/inputs/' + this.logglyKey + '?rt=1',
20985 this.setLocale($.cookie(this.cookieName) || this.defaultLocale);
20986 window.t = _.bind(this.t, this);
20987 this.loadLocaleTranslations(this.locale);
20988 if (!(this[this.defaultLocale] != null)) {
20989 return this.loadLocaleTranslations(this.defaultLocale);
20992 loadLocaleTranslations: function(locale) {
20993 var loadPaths, path, _i, _len, _results;
20994 loadPaths = ['web-lib/translations/' + locale, 'web-lib/translations/' + locale.slice(0, 2), 'translations/' + locale, 'translations/' + locale.slice(0, 2)];
20996 for (_i = 0, _len = loadPaths.length; _i < _len; _i++) {
20997 path = loadPaths[_i];
20998 locale = path.substring(path.lastIndexOf('/') + 1);
20999 if (this[locale] == null) {
21002 _results.push((function() {
21004 return _.extend(this[locale], require(path).translations);
21012 getLocale: function() {
21013 return this.locale;
21015 setLocale: function(locale) {
21016 var message, parts, _ref;
21017 parts = locale.split('_');
21018 this.locale = parts[0].toLowerCase();
21019 if (parts.length > 1) {
21020 this.locale += "_" + (parts[1].toUpperCase());
21023 $.cookie(this.cookieName, this.locale, {
21025 domain: '.uber.com'
21029 ((_ref = this.jsworld) != null ? _ref : this.jsworld = {}).lc = new jsworld.Locale(POSIX_LC[this.locale]);
21030 this.jsworld.mf = new jsworld.MonetaryFormatter(this.jsworld.lc);
21031 this.jsworld.nf = new jsworld.NumericFormatter(this.jsworld.lc);
21032 this.jsworld.dtf = new jsworld.DateTimeFormatter(this.jsworld.lc);
21033 this.jsworld.np = new jsworld.NumericParser(this.jsworld.lc);
21034 this.jsworld.mp = new jsworld.MonetaryParser(this.jsworld.lc);
21035 return this.jsworld.dtp = new jsworld.DateTimeParser(this.jsworld.lc);
21037 message = 'JsWorld error with locale: ' + this.locale;
21044 getTemplate: function(id) {
21046 return ((_ref = this[this.locale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.locale.slice(0, 2)]) != null ? _ref2[id] : void 0);
21048 getTemplateDefault: function(id) {
21050 return ((_ref = this[this.defaultLocale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.defaultLocale.slice(0, 2)]) != null ? _ref2[id] : void 0);
21052 getTemplateOrDefault: function(id) {
21053 return this.getTemplate(id) || this.getTemplateDefault(id);
21055 t: function(id, vars) {
21056 var errStr, locale, template;
21057 if (vars == null) {
21060 locale = this.getLocale();
21061 template = this.getTemplate(id);
21062 if (template == null) {
21063 if (/dev|test/.test(window.location.host)) {
21064 template = "(?) " + id;
21066 template = this.getTemplateDefault(id);
21068 errStr = "Missing [" + locale + "] translation for [" + id + "] at [" + window.location.hash + "] - Default template is [" + template + "]";
21073 defaultTemplate: template
21077 return _.template(template, vars);
21082 log: function(error) {
21083 if (/dev/.test(window.location.host)) {
21084 if ((typeof console !== "undefined" && console !== null ? console.log : void 0) != null) {
21085 return console.log(error);
21089 host: window.location.host,
21090 hash: window.location.hash
21092 return this.castor.error(JSON.stringify(error));
21097 }, "web-lib/mixins/i18n_phone_form": function(exports, require, module) {(function() {
21098 exports.i18nPhoneForm = {
21100 'change select[data-country-code-prefix]': 'setCountryCodePrefix'
21102 setCountryCodePrefix: function(e) {
21104 $el = $(e.currentTarget);
21105 prefix = $el.find('option:selected').attr('data-prefix');
21106 return $("#" + ($el.attr('data-country-code-prefix'))).text(prefix);
21110 }, "web-lib/models/country": function(exports, require, module) {(function() {
21112 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21113 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21114 function ctor() { this.constructor = child; }
21115 ctor.prototype = parent.prototype;
21116 child.prototype = new ctor;
21117 child.__super__ = parent.prototype;
21120 UberModel = require('web-lib/uber_model').UberModel;
21121 exports.Country = (function() {
21122 __extends(Country, UberModel);
21123 function Country() {
21124 Country.__super__.constructor.apply(this, arguments);
21126 Country.prototype.url = function() {
21128 return "/countries/" + this.id;
21130 return '/countries';
21136 }, "web-lib/models/vehicle_type": function(exports, require, module) {(function() {
21138 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21139 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21140 function ctor() { this.constructor = child; }
21141 ctor.prototype = parent.prototype;
21142 child.prototype = new ctor;
21143 child.__super__ = parent.prototype;
21146 UberModel = require('web-lib/uber_model').UberModel;
21147 exports.VehicleType = (function() {
21148 __extends(VehicleType, UberModel);
21149 function VehicleType() {
21150 this.toString = __bind(this.toString, this);
21151 VehicleType.__super__.constructor.apply(this, arguments);
21153 VehicleType.prototype.endpoint = 'vehicle_types';
21154 VehicleType.prototype.toTableRow = function(cols) {
21155 var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, id, make, minimum_year, model, rows, type, updated_at, updated_by_user_id, _i, _len, _ref;
21156 id = "<a href='#/vehicle_types/" + (this.get('id')) + "'>" + (this.get('id')) + "</a>";
21157 if (this.get('created_at')) {
21158 created_at = app.helpers.formatDate(this.get('created_at'));
21160 if (this.get('updated_at')) {
21161 updated_at = app.helpers.formatDate(this.get('updated_at'));
21163 if (this.get('deleted_at')) {
21164 deleted_at = app.helpers.formatDate(this.get('deleted_at'));
21166 created_by_user_id = "<a href='#/clients/" + (this.get('created_by_user_id')) + "'>" + (this.get('created_by_user_id')) + "</a>";
21167 updated_by_user_id = "<a href='#/clients/" + (this.get('updated_by_user_id')) + "'>" + (this.get('updated_by_user_id')) + "</a>";
21168 city_id = (_ref = this.get('city')) != null ? _ref.get('display_name') : void 0;
21169 type = this.get('type');
21170 make = this.get('make');
21171 model = this.get('model');
21172 capacity = this.get('capacity');
21173 minimum_year = this.get('minimum_year');
21174 actions = "<a href='#/vehicle_types/" + (this.get('id')) + "'>Show</a>";
21175 if (!this.get('deleted_at')) {
21176 actions += " <a href='#/vehicle_types/" + (this.get('id')) + "/edit'>Edit</a>";
21177 actions += " <a id='" + (this.get('id')) + "' class='delete' href='#'>Delete</a>";
21181 created_at: created_at,
21182 updated_at: updated_at,
21183 deleted_at: deleted_at,
21184 created_by_user_id: created_by_user_id,
21185 updated_by_user_id: updated_by_user_id,
21190 capacity: capacity,
21191 minimum_year: minimum_year,
21195 for (_i = 0, _len = cols.length; _i < _len; _i++) {
21197 rows.push(columnValues[c] ? columnValues[c] : '-');
21201 VehicleType.prototype.toString = function() {
21202 return this.get('make') + ' ' + this.get('model') + ' ' + this.get('type') + (" (" + (this.get('capacity')) + ")");
21204 return VehicleType;
21207 }, "web-lib/templates/footer": function(exports, require, module) {module.exports = function(__obj) {
21208 if (!__obj) __obj = {};
21209 var __out = [], __capture = function(callback) {
21210 var out = __out, result;
21212 callback.call(this);
21213 result = __out.join('');
21215 return __safe(result);
21216 }, __sanitize = function(value) {
21217 if (value && value.ecoSafe) {
21219 } else if (typeof value !== 'undefined' && value != null) {
21220 return __escape(value);
21224 }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
21225 __safe = __obj.safe = function(value) {
21226 if (value && value.ecoSafe) {
21229 if (!(typeof value !== 'undefined' && value != null)) value = '';
21230 var result = new String(value);
21231 result.ecoSafe = true;
21236 __escape = __obj.escape = function(value) {
21237 return ('' + value)
21238 .replace(/&/g, '&')
21239 .replace(/</g, '<')
21240 .replace(/>/g, '>')
21241 .replace(/"/g, '"');
21246 var locale, title, _ref;
21247 __out.push('<div class="footer_col_2">\n <ul>\n <li class="head">');
21248 __out.push(__sanitize(t("Info")));
21249 __out.push('</li>\n <li><a href="https://www.uber.com/learn">');
21250 __out.push(__sanitize(t("Learn More")));
21251 __out.push('</a></li>\n <li><a href="https://www.uber.com/learn#pricing">');
21252 __out.push(__sanitize(t("Pricing")));
21253 __out.push('</a></li>\n <li><a href="http://support.uber.com">');
21254 __out.push(__sanitize(t("Support & FAQ")));
21255 __out.push('</a></li>\n <li><a href="https://partners.uber.com/#!/partners/new">');
21256 __out.push(__sanitize(t("Apply to Drive")));
21257 __out.push('</a></li>\n </ul>\n</div>\n<div class="footer_col_2">\n <ul>\n <li class="head">');
21258 __out.push(__sanitize(t("Social")));
21259 __out.push('</li>\n <li><a href="http://www.twitter.com/uber">');
21260 __out.push(__sanitize(t("Twitter")));
21261 __out.push('</a></li>\n <li><a href="http://www.facebook.com/uber">');
21262 __out.push(__sanitize(t("Facebook")));
21263 __out.push('</a></li>\n <li><a href="http://blog.uber.com">');
21264 __out.push(__sanitize(t("Blog")));
21265 __out.push('</a></li>\n <li><a href="https://www.uber.com/contact">');
21266 __out.push(__sanitize(t("Contact Us")));
21267 __out.push('</a></li>\n </ul>\n</div>\n<div class="footer_col_2">\n <ul>\n <li class="head">');
21268 __out.push(__sanitize(t("Phones")));
21269 __out.push('</li>\n <li><a href="https://www.uber.com/phones/text">');
21270 __out.push(__sanitize(t("Text Message")));
21271 __out.push('</a></li>\n <li><a href="https://www.uber.com/phones/iphone">');
21272 __out.push(__sanitize(t("iPhone")));
21273 __out.push('</a></li>\n <li><a href="https://www.uber.com/phones/android">');
21274 __out.push(__sanitize(t("Android")));
21275 __out.push('</a></li>\n </ul>\n</div>\n<div class="footer_col_2">\n <ul>\n <li class="head">');
21276 __out.push(__sanitize(t("Company_Footer")));
21277 __out.push('</li>\n <li><a href="https://www.uber.com/privacy">');
21278 __out.push(__sanitize(t("Privacy Policy")));
21279 __out.push('</a></li>\n <li><a href="https://www.uber.com/terms">');
21280 __out.push(__sanitize(t("Terms")));
21281 __out.push('</a></li>\n <li><a href="https://www.uber.com/jobs">');
21282 __out.push(__sanitize(t("Jobs")));
21283 __out.push('</a></li>\n </ul>\n</div>\n<div class="footer_col_copyright">\n <p>');
21284 __out.push(t("Copyright © Uber Technologies, Inc."));
21285 __out.push('</p>\n <p>\n ');
21286 __out.push(__sanitize(t('Language:')));
21288 _ref = typeof i18n !== "undefined" && i18n !== null ? i18n.locales : void 0;
21289 for (locale in _ref) {
21290 title = _ref[locale];
21292 if (locale === (typeof i18n !== "undefined" && i18n !== null ? i18n.getLocale() : void 0)) {
21293 __out.push('\n <span class="language current_language" id=\'');
21294 __out.push(__sanitize(locale));
21296 __out.push(__sanitize(title));
21297 __out.push('</span>\n ');
21299 __out.push('\n <a href="');
21300 __out.push(__sanitize(window.location.href));
21301 __out.push('" class="language" id=\'');
21302 __out.push(__sanitize(locale));
21303 __out.push('\' title="');
21304 __out.push(__sanitize(title));
21306 __out.push(__sanitize(title));
21307 __out.push('</a>\n ');
21311 __out.push('\n </p>\n</div>\n');
21315 __obj.safe = __objSafe, __obj.escape = __escape;
21316 return __out.join('');
21317 }}, "web-lib/translations/en": function(exports, require, module) {(function() {
21318 exports.translations = {
21320 "Learn More": "Learn More",
21321 "Pricing": "Pricing",
21323 "Support": "Support",
21324 "Support & FAQ": "Support & FAQ",
21325 "Contact Us": "Contact Us",
21327 "Phones": "Phones",
21328 "Text Message": "Text Message",
21329 "iPhone": "iPhone",
21330 "Android": "Android",
21331 "Drivers": "Drivers",
21333 "Sign In": "Sign In",
21334 "Social": "Social",
21335 "Twitter": "Twitter",
21336 "Facebook": "Facebook",
21339 "Company_Footer": "Company",
21340 "Privacy Policy": "Privacy Policy",
21342 "Copyright © Uber Technologies, Inc.": "Copyright © Uber Technologies, Inc.",
21343 "Language:": "Language:",
21344 "Apply to Drive": "Apply to Drive",
21345 "Expiration": "Expiration",
21347 "Driver": "Driver ",
21348 "Dashboard": "Dashboard",
21349 "Forgot Password": "Forgot Password",
21350 "Trip Details": "Trip Details",
21352 "Cancel": "Cancel",
21354 "Password": "Password",
21355 "First Name": "First Name",
21356 "Last Name": "Last Name",
21357 "Email Address": "Email Address",
21358 "Submit": "Submit",
21359 "Mobile Number": "Mobile Number",
21360 "Zip Code": "Zip Code",
21361 "Sign Out": "Sign Out",
21362 "Confirm Email Message": "Attempting to confirm email...",
21363 "Upload": "Upload",
21364 "Rating": "Rating",
21365 "Pickup Time": "Pickup Time",
21392 }, "web-lib/translations/fr": function(exports, require, module) {(function() {
21393 exports.translations = {
21395 "Learn More": "En Savoir Plus",
21396 "Pricing": "Calcul du Prix",
21397 "Support & FAQ": "Aide & FAQ",
21398 "Contact Us": "Contactez Nous",
21400 "Phones": "Téléphones",
21401 "Text Message": "SMS",
21402 "iPhone": "iPhone",
21403 "Android": "Android",
21404 "Apply to Drive": "Candidature Chauffeur",
21405 "Sign In": "Connexion",
21406 "Social": "Contact",
21407 "Twitter": "Twitter",
21408 "Facebook": "Facebook",
21410 "Privacy Policy": "Protection des Données Personelles",
21411 "Terms": "Conditions Générales",
21412 "Copyright © Uber Technologies, Inc.": "© Uber, Inc.",
21413 "Language:": "Langue:",
21414 "Forgot Password": "Mot de passe oublié",
21415 "Company_Footer": "À Propos d'Uber",
21416 "Expiration": "Expiration",
21418 "Driver": "Chauffeur",
21419 "Drivers": "Chauffeurs",
21420 "Dashboard": "Tableau de bord",
21421 "Forgot Password": "Mot de passe oublié",
21422 "Forgot Password?": "Mot de passe oublié?",
21423 "Trip Details": "Détails de la course",
21424 "Save": "Enregistrer",
21425 "Cancel": "Annuler",
21426 "Edit": "Modifier",
21427 "Password": "Mot de passe",
21428 "First Name": "Prénom",
21429 "Last Name": "Nom",
21430 "Email Address": "E-mail",
21431 "Submit": "Soumettre",
21432 "Mobile Number": "Téléphone Portable",
21433 "Zip Code": "Code Postal",
21434 "Sign Out": "Se déconnecter",
21435 "Confirm Email Message": "E-mail de confirmation",
21436 "Upload": "Télécharger",
21437 "Rating": "Notation",
21438 "Pickup Time": "Heure de prise en charge",
21465 }, "web-lib/uber_collection": function(exports, require, module) {(function() {
21466 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21467 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21468 function ctor() { this.constructor = child; }
21469 ctor.prototype = parent.prototype;
21470 child.prototype = new ctor;
21471 child.__super__ = parent.prototype;
21474 exports.UberCollection = (function() {
21475 __extends(UberCollection, Backbone.Collection);
21476 function UberCollection() {
21477 UberCollection.__super__.constructor.apply(this, arguments);
21479 UberCollection.prototype.parse = function(data) {
21480 var model, tmp, _i, _in, _len, _out;
21481 _in = data.resources || data;
21484 this.meta = data.meta;
21486 for (_i = 0, _len = _in.length; _i < _len; _i++) {
21488 tmp = new this.model;
21489 tmp.set(tmp.parse(model));
21494 UberCollection.prototype.isRenderable = function() {
21495 if (this.models.length) {
21499 UberCollection.prototype.toTableRows = function(cols) {
21502 _.each(this.models, function(model) {
21503 return tableRows.push(model.toTableRow(cols));
21507 return UberCollection;
21510 }, "web-lib/uber_model": function(exports, require, module) {(function() {
21511 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21512 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21513 function ctor() { this.constructor = child; }
21514 ctor.prototype = parent.prototype;
21515 child.prototype = new ctor;
21516 child.__super__ = parent.prototype;
21518 }, __indexOf = Array.prototype.indexOf || function(item) {
21519 for (var i = 0, l = this.length; i < l; i++) {
21520 if (this[i] === item) return i;
21524 exports.UberModel = (function() {
21525 __extends(UberModel, Backbone.Model);
21526 function UberModel() {
21527 this.refetch = __bind(this.refetch, this);
21528 this.fetch = __bind(this.fetch, this);
21529 this.save = __bind(this.save, this);
21530 this.parse = __bind(this.parse, this);
21531 UberModel.__super__.constructor.apply(this, arguments);
21533 UberModel.prototype.endpoint = 'set_api_endpoint_in_subclass';
21534 UberModel.prototype.refetchOptions = {};
21535 UberModel.prototype.url = function(type) {
21537 endpoint_path = "/" + this.endpoint;
21538 if (this.get('id')) {
21539 return endpoint_path + ("/" + (this.get('id')));
21541 return endpoint_path;
21544 UberModel.prototype.isRenderable = function() {
21545 var i, key, value, _ref;
21547 _ref = this.attributes;
21548 for (key in _ref) {
21549 if (!__hasProp.call(_ref, key)) continue;
21551 if (this.attributes.hasOwnProperty(key)) {
21560 UberModel.prototype.parse = function(response) {
21561 var attrs, key, model, models, _i, _j, _k, _len, _len2, _len3, _ref, _ref2;
21562 if (typeof response === 'object') {
21563 _ref = _.intersection(_.keys(app.models), _.keys(response));
21564 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
21566 if (response[key]) {
21567 attrs = this.parse(response[key]);
21568 if (typeof attrs === 'object') {
21569 response[key] = new app.models[key](attrs);
21573 _ref2 = _.intersection(_.keys(app.collections), _.keys(response));
21574 for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
21576 models = response[key];
21577 if (_.isArray(models)) {
21578 response[key] = new app.collections[key];
21579 for (_k = 0, _len3 = models.length; _k < _len3; _k++) {
21580 model = models[_k];
21581 attrs = app.collections[key].prototype.model.prototype.parse(model);
21582 response[key].add(new response[key].model(attrs));
21589 UberModel.prototype.save = function(attributes, options) {
21590 var attr, _i, _j, _len, _len2, _ref, _ref2;
21591 if (options == null) {
21594 _ref = _.intersection(_.keys(app.models), _.keys(this.attributes));
21595 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
21597 if (typeof this.get(attr) === "object") {
21603 _ref2 = _.intersection(_.keys(app.collections), _.keys(this.attributes));
21604 for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
21606 if (typeof this.get(attr) === "object") {
21612 if ((options != null) && options.diff && (attributes != null) && attributes !== {}) {
21613 attributes['id'] = this.get('id');
21614 attributes['token'] = this.get('token');
21618 this.set(attributes, {
21622 if (__indexOf.call(_.keys(options), "data") < 0 && __indexOf.call(_.keys(this.refetchOptions || {}), "data") >= 0) {
21623 options.data = this.refetchOptions.data;
21625 return Backbone.Model.prototype.save.call(this, attributes, options);
21627 UberModel.prototype.fetch = function(options) {
21628 this.refetchOptions = options;
21629 return Backbone.Model.prototype.fetch.call(this, options);
21631 UberModel.prototype.refetch = function() {
21632 return this.fetch(this.refetchOptions);
21637 }, "web-lib/uber_router": function(exports, require, module) {(function() {
21638 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21639 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21640 function ctor() { this.constructor = child; }
21641 ctor.prototype = parent.prototype;
21642 child.prototype = new ctor;
21643 child.__super__ = parent.prototype;
21646 exports.UberRouter = (function() {
21647 __extends(UberRouter, Backbone.Router);
21648 function UberRouter() {
21649 UberRouter.__super__.constructor.apply(this, arguments);
21651 UberRouter.prototype.datePickers = function(format) {
21652 if (format == null) {
21653 format = "%Z-%m-%dT%H:%i:%s%:";
21655 $('.datepicker').AnyTime_noPicker();
21656 return $('.datepicker').AnyTime_picker({
21658 'formatUtcOffset': '%@'
21661 UberRouter.prototype.autoGrowInput = function() {
21662 return $('.editable input').autoGrowInput();
21664 UberRouter.prototype.windowTitle = function(title) {
21665 return $(document).attr('title', title);
21670 }, "web-lib/uber_show_view": function(exports, require, module) {(function() {
21672 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21673 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21674 function ctor() { this.constructor = child; }
21675 ctor.prototype = parent.prototype;
21676 child.prototype = new ctor;
21677 child.__super__ = parent.prototype;
21679 }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
21680 UberView = require('web-lib/uber_view').UberView;
21681 exports.UberShowView = (function() {
21682 __extends(UberShowView, UberView);
21683 function UberShowView() {
21684 UberShowView.__super__.constructor.apply(this, arguments);
21686 UberShowView.prototype.view = 'show';
21687 UberShowView.prototype.events = {
21688 'click #edit': 'edit',
21689 'submit form': 'save',
21690 'click .cancel': 'cancel'
21692 UberShowView.prototype.errors = null;
21693 UberShowView.prototype.showTemplate = null;
21694 UberShowView.prototype.editTemplate = null;
21695 UberShowView.prototype.initialize = function() {
21696 if (this.init_hook) {
21699 _.bindAll(this, 'render');
21700 return this.model.bind('change', this.render);
21702 UberShowView.prototype.render = function() {
21706 if (this.view === 'show') {
21707 $el.html(this.showTemplate({
21710 } else if (this.view === 'edit') {
21711 $el.html(this.editTemplate({
21713 errors: this.errors || {},
21714 collections: this.collections || {}
21717 $el.html(this.newTemplate({
21719 errors: this.errors || {},
21720 collections: this.collections || {}
21723 if (this.render_hook) {
21724 this.render_hook();
21726 this.errors = null;
21727 this.userIdsToLinkedNames();
21728 this.datePickers();
21729 return this.place();
21731 UberShowView.prototype.selectView = function() {
21733 if (this.options.urlRendering) {
21734 url = window.location.hash;
21735 if (url.match(/\/new/)) {
21736 return this.view = 'new';
21737 } else if (url.match(/\/edit/)) {
21738 return this.view = 'edit';
21740 return this.view = 'show';
21744 UberShowView.prototype.edit = function(e) {
21745 e.preventDefault();
21746 if (this.options.urlRendering) {
21747 window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id') + '/edit';
21749 this.view = 'edit';
21751 return this.model.change();
21753 UberShowView.prototype.save = function(e) {
21754 var attributes, ele, form_attrs, _i, _len, _ref;
21755 e.preventDefault();
21756 attributes = $(e.currentTarget).serializeToJson();
21758 _ref = $('input[type="radio"]');
21759 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
21761 if ($(ele).is(':checked')) {
21762 form_attrs[$(ele).attr('name')] = $(ele).attr('value');
21765 attributes = _.extend(attributes, form_attrs);
21766 if (this.relationships) {
21767 attributes = _.extend(attributes, {
21768 relationships: this.relationships
21771 if (this.filter_attributes != null) {
21772 this.filter_attributes(attributes);
21774 return this.model.save(attributes, {
21776 success: __bind(function(model) {
21777 if (this.options.urlRendering) {
21778 window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id');
21780 this.view = 'show';
21782 return this.flash('success', "Uber save!");
21785 406: __bind(function(xhr) {
21786 this.errors = JSON.parse(xhr.responseText);
21787 return this.flash('error', 'That was not Uber.');
21790 error: __bind(function(model, xhr) {
21791 var code, message, responseJSON, responseText;
21793 responseText = xhr.responseText;
21794 if (responseText) {
21795 responseJSON = JSON.parse(responseText);
21797 if (responseJSON && (typeof responseJSON === 'object') && (responseJSON.hasOwnProperty('error'))) {
21798 message = responseJSON.error;
21800 return this.flash('error', (code || 'Unknown') + ' error' + (': ' + message || ''));
21802 complete: __bind(function() {
21803 return this.model.change();
21807 UberShowView.prototype.cancel = function(e) {
21808 e.preventDefault();
21809 if (this.options.urlRendering) {
21810 window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id');
21812 this.view = 'show';
21814 return this.model.fetch({
21816 complete: __bind(function() {
21817 return this.model.change();
21821 return UberShowView;
21824 }, "web-lib/uber_sync": function(exports, require, module) {(function() {
21826 var __indexOf = Array.prototype.indexOf || function(item) {
21827 for (var i = 0, l = this.length; i < l; i++) {
21828 if (this[i] === item) return i;
21835 "delete": 'DELETE',
21838 exports.UberSync = function(method, model, options) {
21840 options.type = methodType[method];
21841 options.url = _.isString(this.url) ? '/api' + this.url : '/api' + this.url(options.type);
21842 options.data = _.extend({}, options.data);
21843 if (__indexOf.call(_.keys(options.data), "city_id") < 0) {
21844 if ($.cookie('city_filter')) {
21845 _.extend(options.data, {
21846 city_id: $.cookie('city_filter')
21850 delete options.data['city_id'];
21852 if (options.type === 'POST' || options.type === 'PUT') {
21853 _.extend(options.data, model.toJSON());
21855 token = $.cookie('token') ? $.cookie('token') : typeof USER !== "undefined" && USER !== null ? USER.get('token') : "";
21856 _.extend(options.data, {
21859 if (method === "delete") {
21860 options.contentType = 'application/json';
21861 options.data = JSON.stringify(options.data);
21863 return $.ajax(options);
21866 }, "web-lib/uber_view": function(exports, require, module) {(function() {
21867 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
21868 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
21869 function ctor() { this.constructor = child; }
21870 ctor.prototype = parent.prototype;
21871 child.prototype = new ctor;
21872 child.__super__ = parent.prototype;
21875 exports.UberView = (function() {
21876 __extends(UberView, Backbone.View);
21877 function UberView() {
21878 this.processDocumentUpload = __bind(this.processDocumentUpload, this);
21879 UberView.__super__.constructor.apply(this, arguments);
21881 UberView.prototype.className = 'view_container';
21882 UberView.prototype.hashId = function() {
21883 return parseInt(location.hash.split('/')[2]);
21885 UberView.prototype.place = function(content) {
21887 $target = this.options.scope ? this.options.scope.find(this.options.selector) : $(this.options.selector);
21888 $target[this.options.method || 'html'](content || this.el);
21889 this.delegateEvents();
21890 $('#spinner').hide();
21893 UberView.prototype.mixin = function(m, args) {
21895 if (args == null) {
21899 events = m._events;
21901 if (m.initialize) {
21902 m.initialize(self, args);
21904 return _.each(_.keys(events), function(key) {
21905 var event, func, selector, split;
21906 split = key.split(' ');
21908 selector = split[1];
21909 func = events[key];
21910 return $(self.el).find(selector).live(event, function(e) {
21911 return self[func](e);
21915 UberView.prototype.datePickers = function(format) {
21916 if (format == null) {
21917 format = "%Z-%m-%dT%H:%i:%s%:";
21919 $('.datepicker').AnyTime_noPicker();
21920 return $('.datepicker').AnyTime_picker({
21922 'formatUtcOffset': '%@'
21925 UberView.prototype.dataTable = function(collection, selector, options, params, cols) {
21927 if (selector == null) {
21928 selector = 'table';
21930 if (options == null) {
21933 if (params == null) {
21936 if (cols == null) {
21939 $(selector).empty();
21940 if (!cols.length) {
21941 cols = collection.defaultColumns;
21944 aoColumns: collection.tableColumns(cols),
21951 bScrollInfinite: true,
21952 bScrollCollapse: true,
21954 iDisplayLength: 50,
21955 fnServerData: function(source, data, callback) {
21958 limit: data[4].value,
21959 offset: data[3].value
21961 return collection.fetch({
21962 data: _.extend(defaultParams, params),
21963 success: function() {
21965 aaData: collection.toTableRows(cols),
21966 iTotalRecords: collection.meta.count,
21967 iTotalDisplayRecords: collection.meta.count
21970 error: function() {
21972 message: 'Loading error.'
21977 fnRowCallback: function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
21978 $('[data-tooltip]', nRow).qtip({
21980 attr: 'data-tooltip'
21983 classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow"
21989 return $(this.el).find(selector).dataTable(_.extend(defaults, options));
21991 UberView.prototype.dataTableLocal = function(collection, selector, options, params, cols) {
21992 var $dataTable, defaults;
21993 if (selector == null) {
21994 selector = 'table';
21996 if (options == null) {
21999 if (params == null) {
22002 if (cols == null) {
22005 $(selector).empty();
22006 if (!cols.length || cols.length === 0) {
22007 cols = collection.defaultColumns;
22010 aaData: collection.toTableRows(cols),
22011 aoColumns: collection.tableColumns(cols),
22016 bScrollInfinite: true,
22017 bScrollCollapse: true,
22021 $dataTable = $(this.el).find(selector).dataTable(_.extend(defaults, options));
22022 _.delay(__bind(function() {
22023 if ($dataTable && $dataTable.length > 0) {
22024 return $dataTable.fnAdjustColumnSizing();
22029 UberView.prototype.reverseGeocode = function() {
22033 return this.requireMaps(function() {
22035 geocoder = new google.maps.Geocoder();
22036 return $el.find('[data-point]').each(function() {
22037 var $this, latLng, point;
22039 point = JSON.parse($this.attr('data-point'));
22040 latLng = new google.maps.LatLng(point.latitude, point.longitude);
22041 return geocoder.geocode({
22043 }, function(data, status) {
22044 if (status === google.maps.GeocoderStatus.OK) {
22045 return $this.text(data[0].formatted_address);
22051 UberView.prototype.userIdsToLinkedNames = function() {
22054 return $el.find('a[data-user-id][data-user-type]').each(function() {
22055 var $this, user, userType;
22057 userType = $this.attr('data-user-type') === 'user' ? 'client' : $this.attr('data-user-type');
22058 user = new app.models[userType]({
22059 id: $this.attr('data-user-id')
22061 return user.fetch({
22062 success: function(user) {
22063 return $this.html(app.helpers.linkedName(user)).attr('href', "!/" + user.role + "s/" + user.id);
22065 error: function() {
22066 if ($this.attr('data-user-type') === 'user') {
22067 user = new app.models['driver']({
22068 id: $this.attr('data-user-id')
22070 return user.fetch({
22071 success: function(user) {
22072 return $this.html(app.helpers.linkedName(user)).attr('href', "!/driver/" + user.id);
22080 UberView.prototype.selectedCity = function() {
22081 var $selected, city, cityFilter;
22082 cityFilter = $.cookie('city_filter');
22083 $selected = $("#city_filter option[value=" + cityFilter + "]");
22084 if (city_filter && $selected.length) {
22086 lat: parseFloat($selected.attr('data-lat')),
22087 lng: parseFloat($selected.attr('data-lng')),
22088 timezone: $selected.attr('data-timezone')
22094 timezone: 'Etc/UTC'
22098 UberView.prototype.updateModel = function(e, success) {
22099 var $el, attrs, model, self;
22100 e.preventDefault();
22101 $el = $(e.currentTarget);
22103 model = new this.model.__proto__.constructor({
22107 $el.find('[name]').each(function() {
22110 return attrs["" + ($this.attr('name'))] = $this.val();
22112 self.model.set(attrs);
22113 $el.find('span.error').text('');
22114 return model.save(attrs, {
22115 complete: function(xhr) {
22117 response = JSON.parse(xhr.responseText);
22118 switch (xhr.status) {
22120 self.model = model;
22121 $el.find('[name]').val('');
22127 return _.each(response, function(error, field) {
22128 return $el.find("[name=" + field + "]").parent().find('span.error').text(error);
22131 return this.unanticipatedError(response);
22136 UberView.prototype.autoUpdateModel = function(e) {
22137 var $el, arg, model, self, val;
22138 $el = $(e.currentTarget);
22141 if (val !== this.model.get($el.attr('id'))) {
22143 arg[$el.attr('id')] = $el.is(':checkbox') ? $el.is(':checked') ? 1 : 0 : val;
22144 $('.editable span').empty();
22145 this.model.set(arg);
22146 model = new this.model.__proto__.constructor({
22149 return model.save(arg, {
22150 complete: function(xhr) {
22151 var key, response, _i, _len, _ref, _results;
22152 response = JSON.parse(xhr.responseText);
22153 switch (xhr.status) {
22155 self.flash('success', 'Saved!');
22158 self.flash('error', 'That was not Uber.');
22159 _ref = _.keys(response);
22161 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
22163 _results.push($el.parent().find('span').html(response[key]));
22168 return self.unanticipatedError;
22174 UberView.prototype.unanticipatedError = function(response) {
22175 return self.flash('error', response);
22177 UberView.prototype.flash = function(type, text) {
22179 $banner = $("." + type);
22180 $banner.find('p').text(text).end().css('border', '1px solid #999').animate({
22183 return setTimeout(function() {
22184 return $banner.animate({
22185 top: -$banner.outerHeight()
22189 UberView.prototype.requireMaps = function(callback) {
22190 if (typeof google !== 'undefined' && google.maps) {
22193 return $.getScript("https://www.google.com/jsapi?key=" + CONFIG.googleJsApiKey, function() {
22194 return google.load('maps', 3, {
22195 callback: callback,
22196 other_params: 'sensor=false&language=en'
22201 UberView.prototype.select_drop_down = function(model, key) {
22203 value = model.get(key);
22205 return $("select[id='" + key + "'] option[value='" + value + "']").attr('selected', 'selected');
22208 UberView.prototype.processDocumentUpload = function(e) {
22209 var $fi, $form, arbData, curDate, data, expDate, expM, expY, expiration, fileElementId, invalid;
22210 e.preventDefault();
22211 $form = $(e.currentTarget);
22212 $fi = $("input[type=file]", $form);
22213 $(".validationError").removeClass("validationError");
22215 return $fi.addClass("validationError");
22217 fileElementId = $fi.attr('id');
22218 expY = $("select[name=expiration-year]", $form).val();
22219 expM = $("select[name=expiration-month]", $form).val();
22221 if (expY && expM) {
22222 expDate = new Date(expY, expM, 28);
22223 curDate = new Date();
22224 if (expDate < curDate) {
22226 $(".expiration", $form).addClass("validationError");
22228 expiration = "" + expY + "-" + expM + "-28T23:59:59Z";
22231 $(".arbitraryField", $form).each(__bind(function(i, e) {
22232 arbData[$(e).attr('name')] = $(e).val();
22233 if ($(e).val() === "") {
22235 return $(e).addClass("validationError");
22240 token: $.cookie('token') || USER.get('token'),
22241 name: $("input[name=fileName]", $form).val(),
22242 meta: escape(JSON.stringify(arbData)),
22243 user_id: $("input[name=driver_id]", $form).val(),
22244 vehicle_id: $("input[name=vehicle_id]", $form).val()
22247 data['expiration'] = expiration;
22249 $("#spinner").show();
22250 return $.ajaxFileUpload({
22251 url: '/api/documents',
22253 fileElementId: fileElementId,
22255 complete: __bind(function(resp, status) {
22256 var key, _i, _len, _ref, _results;
22257 $("#spinner").hide();
22258 if (status === "success") {
22260 this.model.refetch();
22265 if (status === "error") {
22266 _ref = _.keys(resp);
22268 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
22270 _results.push($("*[name=" + key + "]", $form).addClass("validationError"));
22282 }, "web-lib/views/footer": function(exports, require, module) {(function() {
22283 var footerTemplate;
22284 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
22285 for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
22286 function ctor() { this.constructor = child; }
22287 ctor.prototype = parent.prototype;
22288 child.prototype = new ctor;
22289 child.__super__ = parent.prototype;
22292 footerTemplate = require('web-lib/templates/footer');
22293 exports.SharedFooterView = (function() {
22294 __extends(SharedFooterView, Backbone.View);
22295 function SharedFooterView() {
22296 SharedFooterView.__super__.constructor.apply(this, arguments);
22298 SharedFooterView.prototype.id = 'footer_view';
22299 SharedFooterView.prototype.events = {
22300 'click .language': 'intl_set_cookie_locale'
22302 SharedFooterView.prototype.render = function() {
22303 $(this.el).html(footerTemplate());
22304 this.delegateEvents();
22307 SharedFooterView.prototype.intl_set_cookie_locale = function(e) {
22309 i18n.setLocale(e != null ? (_ref = e.srcElement) != null ? _ref.id : void 0 : void 0);
22310 return location.reload();
22312 return SharedFooterView;