PageSourceSearch

https://www.verkami.com/assets/main-3dfcb58d712e7cb417fc6040e77af32ce030ff685d844c0c9d0d650f7506a723.js

js verkami.com collected 2026-09-24 08:35:49 UTC 878,020 bytes, 24,929 lines download raw bytes

vendor: 4,698 bytes, lines 1-182
1/*!
2 * jQuery JavaScript Library v2.1.4
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: 2015-04-28T16:01Z
13 */
14
15(function( global, factory ) {
16
17  if ( typeof module === "object" && typeof module.exports === "object" ) {
18    // For CommonJS and CommonJS-like environments where a proper `window`
19    // is present, execute the factory and get jQuery.
20    // For environments that do not have a `window` with a `document`
21    // (such as Node.js), expose a factory as module.exports.
22    // This accentuates the need for the creation of a real `window`.
23    // e.g. var jQuery = require("jquery")(window);
24    // See ticket #14549 for more info.
25    module.exports = global.document ?
26      factory( global, true ) :
27      function( w ) {
28        if ( !w.document ) {
29          throw new Error( "jQuery requires a window with a document" );
30        }
31        return factory( w );
32      };
33  } else {
34    factory( global );
35  }
36
37// Pass this if window is not defined yet
38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
39
40// Support: Firefox 18+
41// Can't be in strict mode, several libs including ASP.NET trace
42// the stack via arguments.caller.callee and Firefox dies if
43// you try to trace through "use strict" call chains. (#13335)
44//
45
46var arr = [];
47
48var slice = arr.slice;
49
50var concat = arr.concat;
51
52var push = arr.push;
53
54var indexOf = arr.indexOf;
55
56var class2type = {};
57
58var toString = class2type.toString;
59
60var hasOwn = class2type.hasOwnProperty;
61
62var support = {};
63
64
65
66var
67  // Use the correct document accordingly with window argument (sandbox)
68  document = window.document,
69
70  version = "2.1.4",
71
72  // Define a local copy of jQuery
73  jQuery = function( selector, context ) {
74    // The jQuery object is actually just the init constructor 'enhanced'
75    // Need init if jQuery is called (just allow error to be thrown if not included)
76    return new jQuery.fn.init( selector, context );
77  },
78
79  // Support: Android<4.1
80  // Make sure we trim BOM and NBSP
81  rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
82
83  // Matches dashed string for camelizing
84  rmsPrefix = /^-ms-/,
85  rdashAlpha = /-([\da-z])/gi,
86
87  // Used by jQuery.camelCase as callback to replace()
88  fcamelCase = function( all, letter ) {
89    return letter.toUpperCase();
90  };
91
92jQuery.fn = jQuery.prototype = {
93  // The current version of jQuery being used
94  jquery: version,
95
96  constructor: jQuery,
97
98  // Start with an empty selector
99  selector: "",
100
101  // The default length of a jQuery object is 0
102  length: 0,
103
104  toArray: function() {
105    return slice.call( this );
106  },
107
108  // Get the Nth element in the matched element set OR
109  // Get the whole matched element set as a clean array
110  get: function( num ) {
111    return num != null ?
112
113      // Return just the one element from the set
114      ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
115
116      // Return all the elements in a clean array
117      slice.call( this );
118  },
119
120  // Take an array of elements and push it onto the stack
121  // (returning the new matched element set)
122  pushStack: function( elems ) {
123
124    // Build a new jQuery matched element set
125    var ret = jQuery.merge( this.constructor(), elems );
126
127    // Add the old object onto the stack (as a reference)
128    ret.prevObject = this;
129    ret.context = this.context;
130
131    // Return the newly-formed element set
132    return ret;
133  },
134
135  // Execute a callback for every element in the matched set.
136  // (You can seed the arguments with an array of args, but this is
137  // only used internally.)
138  each: function( callback, args ) {
139    return jQuery.each( this, callback, args );
140  },
141
142  map: function( callback ) {
143    return this.pushStack( jQuery.map(this, function( elem, i ) {
144      return callback.call( elem, i, elem );
145    }));
146  },
147
148  slice: function() {
149    return this.pushStack( slice.apply( this, arguments ) );
150  },
151
152  first: function() {
153    return this.eq( 0 );
154  },
155
156  last: function() {
157    return this.eq( -1 );
158  },
159
160  eq: function( i ) {
161    var len = this.length,
162      j = +i + ( i < 0 ? len : 0 );
163    return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
164  },
165
166  end: function() {
167    return this.prevObject || this.constructor(null);
168  },
169
170  // For internal use only.
171  // Behaves like an Array's method, not like a jQuery method.
172  push: push,
173  sort: arr.sort,
174  splice: arr.splice
175};
176
177jQuery.extend = jQuery.fn.extend = function() {
178  var options, name, src, copy, copyIsArray, clone,
179    target = arguments[0] || {},
180    i = 1,
181    length = arguments.length,
182    deep = false;
183
184  // Handle a deep copy situation
185  if ( typeof target === "boolean" ) {
186    deep = target;
187
188    // Skip the boolean and the target
189    target = arguments[ i ] || {};
190    i++;
191  }
192
193  // Handle case when target is a string or something (possible in deep copy)
194  if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
195    target = {};
196  }
197
198  // Extend jQuery itself if only one argument is passed
199  if ( i === length ) {
200    target = this;
201    i--;
202  }
203
204  for ( ; i < length; i++ ) {
205    // Only deal with non-null/undefined values
206    if ( (options = arguments[ i ]) != null ) {
207      // Extend the base object
208      for ( name in options ) {
209        src = target[ name ];
210        copy = options[ name ];
211
212        // Prevent never-ending loop
213        if ( target === copy ) {
214          continue;
215        }
216
217        // Recurse if we're merging plain objects or arrays
218        if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
219          if ( copyIsArray ) {
220            copyIsArray = false;
221            clone = src && jQuery.isArray(src) ? src : [];
222
223          } else {
224            clone = src && jQuery.isPlainObject(src) ? src : {};
225          }
226
227          // Never move original objects, clone them
228          target[ name ] = jQuery.extend( deep, clone, copy );
229
230        // Don't bring in undefined values
231        } else if ( copy !== undefined ) {
232          target[ name ] = copy;
233        }
234      }
235    }
236  }
237
238  // Return the modified object
239  return target;
240};
241
242jQuery.extend({
243  // Unique for each copy of jQuery on the page
244  expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
245
246  // Assume jQuery is ready without the ready module
247  isReady: true,
248
249  error: function( msg ) {
250    throw new Error( msg );
251  },
252
253  noop: function() {},
254
255  isFunction: function( obj ) {
256    return jQuery.type(obj) === "function";
257  },
258
259  isArray: Array.isArray,
260
261  isWindow: function( obj ) {
262    return obj != null && obj === obj.window;
263  },
264
265  isNumeric: function( obj ) {
266    // parseFloat NaNs numeric-cast false positives (null|true|false|"")
267    // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
268    // subtraction forces infinities to NaN
269    // adding 1 corrects loss of precision from parseFloat (#15100)
270    return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
271  },
272
273  isPlainObject: function( obj ) {
274    // Not plain objects:
275    // - Any object or value whose internal [[Class]] property is not "[object Object]"
276    // - DOM nodes
277    // - window
278    if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
279      return false;
280    }
281
282    if ( obj.constructor &&
283        !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
284      return false;
285    }
286
287    // If the function hasn't returned already, we're confident that
288    // |obj| is a plain object, created by {} or constructed with new Object
289    return true;
290  },
291
292  isEmptyObject: function( obj ) {
293    var name;
294    for ( name in obj ) {
295      return false;
296    }
297    return true;
298  },
299
300  type: function( obj ) {
301    if ( obj == null ) {
302      return obj + "";
303    }
304    // Support: Android<4.0, iOS<6 (functionish RegExp)
305    return typeof obj === "object" || typeof obj === "function" ?
306      class2type[ toString.call(obj) ] || "object" :
307      typeof obj;
308  },
309
310  // Evaluates a script in a global context
311  globalEval: function( code ) {
312    var script,
313      indirect = eval;
314
315    code = jQuery.trim( code );
316
317    if ( code ) {
318      // If the code includes a valid, prologue position
319      // strict mode pragma, execute code by injecting a
320      // script tag into the document.
321      if ( code.indexOf("use strict") === 1 ) {
322        script = document.createElement("script");
323        script.text = code;
324        document.head.appendChild( script ).parentNode.removeChild( script );
325      } else {
326      // Otherwise, avoid the DOM node creation, insertion
327      // and removal by using an indirect global eval
328        indirect( code );
329      }
330    }
331  },
332
333  // Convert dashed to camelCase; used by the css and data modules
334  // Support: IE9-11+
335  // Microsoft forgot to hump their vendor prefix (#9572)
336  camelCase: function( string ) {
337    return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
338  },
339
340  nodeName: function( elem, name ) {
341    return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
342  },
343
344  // args is for internal usage only
345  each: function( obj, callback, args ) {
346    var value,
347      i = 0,
348      length = obj.length,
349      isArray = isArraylike( obj );
350
351    if ( args ) {
352      if ( isArray ) {
353        for ( ; i < length; i++ ) {
354          value = callback.apply( obj[ i ], args );
355
356          if ( value === false ) {
357            break;
358          }
359        }
360      } else {
361        for ( i in obj ) {
362          value = callback.apply( obj[ i ], args );
363
364          if ( value === false ) {
365            break;
366          }
367        }
368      }
369
370    // A special, fast, case for the most common use of each
371    } else {
372      if ( isArray ) {
373        for ( ; i < length; i++ ) {
374          value = callback.call( obj[ i ], i, obj[ i ] );
375
376          if ( value === false ) {
377            break;
378          }
379        }
380      } else {
381        for ( i in obj ) {
382          value = callback.call( obj[ i ], i, obj[ i ] );
383
384          if ( value === false ) {
385            break;
386          }
387        }
388      }
389    }
390
391    return obj;
392  },
393
394  // Support: Android<4.1
395  trim: function( text ) {
396    return text == null ?
397      "" :
398      ( text + "" ).replace( rtrim, "" );
399  },
400
401  // results is for internal usage only
402  makeArray: function( arr, results ) {
403    var ret = results || [];
404
405    if ( arr != null ) {
406      if ( isArraylike( Object(arr) ) ) {
407        jQuery.merge( ret,
408          typeof arr === "string" ?
409          [ arr ] : arr
410        );
411      } else {
412        push.call( ret, arr );
413      }
414    }
415
416    return ret;
417  },
418
419  inArray: function( elem, arr, i ) {
420    return arr == null ? -1 : indexOf.call( arr, elem, i );
421  },
422
423  merge: function( first, second ) {
424    var len = +second.length,
425      j = 0,
426      i = first.length;
427
428    for ( ; j < len; j++ ) {
429      first[ i++ ] = second[ j ];
430    }
431
432    first.length = i;
433
434    return first;
435  },
436
437  grep: function( elems, callback, invert ) {
438    var callbackInverse,
439      matches = [],
440      i = 0,
441      length = elems.length,
442      callbackExpect = !invert;
443
444    // Go through the array, only saving the items
445    // that pass the validator function
446    for ( ; i < length; i++ ) {
447      callbackInverse = !callback( elems[ i ], i );
448      if ( callbackInverse !== callbackExpect ) {
449        matches.push( elems[ i ] );
450      }
451    }
452
453    return matches;
454  },
455
456  // arg is for internal usage only
457  map: function( elems, callback, arg ) {
458    var value,
459      i = 0,
460      length = elems.length,
461      isArray = isArraylike( elems ),
462      ret = [];
463
464    // Go through the array, translating each of the items to their new values
465    if ( isArray ) {
466      for ( ; i < length; i++ ) {
467        value = callback( elems[ i ], i, arg );
468
469        if ( value != null ) {
470          ret.push( value );
471        }
472      }
473
474    // Go through every key on the object,
475    } else {
476      for ( i in elems ) {
477        value = callback( elems[ i ], i, arg );
478
479        if ( value != null ) {
480          ret.push( value );
481        }
482      }
483    }
484
485    // Flatten any nested arrays
486    return concat.apply( [], ret );
487  },
488
489  // A global GUID counter for objects
490  guid: 1,
491
492  // Bind a function to a context, optionally partially applying any
493  // arguments.
494  proxy: function( fn, context ) {
495    var tmp, args, proxy;
496
497    if ( typeof context === "string" ) {
498      tmp = fn[ context ];
499      context = fn;
500      fn = tmp;
501    }
502
503    // Quick check to determine if target is callable, in the spec
504    // this throws a TypeError, but we will just return undefined.
505    if ( !jQuery.isFunction( fn ) ) {
506      return undefined;
507    }
508
509    // Simulated bind
510    args = slice.call( arguments, 2 );
511    proxy = function() {
512      return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
513    };
514
515    // Set the guid of unique handler to the same of original handler, so it can be removed
516    proxy.guid = fn.guid = fn.guid || jQuery.guid++;
517
518    return proxy;
519  },
520
521  now: Date.now,
522
523  // jQuery.support is not used in Core but other projects attach their
524  // properties to it so it needs to exist.
525  support: support
526});
527
528// Populate the class2type map
529jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
530  class2type[ "[object " + name + "]" ] = name.toLowerCase();
531});
532
533function isArraylike( obj ) {
534
vendor: 5,493 bytes, lines 535-701
535  // Support: iOS 8.2 (not reproducible in simulator)
536  // `in` check used to prevent JIT error (gh-2145)
537  // hasOwn isn't used here due to false negatives
538  // regarding Nodelist length in IE
539  var length = "length" in obj && obj.length,
540    type = jQuery.type( obj );
541
542  if ( type === "function" || jQuery.isWindow( obj ) ) {
543    return false;
544  }
545
546  if ( obj.nodeType === 1 && length ) {
547    return true;
548  }
549
550  return type === "array" || length === 0 ||
551    typeof length === "number" && length > 0 && ( length - 1 ) in obj;
552}
553var Sizzle =
554/*!
555 * Sizzle CSS Selector Engine v2.2.0-pre
556 * http://sizzlejs.com/
557 *
558 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
559 * Released under the MIT license
560 * http://jquery.org/license
561 *
562 * Date: 2014-12-16
563 */
564(function( window ) {
565
566var i,
567  support,
568  Expr,
569  getText,
570  isXML,
571  tokenize,
572  compile,
573  select,
574  outermostContext,
575  sortInput,
576  hasDuplicate,
577
578  // Local document vars
579  setDocument,
580  document,
581  docElem,
582  documentIsHTML,
583  rbuggyQSA,
584  rbuggyMatches,
585  matches,
586  contains,
587
588  // Instance-specific data
589  expando = "sizzle" + 1 * new Date(),
590  preferredDoc = window.document,
591  dirruns = 0,
592  done = 0,
593  classCache = createCache(),
594  tokenCache = createCache(),
595  compilerCache = createCache(),
596  sortOrder = function( a, b ) {
597    if ( a === b ) {
598      hasDuplicate = true;
599    }
600    return 0;
601  },
602
603  // General-purpose constants
604  MAX_NEGATIVE = 1 << 31,
605
606  // Instance methods
607  hasOwn = ({}).hasOwnProperty,
608  arr = [],
609  pop = arr.pop,
610  push_native = arr.push,
611  push = arr.push,
612  slice = arr.slice,
613  // Use a stripped-down indexOf as it's faster than native
614  // http://jsperf.com/thor-indexof-vs-for/5
615  indexOf = function( list, elem ) {
616    var i = 0,
617      len = list.length;
618    for ( ; i < len; i++ ) {
619      if ( list[i] === elem ) {
620        return i;
621      }
622    }
623    return -1;
624  },
625
626  booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
627
628  // Regular expressions
629
630  // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
631  whitespace = "[\\x20\\t\\r\\n\\f]",
632  // http://www.w3.org/TR/css3-syntax/#characters
633  characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
634
635  // Loosely modeled on CSS identifier characters
636  // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
637  // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
638  identifier = characterEncoding.replace( "w", "w#" ),
639
640  // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
641  attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
642    // Operator (capture 2)
643    "*([*^$|!~]?=)" + whitespace +
644    // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
645    "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
646    "*\\]",
647
648  pseudos = ":(" + characterEncoding + ")(?:\\((" +
649    // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
650    // 1. quoted (capture 3; capture 4 or capture 5)
651    "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
652    // 2. simple (capture 6)
653    "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
654    // 3. anything else (capture 2)
655    ".*" +
656    ")\\)|)",
657
658  // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
659  rwhitespace = new RegExp( whitespace + "+", "g" ),
660  rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
661
662  rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
663  rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
664
665  rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
666
667  rpseudo = new RegExp( pseudos ),
668  ridentifier = new RegExp( "^" + identifier + "$" ),
669
670  matchExpr = {
671    "ID": new RegExp( "^#(" + characterEncoding + ")" ),
672    "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
673    "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
674    "ATTR": new RegExp( "^" + attributes ),
675    "PSEUDO": new RegExp( "^" + pseudos ),
676    "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
677      "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
678      "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
679    "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
680    // For use in libraries implementing .is()
681    // We use this for POS matching in `select`
682    "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
683      whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
684  },
685
686  rinputs = /^(?:input|select|textarea|button)$/i,
687  rheader = /^h\d$/i,
688
689  rnative = /^[^{]+\{\s*\[native \w/,
690
691  // Easily-parseable/retrievable ID or TAG or CLASS selectors
692  rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
693
694  rsibling = /[+~]/,
695  rescape = /'|\\/g,
696
697  // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
698  runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
699  funescape = function( _, escaped, escapedWhitespace ) {
700    var high = "0x" + escaped - 0x10000;
701    // NaN means non-codepoint
702    // Support: Firefox<24
703    // Workaround erroneous numeric interpretation of +"0x"
704    return high !== high || escapedWhitespace ?
705      escaped :
706      high < 0 ?
707        // BMP codepoint
708        String.fromCharCode( high + 0x10000 ) :
709        // Supplemental Plane codepoint (surrogate pair)
710        String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
711  },
712
713  // Used for iframes
714  // See setDocument()
715  // Removing the function wrapper causes a "Permission Denied"
716  // error in IE
717  unloadHandler = function() {
718    setDocument();
719  };
720
721// Optimize for push.apply( _, NodeList )
722try {
723  push.apply(
724    (arr = slice.call( preferredDoc.childNodes )),
725    preferredDoc.childNodes
726  );
727  // Support: Android<4.0
728  // Detect silently failing push.apply
729  arr[ preferredDoc.childNodes.length ].nodeType;
730} catch ( e ) {
731  push = { apply: arr.length ?
732
733    // Leverage slice if possible
734    function( target, els ) {
735      push_native.apply( target, slice.call(els) );
736    } :
737
738    // Support: IE<9
739    // Otherwise append directly
740    function( target, els ) {
741      var j = target.length,
742        i = 0;
743      // Can't trust NodeList.length
744      while ( (target[j++] = els[i++]) ) {}
745      target.length = j - 1;
746    }
747  };
748}
749
750function Sizzle( selector, context, results, seed ) {
751  var match, elem, m, nodeType,
752    // QSA vars
753    i, groups, old, nid, newContext, newSelector;
754
755  if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
756    setDocument( context );
757  }
758
759  context = context || document;
760  results = results || [];
761  nodeType = context.nodeType;
762
763  if ( typeof selector !== "string" || !selector ||
764    nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
765
766    return results;
767  }
768
769  if ( !seed && documentIsHTML ) {
770
771    // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
772    if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
773      // Speed-up: Sizzle("#ID")
774      if ( (m = match[1]) ) {
775        if ( nodeType === 9 ) {
776          elem = context.getElementById( m );
777          // Check parentNode to catch when Blackberry 4.6 returns
778          // nodes that are no longer in the document (jQuery #6963)
779          if ( elem && elem.parentNode ) {
780            // Handle the case where IE, Opera, and Webkit return items
781            // by name instead of ID
782            if ( elem.id === m ) {
783              results.push( elem );
784              return results;
785            }
786          } else {
787            return results;
788          }
789        } else {
790          // Context is not a document
791          if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
792            contains( context, elem ) && elem.id === m ) {
793            results.push( elem );
794            return results;
795          }
796        }
797
798      // Speed-up: Sizzle("TAG")
799      } else if ( match[2] ) {
800        push.apply( results, context.getElementsByTagName( selector ) );
801        return results;
802
803      // Speed-up: Sizzle(".CLASS")
804      } else if ( (m = match[3]) && support.getElementsByClassName ) {
805        push.apply( results, context.getElementsByClassName( m ) );
806        return results;
807      }
808    }
809
810    // QSA path
811    if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
812      nid = old = expando;
813      newContext = context;
814      newSelector = nodeType !== 1 && selector;
815
816      // qSA works strangely on Element-rooted queries
817      // We can work around this by specifying an extra ID on the root
818      // and working up from there (Thanks to Andrew Dupont for the technique)
819      // IE 8 doesn't work on object elements
820      if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
821        groups = tokenize( selector );
822
823        if ( (old = context.getAttribute("id")) ) {
824          nid = old.replace( rescape, "\\$&" );
825        } else {
826          context.setAttribute( "id", nid );
827        }
828        nid = "[id='" + nid + "'] ";
829
830        i = groups.length;
831        while ( i-- ) {
832          groups[i] = nid + toSelector( groups[i] );
833        }
vendor: 56,408 bytes, lines 834-2684
834        newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
835        newSelector = groups.join(",");
836      }
837
838      if ( newSelector ) {
839        try {
840          push.apply( results,
841            newContext.querySelectorAll( newSelector )
842          );
843          return results;
844        } catch(qsaError) {
845        } finally {
846          if ( !old ) {
847            context.removeAttribute("id");
848          }
849        }
850      }
851    }
852  }
853
854  // All others
855  return select( selector.replace( rtrim, "$1" ), context, results, seed );
856}
857
858/**
859 * Create key-value caches of limited size
860 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
861 *  property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
862 *  deleting the oldest entry
863 */
864function createCache() {
865  var keys = [];
866
867  function cache( key, value ) {
868    // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
869    if ( keys.push( key + " " ) > Expr.cacheLength ) {
870      // Only keep the most recent entries
871      delete cache[ keys.shift() ];
872    }
873    return (cache[ key + " " ] = value);
874  }
875  return cache;
876}
877
878/**
879 * Mark a function for special use by Sizzle
880 * @param {Function} fn The function to mark
881 */
882function markFunction( fn ) {
883  fn[ expando ] = true;
884  return fn;
885}
886
887/**
888 * Support testing using an element
889 * @param {Function} fn Passed the created div and expects a boolean result
890 */
891function assert( fn ) {
892  var div = document.createElement("div");
893
894  try {
895    return !!fn( div );
896  } catch (e) {
897    return false;
898  } finally {
899    // Remove from its parent by default
900    if ( div.parentNode ) {
901      div.parentNode.removeChild( div );
902    }
903    // release memory in IE
904    div = null;
905  }
906}
907
908/**
909 * Adds the same handler for all of the specified attrs
910 * @param {String} attrs Pipe-separated list of attributes
911 * @param {Function} handler The method that will be applied
912 */
913function addHandle( attrs, handler ) {
914  var arr = attrs.split("|"),
915    i = attrs.length;
916
917  while ( i-- ) {
918    Expr.attrHandle[ arr[i] ] = handler;
919  }
920}
921
922/**
923 * Checks document order of two siblings
924 * @param {Element} a
925 * @param {Element} b
926 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
927 */
928function siblingCheck( a, b ) {
929  var cur = b && a,
930    diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
931      ( ~b.sourceIndex || MAX_NEGATIVE ) -
932      ( ~a.sourceIndex || MAX_NEGATIVE );
933
934  // Use IE sourceIndex if available on both nodes
935  if ( diff ) {
936    return diff;
937  }
938
939  // Check if b follows a
940  if ( cur ) {
941    while ( (cur = cur.nextSibling) ) {
942      if ( cur === b ) {
943        return -1;
944      }
945    }
946  }
947
948  return a ? 1 : -1;
949}
950
951/**
952 * Returns a function to use in pseudos for input types
953 * @param {String} type
954 */
955function createInputPseudo( type ) {
956  return function( elem ) {
957    var name = elem.nodeName.toLowerCase();
958    return name === "input" && elem.type === type;
959  };
960}
961
962/**
963 * Returns a function to use in pseudos for buttons
964 * @param {String} type
965 */
966function createButtonPseudo( type ) {
967  return function( elem ) {
968    var name = elem.nodeName.toLowerCase();
969    return (name === "input" || name === "button") && elem.type === type;
970  };
971}
972
973/**
974 * Returns a function to use in pseudos for positionals
975 * @param {Function} fn
976 */
977function createPositionalPseudo( fn ) {
978  return markFunction(function( argument ) {
979    argument = +argument;
980    return markFunction(function( seed, matches ) {
981      var j,
982        matchIndexes = fn( [], seed.length, argument ),
983        i = matchIndexes.length;
984
985      // Match elements found at the specified indexes
986      while ( i-- ) {
987        if ( seed[ (j = matchIndexes[i]) ] ) {
988          seed[j] = !(matches[j] = seed[j]);
989        }
990      }
991    });
992  });
993}
994
995/**
996 * Checks a node for validity as a Sizzle context
997 * @param {Element|Object=} context
998 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
999 */
1000function testContext( context ) {
1001  return context && typeof context.getElementsByTagName !== "undefined" && context;
1002}
1003
1004// Expose support vars for convenience
1005support = Sizzle.support = {};
1006
1007/**
1008 * Detects XML nodes
1009 * @param {Element|Object} elem An element or a document
1010 * @returns {Boolean} True iff elem is a non-HTML XML node
1011 */
1012isXML = Sizzle.isXML = function( elem ) {
1013  // documentElement is verified for cases where it doesn't yet exist
1014  // (such as loading iframes in IE - #4833)
1015  var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1016  return documentElement ? documentElement.nodeName !== "HTML" : false;
1017};
1018
1019/**
1020 * Sets document-related variables once based on the current document
1021 * @param {Element|Object} [doc] An element or document object to use to set the document
1022 * @returns {Object} Returns the current document
1023 */
1024setDocument = Sizzle.setDocument = function( node ) {
1025  var hasCompare, parent,
1026    doc = node ? node.ownerDocument || node : preferredDoc;
1027
1028  // If no document and documentElement is available, return
1029  if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1030    return document;
1031  }
1032
1033  // Set our document
1034  document = doc;
1035  docElem = doc.documentElement;
1036  parent = doc.defaultView;
1037
1038  // Support: IE>8
1039  // If iframe document is assigned to "document" variable and if iframe has been reloaded,
1040  // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1041  // IE6-8 do not support the defaultView property so parent will be undefined
1042  if ( parent && parent !== parent.top ) {
1043    // IE11 does not have attachEvent, so all must suffer
1044    if ( parent.addEventListener ) {
1045      parent.addEventListener( "unload", unloadHandler, false );
1046    } else if ( parent.attachEvent ) {
1047      parent.attachEvent( "onunload", unloadHandler );
1048    }
1049  }
1050
1051  /* Support tests
1052  ---------------------------------------------------------------------- */
1053  documentIsHTML = !isXML( doc );
1054
1055  /* Attributes
1056  ---------------------------------------------------------------------- */
1057
1058  // Support: IE<8
1059  // Verify that getAttribute really returns attributes and not properties
1060  // (excepting IE8 booleans)
1061  support.attributes = assert(function( div ) {
1062    div.className = "i";
1063    return !div.getAttribute("className");
1064  });
1065
1066  /* getElement(s)By*
1067  ---------------------------------------------------------------------- */
1068
1069  // Check if getElementsByTagName("*") returns only elements
1070  support.getElementsByTagName = assert(function( div ) {
1071    div.appendChild( doc.createComment("") );
1072    return !div.getElementsByTagName("*").length;
1073  });
1074
1075  // Support: IE<9
1076  support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
1077
1078  // Support: IE<10
1079  // Check if getElementById returns elements by name
1080  // The broken getElementById methods don't pick up programatically-set names,
1081  // so use a roundabout getElementsByName test
1082  support.getById = assert(function( div ) {
1083    docElem.appendChild( div ).id = expando;
1084    return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1085  });
1086
1087  // ID find and filter
1088  if ( support.getById ) {
1089    Expr.find["ID"] = function( id, context ) {
1090      if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1091        var m = context.getElementById( id );
1092        // Check parentNode to catch when Blackberry 4.6 returns
1093        // nodes that are no longer in the document #6963
1094        return m && m.parentNode ? [ m ] : [];
1095      }
1096    };
1097    Expr.filter["ID"] = function( id ) {
1098      var attrId = id.replace( runescape, funescape );
1099      return function( elem ) {
1100        return elem.getAttribute("id") === attrId;
1101      };
1102    };
1103  } else {
1104    // Support: IE6/7
1105    // getElementById is not reliable as a find shortcut
1106    delete Expr.find["ID"];
1107
1108    Expr.filter["ID"] =  function( id ) {
1109      var attrId = id.replace( runescape, funescape );
1110      return function( elem ) {
1111        var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
1112        return node && node.value === attrId;
1113      };
1114    };
1115  }
1116
1117  // Tag
1118  Expr.find["TAG"] = support.getElementsByTagName ?
1119    function( tag, context ) {
1120      if ( typeof context.getElementsByTagName !== "undefined" ) {
1121        return context.getElementsByTagName( tag );
1122
1123      // DocumentFragment nodes don't have gEBTN
1124      } else if ( support.qsa ) {
1125        return context.querySelectorAll( tag );
1126      }
1127    } :
1128
1129    function( tag, context ) {
1130      var elem,
1131        tmp = [],
1132        i = 0,
1133        // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1134        results = context.getElementsByTagName( tag );
1135
1136      // Filter out possible comments
1137      if ( tag === "*" ) {
1138        while ( (elem = results[i++]) ) {
1139          if ( elem.nodeType === 1 ) {
1140            tmp.push( elem );
1141          }
1142        }
1143
1144        return tmp;
1145      }
1146      return results;
1147    };
1148
1149  // Class
1150  Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1151    if ( documentIsHTML ) {
1152      return context.getElementsByClassName( className );
1153    }
1154  };
1155
1156  /* QSA/matchesSelector
1157  ---------------------------------------------------------------------- */
1158
1159  // QSA and matchesSelector support
1160
1161  // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1162  rbuggyMatches = [];
1163
1164  // qSa(:focus) reports false when true (Chrome 21)
1165  // We allow this because of a bug in IE8/9 that throws an error
1166  // whenever `document.activeElement` is accessed on an iframe
1167  // So, we allow :focus to pass through QSA all the time to avoid the IE error
1168  // See http://bugs.jquery.com/ticket/13378
1169  rbuggyQSA = [];
1170
1171  if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1172    // Build QSA regex
1173    // Regex strategy adopted from Diego Perini
1174    assert(function( div ) {
1175      // Select is set to empty string on purpose
1176      // This is to test IE's treatment of not explicitly
1177      // setting a boolean content attribute,
1178      // since its presence should be enough
1179      // http://bugs.jquery.com/ticket/12359
1180      docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
1181        "<select id='" + expando + "-\f]' msallowcapture=''>" +
1182        "<option selected=''></option></select>";
1183
1184      // Support: IE8, Opera 11-12.16
1185      // Nothing should be selected when empty strings follow ^= or $= or *=
1186      // The test attribute must be unknown in Opera but "safe" for WinRT
1187      // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1188      if ( div.querySelectorAll("[msallowcapture^='']").length ) {
1189        rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1190      }
1191
1192      // Support: IE8
1193      // Boolean attributes and "value" are not treated correctly
1194      if ( !div.querySelectorAll("[selected]").length ) {
1195        rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1196      }
1197
1198      // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
1199      if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1200        rbuggyQSA.push("~=");
1201      }
1202
1203      // Webkit/Opera - :checked should return selected option elements
1204      // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1205      // IE8 throws error here and will not see later tests
1206      if ( !div.querySelectorAll(":checked").length ) {
1207        rbuggyQSA.push(":checked");
1208      }
1209
1210      // Support: Safari 8+, iOS 8+
1211      // https://bugs.webkit.org/show_bug.cgi?id=136851
1212      // In-page `selector#id sibing-combinator selector` fails
1213      if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
1214        rbuggyQSA.push(".#.+[+~]");
1215      }
1216    });
1217
1218    assert(function( div ) {
1219      // Support: Windows 8 Native Apps
1220      // The type and name attributes are restricted during .innerHTML assignment
1221      var input = doc.createElement("input");
1222      input.setAttribute( "type", "hidden" );
1223      div.appendChild( input ).setAttribute( "name", "D" );
1224
1225      // Support: IE8
1226      // Enforce case-sensitivity of name attribute
1227      if ( div.querySelectorAll("[name=d]").length ) {
1228        rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1229      }
1230
1231      // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1232      // IE8 throws error here and will not see later tests
1233      if ( !div.querySelectorAll(":enabled").length ) {
1234        rbuggyQSA.push( ":enabled", ":disabled" );
1235      }
1236
1237      // Opera 10-11 does not throw on post-comma invalid pseudos
1238      div.querySelectorAll("*,:x");
1239      rbuggyQSA.push(",.*:");
1240    });
1241  }
1242
1243  if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1244    docElem.webkitMatchesSelector ||
1245    docElem.mozMatchesSelector ||
1246    docElem.oMatchesSelector ||
1247    docElem.msMatchesSelector) )) ) {
1248
1249    assert(function( div ) {
1250      // Check to see if it's possible to do matchesSelector
1251      // on a disconnected node (IE 9)
1252      support.disconnectedMatch = matches.call( div, "div" );
1253
1254      // This should fail with an exception
1255      // Gecko does not error, returns false instead
1256      matches.call( div, "[s!='']:x" );
1257      rbuggyMatches.push( "!=", pseudos );
1258    });
1259  }
1260
1261  rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1262  rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1263
1264  /* Contains
1265  ---------------------------------------------------------------------- */
1266  hasCompare = rnative.test( docElem.compareDocumentPosition );
1267
1268  // Element contains another
1269  // Purposefully does not implement inclusive descendent
1270  // As in, an element does not contain itself
1271  contains = hasCompare || rnative.test( docElem.contains ) ?
1272    function( a, b ) {
1273      var adown = a.nodeType === 9 ? a.documentElement : a,
1274        bup = b && b.parentNode;
1275      return a === bup || !!( bup && bup.nodeType === 1 && (
1276        adown.contains ?
1277          adown.contains( bup ) :
1278          a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1279      ));
1280    } :
1281    function( a, b ) {
1282      if ( b ) {
1283        while ( (b = b.parentNode) ) {
1284          if ( b === a ) {
1285            return true;
1286          }
1287        }
1288      }
1289      return false;
1290    };
1291
1292  /* Sorting
1293  ---------------------------------------------------------------------- */
1294
1295  // Document order sorting
1296  sortOrder = hasCompare ?
1297  function( a, b ) {
1298
1299    // Flag for duplicate removal
1300    if ( a === b ) {
1301      hasDuplicate = true;
1302      return 0;
1303    }
1304
1305    // Sort on method existence if only one input has compareDocumentPosition
1306    var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1307    if ( compare ) {
1308      return compare;
1309    }
1310
1311    // Calculate position if both inputs belong to the same document
1312    compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1313      a.compareDocumentPosition( b ) :
1314
1315      // Otherwise we know they are disconnected
1316      1;
1317
1318    // Disconnected nodes
1319    if ( compare & 1 ||
1320      (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1321
1322      // Choose the first element that is related to our preferred document
1323      if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1324        return -1;
1325      }
1326      if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1327        return 1;
1328      }
1329
1330      // Maintain original order
1331      return sortInput ?
1332        ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1333        0;
1334    }
1335
1336    return compare & 4 ? -1 : 1;
1337  } :
1338  function( a, b ) {
1339    // Exit early if the nodes are identical
1340    if ( a === b ) {
1341      hasDuplicate = true;
1342      return 0;
1343    }
1344
1345    var cur,
1346      i = 0,
1347      aup = a.parentNode,
1348      bup = b.parentNode,
1349      ap = [ a ],
1350      bp = [ b ];
1351
1352    // Parentless nodes are either documents or disconnected
1353    if ( !aup || !bup ) {
1354      return a === doc ? -1 :
1355        b === doc ? 1 :
1356        aup ? -1 :
1357        bup ? 1 :
1358        sortInput ?
1359        ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1360        0;
1361
1362    // If the nodes are siblings, we can do a quick check
1363    } else if ( aup === bup ) {
1364      return siblingCheck( a, b );
1365    }
1366
1367    // Otherwise we need full lists of their ancestors for comparison
1368    cur = a;
1369    while ( (cur = cur.parentNode) ) {
1370      ap.unshift( cur );
1371    }
1372    cur = b;
1373    while ( (cur = cur.parentNode) ) {
1374      bp.unshift( cur );
1375    }
1376
1377    // Walk down the tree looking for a discrepancy
1378    while ( ap[i] === bp[i] ) {
1379      i++;
1380    }
1381
1382    return i ?
1383      // Do a sibling check if the nodes have a common ancestor
1384      siblingCheck( ap[i], bp[i] ) :
1385
1386      // Otherwise nodes in our document sort first
1387      ap[i] === preferredDoc ? -1 :
1388      bp[i] === preferredDoc ? 1 :
1389      0;
1390  };
1391
1392  return doc;
1393};
1394
1395Sizzle.matches = function( expr, elements ) {
1396  return Sizzle( expr, null, null, elements );
1397};
1398
1399Sizzle.matchesSelector = function( elem, expr ) {
1400  // Set document vars if needed
1401  if ( ( elem.ownerDocument || elem ) !== document ) {
1402    setDocument( elem );
1403  }
1404
1405  // Make sure that attribute selectors are quoted
1406  expr = expr.replace( rattributeQuotes, "='$1']" );
1407
1408  if ( support.matchesSelector && documentIsHTML &&
1409    ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1410    ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
1411
1412    try {
1413      var ret = matches.call( elem, expr );
1414
1415      // IE 9's matchesSelector returns false on disconnected nodes
1416      if ( ret || support.disconnectedMatch ||
1417          // As well, disconnected nodes are said to be in a document
1418          // fragment in IE 9
1419          elem.document && elem.document.nodeType !== 11 ) {
1420        return ret;
1421      }
1422    } catch (e) {}
1423  }
1424
1425  return Sizzle( expr, document, null, [ elem ] ).length > 0;
1426};
1427
1428Sizzle.contains = function( context, elem ) {
1429  // Set document vars if needed
1430  if ( ( context.ownerDocument || context ) !== document ) {
1431    setDocument( context );
1432  }
1433  return contains( context, elem );
1434};
1435
1436Sizzle.attr = function( elem, name ) {
1437  // Set document vars if needed
1438  if ( ( elem.ownerDocument || elem ) !== document ) {
1439    setDocument( elem );
1440  }
1441
1442  var fn = Expr.attrHandle[ name.toLowerCase() ],
1443    // Don't get fooled by Object.prototype properties (jQuery #13807)
1444    val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1445      fn( elem, name, !documentIsHTML ) :
1446      undefined;
1447
1448  return val !== undefined ?
1449    val :
1450    support.attributes || !documentIsHTML ?
1451      elem.getAttribute( name ) :
1452      (val = elem.getAttributeNode(name)) && val.specified ?
1453        val.value :
1454        null;
1455};
1456
1457Sizzle.error = function( msg ) {
1458  throw new Error( "Syntax error, unrecognized expression: " + msg );
1459};
1460
1461/**
1462 * Document sorting and removing duplicates
1463 * @param {ArrayLike} results
1464 */
1465Sizzle.uniqueSort = function( results ) {
1466  var elem,
1467    duplicates = [],
1468    j = 0,
1469    i = 0;
1470
1471  // Unless we *know* we can detect duplicates, assume their presence
1472  hasDuplicate = !support.detectDuplicates;
1473  sortInput = !support.sortStable && results.slice( 0 );
1474  results.sort( sortOrder );
1475
1476  if ( hasDuplicate ) {
1477    while ( (elem = results[i++]) ) {
1478      if ( elem === results[ i ] ) {
1479        j = duplicates.push( i );
1480      }
1481    }
1482    while ( j-- ) {
1483      results.splice( duplicates[ j ], 1 );
1484    }
1485  }
1486
1487  // Clear input after sorting to release objects
1488  // See https://github.com/jquery/sizzle/pull/225
1489  sortInput = null;
1490
1491  return results;
1492};
1493
1494/**
1495 * Utility function for retrieving the text value of an array of DOM nodes
1496 * @param {Array|Element} elem
1497 */
1498getText = Sizzle.getText = function( elem ) {
1499  var node,
1500    ret = "",
1501    i = 0,
1502    nodeType = elem.nodeType;
1503
1504  if ( !nodeType ) {
1505    // If no nodeType, this is expected to be an array
1506    while ( (node = elem[i++]) ) {
1507      // Do not traverse comment nodes
1508      ret += getText( node );
1509    }
1510  } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1511    // Use textContent for elements
1512    // innerText usage removed for consistency of new lines (jQuery #11153)
1513    if ( typeof elem.textContent === "string" ) {
1514      return elem.textContent;
1515    } else {
1516      // Traverse its children
1517      for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1518        ret += getText( elem );
1519      }
1520    }
1521  } else if ( nodeType === 3 || nodeType === 4 ) {
1522    return elem.nodeValue;
1523  }
1524  // Do not include comment or processing instruction nodes
1525
1526  return ret;
1527};
1528
1529Expr = Sizzle.selectors = {
1530
1531  // Can be adjusted by the user
1532  cacheLength: 50,
1533
1534  createPseudo: markFunction,
1535
1536  match: matchExpr,
1537
1538  attrHandle: {},
1539
1540  find: {},
1541
1542  relative: {
1543    ">": { dir: "parentNode", first: true },
1544    " ": { dir: "parentNode" },
1545    "+": { dir: "previousSibling", first: true },
1546    "~": { dir: "previousSibling" }
1547  },
1548
1549  preFilter: {
1550    "ATTR": function( match ) {
1551      match[1] = match[1].replace( runescape, funescape );
1552
1553      // Move the given value to match[3] whether quoted or unquoted
1554      match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1555
1556      if ( match[2] === "~=" ) {
1557        match[3] = " " + match[3] + " ";
1558      }
1559
1560      return match.slice( 0, 4 );
1561    },
1562
1563    "CHILD": function( match ) {
1564      /* matches from matchExpr["CHILD"]
1565        1 type (only|nth|...)
1566        2 what (child|of-type)
1567        3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1568        4 xn-component of xn+y argument ([+-]?\d*n|)
1569        5 sign of xn-component
1570        6 x of xn-component
1571        7 sign of y-component
1572        8 y of y-component
1573      */
1574      match[1] = match[1].toLowerCase();
1575
1576      if ( match[1].slice( 0, 3 ) === "nth" ) {
1577        // nth-* requires argument
1578        if ( !match[3] ) {
1579          Sizzle.error( match[0] );
1580        }
1581
1582        // numeric x and y parameters for Expr.filter.CHILD
1583        // remember that false/true cast respectively to 0/1
1584        match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1585        match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1586
1587      // other types prohibit arguments
1588      } else if ( match[3] ) {
1589        Sizzle.error( match[0] );
1590      }
1591
1592      return match;
1593    },
1594
1595    "PSEUDO": function( match ) {
1596      var excess,
1597        unquoted = !match[6] && match[2];
1598
1599      if ( matchExpr["CHILD"].test( match[0] ) ) {
1600        return null;
1601      }
1602
1603      // Accept quoted arguments as-is
1604      if ( match[3] ) {
1605        match[2] = match[4] || match[5] || "";
1606
1607      // Strip excess characters from unquoted arguments
1608      } else if ( unquoted && rpseudo.test( unquoted ) &&
1609        // Get excess from tokenize (recursively)
1610        (excess = tokenize( unquoted, true )) &&
1611        // advance to the next closing parenthesis
1612        (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1613
1614        // excess is a negative index
1615        match[0] = match[0].slice( 0, excess );
1616        match[2] = unquoted.slice( 0, excess );
1617      }
1618
1619      // Return only captures needed by the pseudo filter method (type and argument)
1620      return match.slice( 0, 3 );
1621    }
1622  },
1623
1624  filter: {
1625
1626    "TAG": function( nodeNameSelector ) {
1627      var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1628      return nodeNameSelector === "*" ?
1629        function() { return true; } :
1630        function( elem ) {
1631          return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1632        };
1633    },
1634
1635    "CLASS": function( className ) {
1636      var pattern = classCache[ className + " " ];
1637
1638      return pattern ||
1639        (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1640        classCache( className, function( elem ) {
1641          return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1642        });
1643    },
1644
1645    "ATTR": function( name, operator, check ) {
1646      return function( elem ) {
1647        var result = Sizzle.attr( elem, name );
1648
1649        if ( result == null ) {
1650          return operator === "!=";
1651        }
1652        if ( !operator ) {
1653          return true;
1654        }
1655
1656        result += "";
1657
1658        return operator === "=" ? result === check :
1659          operator === "!=" ? result !== check :
1660          operator === "^=" ? check && result.indexOf( check ) === 0 :
1661          operator === "*=" ? check && result.indexOf( check ) > -1 :
1662          operator === "$=" ? check && result.slice( -check.length ) === check :
1663          operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1664          operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1665          false;
1666      };
1667    },
1668
1669    "CHILD": function( type, what, argument, first, last ) {
1670      var simple = type.slice( 0, 3 ) !== "nth",
1671        forward = type.slice( -4 ) !== "last",
1672        ofType = what === "of-type";
1673
1674      return first === 1 && last === 0 ?
1675
1676        // Shortcut for :nth-*(n)
1677        function( elem ) {
1678          return !!elem.parentNode;
1679        } :
1680
1681        function( elem, context, xml ) {
1682          var cache, outerCache, node, diff, nodeIndex, start,
1683            dir = simple !== forward ? "nextSibling" : "previousSibling",
1684            parent = elem.parentNode,
1685            name = ofType && elem.nodeName.toLowerCase(),
1686            useCache = !xml && !ofType;
1687
1688          if ( parent ) {
1689
1690            // :(first|last|only)-(child|of-type)
1691            if ( simple ) {
1692              while ( dir ) {
1693                node = elem;
1694                while ( (node = node[ dir ]) ) {
1695                  if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
1696                    return false;
1697                  }
1698                }
1699                // Reverse direction for :only-* (if we haven't yet done so)
1700                start = dir = type === "only" && !start && "nextSibling";
1701              }
1702              return true;
1703            }
1704
1705            start = [ forward ? parent.firstChild : parent.lastChild ];
1706
1707            // non-xml :nth-child(...) stores cache data on `parent`
1708            if ( forward && useCache ) {
1709              // Seek `elem` from a previously-cached index
1710              outerCache = parent[ expando ] || (parent[ expando ] = {});
1711              cache = outerCache[ type ] || [];
1712              nodeIndex = cache[0] === dirruns && cache[1];
1713              diff = cache[0] === dirruns && cache[2];
1714              node = nodeIndex && parent.childNodes[ nodeIndex ];
1715
1716              while ( (node = ++nodeIndex && node && node[ dir ] ||
1717
1718                // Fallback to seeking `elem` from the start
1719                (diff = nodeIndex = 0) || start.pop()) ) {
1720
1721                // When found, cache indexes on `parent` and break
1722                if ( node.nodeType === 1 && ++diff && node === elem ) {
1723                  outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1724                  break;
1725                }
1726              }
1727
1728            // Use previously-cached element index if available
1729            } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
1730              diff = cache[1];
1731
1732            // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
1733            } else {
1734              // Use the same loop as above to seek `elem` from the start
1735              while ( (node = ++nodeIndex && node && node[ dir ] ||
1736                (diff = nodeIndex = 0) || start.pop()) ) {
1737
1738                if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
1739                  // Cache the index of each encountered element
1740                  if ( useCache ) {
1741                    (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
1742                  }
1743
1744                  if ( node === elem ) {
1745                    break;
1746                  }
1747                }
1748              }
1749            }
1750
1751            // Incorporate the offset, then check against cycle size
1752            diff -= last;
1753            return diff === first || ( diff % first === 0 && diff / first >= 0 );
1754          }
1755        };
1756    },
1757
1758    "PSEUDO": function( pseudo, argument ) {
1759      // pseudo-class names are case-insensitive
1760      // http://www.w3.org/TR/selectors/#pseudo-classes
1761      // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1762      // Remember that setFilters inherits from pseudos
1763      var args,
1764        fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1765          Sizzle.error( "unsupported pseudo: " + pseudo );
1766
1767      // The user may use createPseudo to indicate that
1768      // arguments are needed to create the filter function
1769      // just as Sizzle does
1770      if ( fn[ expando ] ) {
1771        return fn( argument );
1772      }
1773
1774      // But maintain support for old signatures
1775      if ( fn.length > 1 ) {
1776        args = [ pseudo, pseudo, "", argument ];
1777        return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1778          markFunction(function( seed, matches ) {
1779            var idx,
1780              matched = fn( seed, argument ),
1781              i = matched.length;
1782            while ( i-- ) {
1783              idx = indexOf( seed, matched[i] );
1784              seed[ idx ] = !( matches[ idx ] = matched[i] );
1785            }
1786          }) :
1787          function( elem ) {
1788            return fn( elem, 0, args );
1789          };
1790      }
1791
1792      return fn;
1793    }
1794  },
1795
1796  pseudos: {
1797    // Potentially complex pseudos
1798    "not": markFunction(function( selector ) {
1799      // Trim the selector passed to compile
1800      // to avoid treating leading and trailing
1801      // spaces as combinators
1802      var input = [],
1803        results = [],
1804        matcher = compile( selector.replace( rtrim, "$1" ) );
1805
1806      return matcher[ expando ] ?
1807        markFunction(function( seed, matches, context, xml ) {
1808          var elem,
1809            unmatched = matcher( seed, null, xml, [] ),
1810            i = seed.length;
1811
1812          // Match elements unmatched by `matcher`
1813          while ( i-- ) {
1814            if ( (elem = unmatched[i]) ) {
1815              seed[i] = !(matches[i] = elem);
1816            }
1817          }
1818        }) :
1819        function( elem, context, xml ) {
1820          input[0] = elem;
1821          matcher( input, null, xml, results );
1822          // Don't keep the element (issue #299)
1823          input[0] = null;
1824          return !results.pop();
1825        };
1826    }),
1827
1828    "has": markFunction(function( selector ) {
1829      return function( elem ) {
1830        return Sizzle( selector, elem ).length > 0;
1831      };
1832    }),
1833
1834    "contains": markFunction(function( text ) {
1835      text = text.replace( runescape, funescape );
1836      return function( elem ) {
1837        return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1838      };
1839    }),
1840
1841    // "Whether an element is represented by a :lang() selector
1842    // is based solely on the element's language value
1843    // being equal to the identifier C,
1844    // or beginning with the identifier C immediately followed by "-".
1845    // The matching of C against the element's language value is performed case-insensitively.
1846    // The identifier C does not have to be a valid language name."
1847    // http://www.w3.org/TR/selectors/#lang-pseudo
1848    "lang": markFunction( function( lang ) {
1849      // lang value must be a valid identifier
1850      if ( !ridentifier.test(lang || "") ) {
1851        Sizzle.error( "unsupported lang: " + lang );
1852      }
1853      lang = lang.replace( runescape, funescape ).toLowerCase();
1854      return function( elem ) {
1855        var elemLang;
1856        do {
1857          if ( (elemLang = documentIsHTML ?
1858            elem.lang :
1859            elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1860
1861            elemLang = elemLang.toLowerCase();
1862            return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1863          }
1864        } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1865        return false;
1866      };
1867    }),
1868
1869    // Miscellaneous
1870    "target": function( elem ) {
1871      var hash = window.location && window.location.hash;
1872      return hash && hash.slice( 1 ) === elem.id;
1873    },
1874
1875    "root": function( elem ) {
1876      return elem === docElem;
1877    },
1878
1879    "focus": function( elem ) {
1880      return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1881    },
1882
1883    // Boolean properties
1884    "enabled": function( elem ) {
1885      return elem.disabled === false;
1886    },
1887
1888    "disabled": function( elem ) {
1889      return elem.disabled === true;
1890    },
1891
1892    "checked": function( elem ) {
1893      // In CSS3, :checked should return both checked and selected elements
1894      // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1895      var nodeName = elem.nodeName.toLowerCase();
1896      return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
1897    },
1898
1899    "selected": function( elem ) {
1900      // Accessing this property makes selected-by-default
1901      // options in Safari work properly
1902      if ( elem.parentNode ) {
1903        elem.parentNode.selectedIndex;
1904      }
1905
1906      return elem.selected === true;
1907    },
1908
1909    // Contents
1910    "empty": function( elem ) {
1911      // http://www.w3.org/TR/selectors/#empty-pseudo
1912      // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1913      //   but not by others (comment: 8; processing instruction: 7; etc.)
1914      // nodeType < 6 works because attributes (2) do not appear as children
1915      for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1916        if ( elem.nodeType < 6 ) {
1917          return false;
1918        }
1919      }
1920      return true;
1921    },
1922
1923    "parent": function( elem ) {
1924      return !Expr.pseudos["empty"]( elem );
1925    },
1926
1927    // Element/input types
1928    "header": function( elem ) {
1929      return rheader.test( elem.nodeName );
1930    },
1931
1932    "input": function( elem ) {
1933      return rinputs.test( elem.nodeName );
1934    },
1935
1936    "button": function( elem ) {
1937      var name = elem.nodeName.toLowerCase();
1938      return name === "input" && elem.type === "button" || name === "button";
1939    },
1940
1941    "text": function( elem ) {
1942      var attr;
1943      return elem.nodeName.toLowerCase() === "input" &&
1944        elem.type === "text" &&
1945
1946        // Support: IE<8
1947        // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
1948        ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
1949    },
1950
1951    // Position-in-collection
1952    "first": createPositionalPseudo(function() {
1953      return [ 0 ];
1954    }),
1955
1956    "last": createPositionalPseudo(function( matchIndexes, length ) {
1957      return [ length - 1 ];
1958    }),
1959
1960    "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
1961      return [ argument < 0 ? argument + length : argument ];
1962    }),
1963
1964    "even": createPositionalPseudo(function( matchIndexes, length ) {
1965      var i = 0;
1966      for ( ; i < length; i += 2 ) {
1967        matchIndexes.push( i );
1968      }
1969      return matchIndexes;
1970    }),
1971
1972    "odd": createPositionalPseudo(function( matchIndexes, length ) {
1973      var i = 1;
1974      for ( ; i < length; i += 2 ) {
1975        matchIndexes.push( i );
1976      }
1977      return matchIndexes;
1978    }),
1979
1980    "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
1981      var i = argument < 0 ? argument + length : argument;
1982      for ( ; --i >= 0; ) {
1983        matchIndexes.push( i );
1984      }
1985      return matchIndexes;
1986    }),
1987
1988    "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
1989      var i = argument < 0 ? argument + length : argument;
1990      for ( ; ++i < length; ) {
1991        matchIndexes.push( i );
1992      }
1993      return matchIndexes;
1994    })
1995  }
1996};
1997
1998Expr.pseudos["nth"] = Expr.pseudos["eq"];
1999
2000// Add button/input type pseudos
2001for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2002  Expr.pseudos[ i ] = createInputPseudo( i );
2003}
2004for ( i in { submit: true, reset: true } ) {
2005  Expr.pseudos[ i ] = createButtonPseudo( i );
2006}
2007
2008// Easy API for creating new setFilters
2009function setFilters() {}
2010setFilters.prototype = Expr.filters = Expr.pseudos;
2011Expr.setFilters = new setFilters();
2012
2013tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2014  var matched, match, tokens, type,
2015    soFar, groups, preFilters,
2016    cached = tokenCache[ selector + " " ];
2017
2018  if ( cached ) {
2019    return parseOnly ? 0 : cached.slice( 0 );
2020  }
2021
2022  soFar = selector;
2023  groups = [];
2024  preFilters = Expr.preFilter;
2025
2026  while ( soFar ) {
2027
2028    // Comma and first run
2029    if ( !matched || (match = rcomma.exec( soFar )) ) {
2030      if ( match ) {
2031        // Don't consume trailing commas as valid
2032        soFar = soFar.slice( match[0].length ) || soFar;
2033      }
2034      groups.push( (tokens = []) );
2035    }
2036
2037    matched = false;
2038
2039    // Combinators
2040    if ( (match = rcombinators.exec( soFar )) ) {
2041      matched = match.shift();
2042      tokens.push({
2043        value: matched,
2044        // Cast descendant combinators to space
2045        type: match[0].replace( rtrim, " " )
2046      });
2047      soFar = soFar.slice( matched.length );
2048    }
2049
2050    // Filters
2051    for ( type in Expr.filter ) {
2052      if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2053        (match = preFilters[ type ]( match ))) ) {
2054        matched = match.shift();
2055        tokens.push({
2056          value: matched,
2057          type: type,
2058          matches: match
2059        });
2060        soFar = soFar.slice( matched.length );
2061      }
2062    }
2063
2064    if ( !matched ) {
2065      break;
2066    }
2067  }
2068
2069  // Return the length of the invalid excess
2070  // if we're just parsing
2071  // Otherwise, throw an error or return tokens
2072  return parseOnly ?
2073    soFar.length :
2074    soFar ?
2075      Sizzle.error( selector ) :
2076      // Cache the tokens
2077      tokenCache( selector, groups ).slice( 0 );
2078};
2079
2080function toSelector( tokens ) {
2081  var i = 0,
2082    len = tokens.length,
2083    selector = "";
2084  for ( ; i < len; i++ ) {
2085    selector += tokens[i].value;
2086  }
2087  return selector;
2088}
2089
2090function addCombinator( matcher, combinator, base ) {
2091  var dir = combinator.dir,
2092    checkNonElements = base && dir === "parentNode",
2093    doneName = done++;
2094
2095  return combinator.first ?
2096    // Check against closest ancestor/preceding element
2097    function( elem, context, xml ) {
2098      while ( (elem = elem[ dir ]) ) {
2099        if ( elem.nodeType === 1 || checkNonElements ) {
2100          return matcher( elem, context, xml );
2101        }
2102      }
2103    } :
2104
2105    // Check against all ancestor/preceding elements
2106    function( elem, context, xml ) {
2107      var oldCache, outerCache,
2108        newCache = [ dirruns, doneName ];
2109
2110      // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2111      if ( xml ) {
2112        while ( (elem = elem[ dir ]) ) {
2113          if ( elem.nodeType === 1 || checkNonElements ) {
2114            if ( matcher( elem, context, xml ) ) {
2115              return true;
2116            }
2117          }
2118        }
2119      } else {
2120        while ( (elem = elem[ dir ]) ) {
2121          if ( elem.nodeType === 1 || checkNonElements ) {
2122            outerCache = elem[ expando ] || (elem[ expando ] = {});
2123            if ( (oldCache = outerCache[ dir ]) &&
2124              oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2125
2126              // Assign to newCache so results back-propagate to previous elements
2127              return (newCache[ 2 ] = oldCache[ 2 ]);
2128            } else {
2129              // Reuse newcache so results back-propagate to previous elements
2130              outerCache[ dir ] = newCache;
2131
2132              // A match means we're done; a fail means we have to keep checking
2133              if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2134                return true;
2135              }
2136            }
2137          }
2138        }
2139      }
2140    };
2141}
2142
2143function elementMatcher( matchers ) {
2144  return matchers.length > 1 ?
2145    function( elem, context, xml ) {
2146      var i = matchers.length;
2147      while ( i-- ) {
2148        if ( !matchers[i]( elem, context, xml ) ) {
2149          return false;
2150        }
2151      }
2152      return true;
2153    } :
2154    matchers[0];
2155}
2156
2157function multipleContexts( selector, contexts, results ) {
2158  var i = 0,
2159    len = contexts.length;
2160  for ( ; i < len; i++ ) {
2161    Sizzle( selector, contexts[i], results );
2162  }
2163  return results;
2164}
2165
2166function condense( unmatched, map, filter, context, xml ) {
2167  var elem,
2168    newUnmatched = [],
2169    i = 0,
2170    len = unmatched.length,
2171    mapped = map != null;
2172
2173  for ( ; i < len; i++ ) {
2174    if ( (elem = unmatched[i]) ) {
2175      if ( !filter || filter( elem, context, xml ) ) {
2176        newUnmatched.push( elem );
2177        if ( mapped ) {
2178          map.push( i );
2179        }
2180      }
2181    }
2182  }
2183
2184  return newUnmatched;
2185}
2186
2187function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2188  if ( postFilter && !postFilter[ expando ] ) {
2189    postFilter = setMatcher( postFilter );
2190  }
2191  if ( postFinder && !postFinder[ expando ] ) {
2192    postFinder = setMatcher( postFinder, postSelector );
2193  }
2194  return markFunction(function( seed, results, context, xml ) {
2195    var temp, i, elem,
2196      preMap = [],
2197      postMap = [],
2198      preexisting = results.length,
2199
2200      // Get initial elements from seed or context
2201      elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2202
2203      // Prefilter to get matcher input, preserving a map for seed-results synchronization
2204      matcherIn = preFilter && ( seed || !selector ) ?
2205        condense( elems, preMap, preFilter, context, xml ) :
2206        elems,
2207
2208      matcherOut = matcher ?
2209        // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2210        postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2211
2212          // ...intermediate processing is necessary
2213          [] :
2214
2215          // ...otherwise use results directly
2216          results :
2217        matcherIn;
2218
2219    // Find primary matches
2220    if ( matcher ) {
2221      matcher( matcherIn, matcherOut, context, xml );
2222    }
2223
2224    // Apply postFilter
2225    if ( postFilter ) {
2226      temp = condense( matcherOut, postMap );
2227      postFilter( temp, [], context, xml );
2228
2229      // Un-match failing elements by moving them back to matcherIn
2230      i = temp.length;
2231      while ( i-- ) {
2232        if ( (elem = temp[i]) ) {
2233          matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2234        }
2235      }
2236    }
2237
2238    if ( seed ) {
2239      if ( postFinder || preFilter ) {
2240        if ( postFinder ) {
2241          // Get the final matcherOut by condensing this intermediate into postFinder contexts
2242          temp = [];
2243          i = matcherOut.length;
2244          while ( i-- ) {
2245            if ( (elem = matcherOut[i]) ) {
2246              // Restore matcherIn since elem is not yet a final match
2247              temp.push( (matcherIn[i] = elem) );
2248            }
2249          }
2250          postFinder( null, (matcherOut = []), temp, xml );
2251        }
2252
2253        // Move matched elements from seed to results to keep them synchronized
2254        i = matcherOut.length;
2255        while ( i-- ) {
2256          if ( (elem = matcherOut[i]) &&
2257            (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2258
2259            seed[temp] = !(results[temp] = elem);
2260          }
2261        }
2262      }
2263
2264    // Add elements to results, through postFinder if defined
2265    } else {
2266      matcherOut = condense(
2267        matcherOut === results ?
2268          matcherOut.splice( preexisting, matcherOut.length ) :
2269          matcherOut
2270      );
2271      if ( postFinder ) {
2272        postFinder( null, results, matcherOut, xml );
2273      } else {
2274        push.apply( results, matcherOut );
2275      }
2276    }
2277  });
2278}
2279
2280function matcherFromTokens( tokens ) {
2281  var checkContext, matcher, j,
2282    len = tokens.length,
2283    leadingRelative = Expr.relative[ tokens[0].type ],
2284    implicitRelative = leadingRelative || Expr.relative[" "],
2285    i = leadingRelative ? 1 : 0,
2286
2287    // The foundational matcher ensures that elements are reachable from top-level context(s)
2288    matchContext = addCombinator( function( elem ) {
2289      return elem === checkContext;
2290    }, implicitRelative, true ),
2291    matchAnyContext = addCombinator( function( elem ) {
2292      return indexOf( checkContext, elem ) > -1;
2293    }, implicitRelative, true ),
2294    matchers = [ function( elem, context, xml ) {
2295      var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2296        (checkContext = context).nodeType ?
2297          matchContext( elem, context, xml ) :
2298          matchAnyContext( elem, context, xml ) );
2299      // Avoid hanging onto element (issue #299)
2300      checkContext = null;
2301      return ret;
2302    } ];
2303
2304  for ( ; i < len; i++ ) {
2305    if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2306      matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2307    } else {
2308      matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2309
2310      // Return special upon seeing a positional matcher
2311      if ( matcher[ expando ] ) {
2312        // Find the next relative operator (if any) for proper handling
2313        j = ++i;
2314        for ( ; j < len; j++ ) {
2315          if ( Expr.relative[ tokens[j].type ] ) {
2316            break;
2317          }
2318        }
2319        return setMatcher(
2320          i > 1 && elementMatcher( matchers ),
2321          i > 1 && toSelector(
2322            // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2323            tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2324          ).replace( rtrim, "$1" ),
2325          matcher,
2326          i < j && matcherFromTokens( tokens.slice( i, j ) ),
2327          j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2328          j < len && toSelector( tokens )
2329        );
2330      }
2331      matchers.push( matcher );
2332    }
2333  }
2334
2335  return elementMatcher( matchers );
2336}
2337
2338function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2339  var bySet = setMatchers.length > 0,
2340    byElement = elementMatchers.length > 0,
2341    superMatcher = function( seed, context, xml, results, outermost ) {
2342      var elem, j, matcher,
2343        matchedCount = 0,
2344        i = "0",
2345        unmatched = seed && [],
2346        setMatched = [],
2347        contextBackup = outermostContext,
2348        // We must always have either seed elements or outermost context
2349        elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2350        // Use integer dirruns iff this is the outermost matcher
2351        dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2352        len = elems.length;
2353
2354      if ( outermost ) {
2355        outermostContext = context !== document && context;
2356      }
2357
2358      // Add elements passing elementMatchers directly to results
2359      // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2360      // Support: IE<9, Safari
2361      // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2362      for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2363        if ( byElement && elem ) {
2364          j = 0;
2365          while ( (matcher = elementMatchers[j++]) ) {
2366            if ( matcher( elem, context, xml ) ) {
2367              results.push( elem );
2368              break;
2369            }
2370          }
2371          if ( outermost ) {
2372            dirruns = dirrunsUnique;
2373          }
2374        }
2375
2376        // Track unmatched elements for set filters
2377        if ( bySet ) {
2378          // They will have gone through all possible matchers
2379          if ( (elem = !matcher && elem) ) {
2380            matchedCount--;
2381          }
2382
2383          // Lengthen the array for every element, matched or not
2384          if ( seed ) {
2385            unmatched.push( elem );
2386          }
2387        }
2388      }
2389
2390      // Apply set filters to unmatched elements
2391      matchedCount += i;
2392      if ( bySet && i !== matchedCount ) {
2393        j = 0;
2394        while ( (matcher = setMatchers[j++]) ) {
2395          matcher( unmatched, setMatched, context, xml );
2396        }
2397
2398        if ( seed ) {
2399          // Reintegrate element matches to eliminate the need for sorting
2400          if ( matchedCount > 0 ) {
2401            while ( i-- ) {
2402              if ( !(unmatched[i] || setMatched[i]) ) {
2403                setMatched[i] = pop.call( results );
2404              }
2405            }
2406          }
2407
2408          // Discard index placeholder values to get only actual matches
2409          setMatched = condense( setMatched );
2410        }
2411
2412        // Add matches to results
2413        push.apply( results, setMatched );
2414
2415        // Seedless set matches succeeding multiple successful matchers stipulate sorting
2416        if ( outermost && !seed && setMatched.length > 0 &&
2417          ( matchedCount + setMatchers.length ) > 1 ) {
2418
2419          Sizzle.uniqueSort( results );
2420        }
2421      }
2422
2423      // Override manipulation of globals by nested matchers
2424      if ( outermost ) {
2425        dirruns = dirrunsUnique;
2426        outermostContext = contextBackup;
2427      }
2428
2429      return unmatched;
2430    };
2431
2432  return bySet ?
2433    markFunction( superMatcher ) :
2434    superMatcher;
2435}
2436
2437compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2438  var i,
2439    setMatchers = [],
2440    elementMatchers = [],
2441    cached = compilerCache[ selector + " " ];
2442
2443  if ( !cached ) {
2444    // Generate a function of recursive functions that can be used to check each element
2445    if ( !match ) {
2446      match = tokenize( selector );
2447    }
2448    i = match.length;
2449    while ( i-- ) {
2450      cached = matcherFromTokens( match[i] );
2451      if ( cached[ expando ] ) {
2452        setMatchers.push( cached );
2453      } else {
2454        elementMatchers.push( cached );
2455      }
2456    }
2457
2458    // Cache the compiled function
2459    cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2460
2461    // Save selector and tokenization
2462    cached.selector = selector;
2463  }
2464  return cached;
2465};
2466
2467/**
2468 * A low-level selection function that works with Sizzle's compiled
2469 *  selector functions
2470 * @param {String|Function} selector A selector or a pre-compiled
2471 *  selector function built with Sizzle.compile
2472 * @param {Element} context
2473 * @param {Array} [results]
2474 * @param {Array} [seed] A set of elements to match against
2475 */
2476select = Sizzle.select = function( selector, context, results, seed ) {
2477  var i, tokens, token, type, find,
2478    compiled = typeof selector === "function" && selector,
2479    match = !seed && tokenize( (selector = compiled.selector || selector) );
2480
2481  results = results || [];
2482
2483  // Try to minimize operations if there is no seed and only one group
2484  if ( match.length === 1 ) {
2485
2486    // Take a shortcut and set the context if the root selector is an ID
2487    tokens = match[0] = match[0].slice( 0 );
2488    if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2489        support.getById && context.nodeType === 9 && documentIsHTML &&
2490        Expr.relative[ tokens[1].type ] ) {
2491
2492      context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2493      if ( !context ) {
2494        return results;
2495
2496      // Precompiled matchers will still verify ancestry, so step up a level
2497      } else if ( compiled ) {
2498        context = context.parentNode;
2499      }
2500
2501      selector = selector.slice( tokens.shift().value.length );
2502    }
2503
2504    // Fetch a seed set for right-to-left matching
2505    i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2506    while ( i-- ) {
2507      token = tokens[i];
2508
2509      // Abort if we hit a combinator
2510      if ( Expr.relative[ (type = token.type) ] ) {
2511        break;
2512      }
2513      if ( (find = Expr.find[ type ]) ) {
2514        // Search, expanding context for leading sibling combinators
2515        if ( (seed = find(
2516          token.matches[0].replace( runescape, funescape ),
2517          rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2518        )) ) {
2519
2520          // If seed is empty or no tokens remain, we can return early
2521          tokens.splice( i, 1 );
2522          selector = seed.length && toSelector( tokens );
2523          if ( !selector ) {
2524            push.apply( results, seed );
2525            return results;
2526          }
2527
2528          break;
2529        }
2530      }
2531    }
2532  }
2533
2534  // Compile and execute a filtering function if one is not provided
2535  // Provide `match` to avoid retokenization if we modified the selector above
2536  ( compiled || compile( selector, match ) )(
2537    seed,
2538    context,
2539    !documentIsHTML,
2540    results,
2541    rsibling.test( selector ) && testContext( context.parentNode ) || context
2542  );
2543  return results;
2544};
2545
2546// One-time assignments
2547
2548// Sort stability
2549support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2550
2551// Support: Chrome 14-35+
2552// Always assume duplicates if they aren't passed to the comparison function
2553support.detectDuplicates = !!hasDuplicate;
2554
2555// Initialize against the default document
2556setDocument();
2557
2558// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2559// Detached nodes confoundingly follow *each other*
2560support.sortDetached = assert(function( div1 ) {
2561  // Should return 1, but returns 4 (following)
2562  return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2563});
2564
2565// Support: IE<8
2566// Prevent attribute/property "interpolation"
2567// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2568if ( !assert(function( div ) {
2569  div.innerHTML = "<a href='#'></a>";
2570  return div.firstChild.getAttribute("href") === "#" ;
2571}) ) {
2572  addHandle( "type|href|height|width", function( elem, name, isXML ) {
2573    if ( !isXML ) {
2574      return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2575    }
2576  });
2577}
2578
2579// Support: IE<9
2580// Use defaultValue in place of getAttribute("value")
2581if ( !support.attributes || !assert(function( div ) {
2582  div.innerHTML = "<input/>";
2583  div.firstChild.setAttribute( "value", "" );
2584  return div.firstChild.getAttribute( "value" ) === "";
2585}) ) {
2586  addHandle( "value", function( elem, name, isXML ) {
2587    if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2588      return elem.defaultValue;
2589    }
2590  });
2591}
2592
2593// Support: IE<9
2594// Use getAttributeNode to fetch booleans when getAttribute lies
2595if ( !assert(function( div ) {
2596  return div.getAttribute("disabled") == null;
2597}) ) {
2598  addHandle( booleans, function( elem, name, isXML ) {
2599    var val;
2600    if ( !isXML ) {
2601      return elem[ name ] === true ? name.toLowerCase() :
2602          (val = elem.getAttributeNode( name )) && val.specified ?
2603          val.value :
2604        null;
2605    }
2606  });
2607}
2608
2609return Sizzle;
2610
2611})( window );
2612
2613
2614
2615jQuery.find = Sizzle;
2616jQuery.expr = Sizzle.selectors;
2617jQuery.expr[":"] = jQuery.expr.pseudos;
2618jQuery.unique = Sizzle.uniqueSort;
2619jQuery.text = Sizzle.getText;
2620jQuery.isXMLDoc = Sizzle.isXML;
2621jQuery.contains = Sizzle.contains;
2622
2623
2624
2625var rneedsContext = jQuery.expr.match.needsContext;
2626
2627var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
2628
2629
2630
2631var risSimple = /^.[^:#\[\.,]*$/;
2632
2633// Implement the identical functionality for filter and not
2634function winnow( elements, qualifier, not ) {
2635  if ( jQuery.isFunction( qualifier ) ) {
2636    return jQuery.grep( elements, function( elem, i ) {
2637      /* jshint -W018 */
2638      return !!qualifier.call( elem, i, elem ) !== not;
2639    });
2640
2641  }
2642
2643  if ( qualifier.nodeType ) {
2644    return jQuery.grep( elements, function( elem ) {
2645      return ( elem === qualifier ) !== not;
2646    });
2647
2648  }
2649
2650  if ( typeof qualifier === "string" ) {
2651    if ( risSimple.test( qualifier ) ) {
2652      return jQuery.filter( qualifier, elements, not );
2653    }
2654
2655    qualifier = jQuery.filter( qualifier, elements );
2656  }
2657
2658  return jQuery.grep( elements, function( elem ) {
2659    return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
2660  });
2661}
2662
2663jQuery.filter = function( expr, elems, not ) {
2664  var elem = elems[ 0 ];
2665
2666  if ( not ) {
2667    expr = ":not(" + expr + ")";
2668  }
2669
2670  return elems.length === 1 && elem.nodeType === 1 ?
2671    jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2672    jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2673      return elem.nodeType === 1;
2674    }));
2675};
2676
2677jQuery.fn.extend({
2678  find: function( selector ) {
2679    var i,
2680      len = this.length,
2681      ret = [],
2682      self = this;
2683
2684    if ( typeof selector !== "string" ) {
2685      return this.pushStack( jQuery( selector ).filter(function() {
2686        for ( i = 0; i < len; i++ ) {
2687          if ( jQuery.contains( self[ i ], this ) ) {
2688            return true;
2689          }
2690        }
2691      }) );
2692    }
2693
2694    for ( i = 0; i < len; i++ ) {
2695      jQuery.find( selector, self[ i ], ret );
2696    }
2697
2698    // Needed because $( selector, context ) becomes $( context ).find( selector )
2699    ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2700    ret.selector = this.selector ? this.selector + " " + selector : selector;
2701    return ret;
2702  },
2703  filter: function( selector ) {
2704    return this.pushStack( winnow(this, selector || [], false) );
2705  },
2706  not: function( selector ) {
2707    return this.pushStack( winnow(this, selector || [], true) );
2708  },
2709  is: function( selector ) {
2710    return !!winnow(
2711      this,
2712
2713      // If this is a positional/relative selector, check membership in the returned set
2714      // so $("p:first").is("p:last") won't return true for a doc with two "p".
2715      typeof selector === "string" && rneedsContext.test( selector ) ?
2716        jQuery( selector ) :
2717        selector || [],
2718      false
2719    ).length;
2720  }
2721});
2722
2723
2724// Initialize a jQuery object
2725
2726
2727// A central reference to the root jQuery(document)
2728var rootjQuery,
2729
2730  // A simple way to check for HTML strings
2731  // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2732  // Strict HTML recognition (#11290: must start with <)
2733  rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2734
2735  init = jQuery.fn.init = function( selector, context ) {
2736    var match, elem;
2737
2738    // HANDLE: $(""), $(null), $(undefined), $(false)
2739    if ( !selector ) {
2740      return this;
2741    }
2742
2743    // Handle HTML strings
2744    if ( typeof selector === "string" ) {
2745      if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
2746        // Assume that strings that start and end with <> are HTML and skip the regex check
2747        match = [ null, selector, null ];
2748
2749      } else {
2750        match = rquickExpr.exec( selector );
2751      }
2752
2753      // Match html or make sure no context is specified for #id
2754      if ( match && (match[1] || !context) ) {
2755
2756        // HANDLE: $(html) -> $(array)
2757        if ( match[1] ) {
2758          context = context instanceof jQuery ? context[0] : context;
2759
2760          // Option to run scripts is true for back-compat
2761          // Intentionally let the error be thrown if parseHTML is not present
2762          jQuery.merge( this, jQuery.parseHTML(
2763            match[1],
2764            context && context.nodeType ? context.ownerDocument || context : document,
2765            true
2766          ) );
2767
2768          // HANDLE: $(html, props)
2769          if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
2770            for ( match in context ) {
2771              // Properties of context are called as methods if possible
2772              if ( jQuery.isFunction( this[ match ] ) ) {
2773                this[ match ]( context[ match ] );
2774
2775              // ...and otherwise set as attributes
2776              } else {
2777                this.attr( match, context[ match ] );
2778              }
2779            }
2780          }
2781
2782          return this;
2783
2784        // HANDLE: $(#id)
2785        } else {
2786          elem = document.getElementById( match[2] );
2787
2788          // Support: Blackberry 4.6
2789          // gEBID returns nodes no longer in the document (#6963)
2790          if ( elem && elem.parentNode ) {
2791            // Inject the element directly into the jQuery object
2792            this.length = 1;
2793            this[0] = elem;
2794          }
2795
2796          this.context = document;
2797          this.selector = selector;
2798          return this;
2799        }
2800
2801      // HANDLE: $(expr, $(...))
2802      } else if ( !context || context.jquery ) {
2803        return ( context || rootjQuery ).find( selector );
2804
2805      // HANDLE: $(expr, context)
2806      // (which is just equivalent to: $(context).find(expr)
2807      } else {
2808        return this.constructor( context ).find( selector );
2809      }
2810
2811    // HANDLE: $(DOMElement)
2812    } else if ( selector.nodeType ) {
2813      this.context = this[0] = selector;
2814      this.length = 1;
2815      return this;
2816
2817    // HANDLE: $(function)
2818    // Shortcut for document ready
2819    } else if ( jQuery.isFunction( selector ) ) {
2820      return typeof rootjQuery.ready !== "undefined" ?
2821        rootjQuery.ready( selector ) :
2822        // Execute immediately if ready is not present
2823        selector( jQuery );
2824    }
2825
2826    if ( selector.selector !== undefined ) {
2827      this.selector = selector.selector;
2828      this.context = selector.context;
2829    }
2830
2831    return jQuery.makeArray( selector, this );
2832  };
2833
2834// Give the init function the jQuery prototype for later instantiation
2835init.prototype = jQuery.fn;
2836
2837// Initialize central reference
2838rootjQuery = jQuery( document );
2839
2840
2841var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2842  // Methods guaranteed to produce a unique set when starting from a unique set
2843  guaranteedUnique = {
2844    children: true,
2845    contents: true,
2846    next: true,
2847    prev: true
2848  };
2849
2850jQuery.extend({
2851  dir: function( elem, dir, until ) {
2852    var matched = [],
2853      truncate = until !== undefined;
2854
2855    while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
2856      if ( elem.nodeType === 1 ) {
2857        if ( truncate && jQuery( elem ).is( until ) ) {
2858          break;
2859        }
2860        matched.push( elem );
2861      }
2862    }
2863    return matched;
2864  },
2865
2866  sibling: function( n, elem ) {
2867    var matched = [];
2868
2869    for ( ; n; n = n.nextSibling ) {
2870      if ( n.nodeType === 1 && n !== elem ) {
2871        matched.push( n );
2872      }
2873    }
2874
2875    return matched;
2876  }
2877});
2878
2879jQuery.fn.extend({
2880  has: function( target ) {
2881    var targets = jQuery( target, this ),
2882      l = targets.length;
2883
2884    return this.filter(function() {
2885      var i = 0;
2886      for ( ; i < l; i++ ) {
2887        if ( jQuery.contains( this, targets[i] ) ) {
2888          return true;
2889        }
2890      }
2891    });
2892  },
2893
2894  closest: function( selectors, context ) {
2895    var cur,
2896      i = 0,
2897      l = this.length,
2898      matched = [],
2899      pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
vendor: 5,295 bytes, lines 2900-3087
2900        jQuery( selectors, context || this.context ) :
2901        0;
2902
2903    for ( ; i < l; i++ ) {
2904      for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
2905        // Always skip document fragments
2906        if ( cur.nodeType < 11 && (pos ?
2907          pos.index(cur) > -1 :
2908
2909          // Don't pass non-elements to Sizzle
2910          cur.nodeType === 1 &&
2911            jQuery.find.matchesSelector(cur, selectors)) ) {
2912
2913          matched.push( cur );
2914          break;
2915        }
2916      }
2917    }
2918
2919    return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
2920  },
2921
2922  // Determine the position of an element within the set
2923  index: function( elem ) {
2924
2925    // No argument, return index in parent
2926    if ( !elem ) {
2927      return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
2928    }
2929
2930    // Index in selector
2931    if ( typeof elem === "string" ) {
2932      return indexOf.call( jQuery( elem ), this[ 0 ] );
2933    }
2934
2935    // Locate the position of the desired element
2936    return indexOf.call( this,
2937
2938      // If it receives a jQuery object, the first element is used
2939      elem.jquery ? elem[ 0 ] : elem
2940    );
2941  },
2942
2943  add: function( selector, context ) {
2944    return this.pushStack(
2945      jQuery.unique(
2946        jQuery.merge( this.get(), jQuery( selector, context ) )
2947      )
2948    );
2949  },
2950
2951  addBack: function( selector ) {
2952    return this.add( selector == null ?
2953      this.prevObject : this.prevObject.filter(selector)
2954    );
2955  }
2956});
2957
2958function sibling( cur, dir ) {
2959  while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
2960  return cur;
2961}
2962
2963jQuery.each({
2964  parent: function( elem ) {
2965    var parent = elem.parentNode;
2966    return parent && parent.nodeType !== 11 ? parent : null;
2967  },
2968  parents: function( elem ) {
2969    return jQuery.dir( elem, "parentNode" );
2970  },
2971  parentsUntil: function( elem, i, until ) {
2972    return jQuery.dir( elem, "parentNode", until );
2973  },
2974  next: function( elem ) {
2975    return sibling( elem, "nextSibling" );
2976  },
2977  prev: function( elem ) {
2978    return sibling( elem, "previousSibling" );
2979  },
2980  nextAll: function( elem ) {
2981    return jQuery.dir( elem, "nextSibling" );
2982  },
2983  prevAll: function( elem ) {
2984    return jQuery.dir( elem, "previousSibling" );
2985  },
2986  nextUntil: function( elem, i, until ) {
2987    return jQuery.dir( elem, "nextSibling", until );
2988  },
2989  prevUntil: function( elem, i, until ) {
2990    return jQuery.dir( elem, "previousSibling", until );
2991  },
2992  siblings: function( elem ) {
2993    return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
2994  },
2995  children: function( elem ) {
2996    return jQuery.sibling( elem.firstChild );
2997  },
2998  contents: function( elem ) {
2999    return elem.contentDocument || jQuery.merge( [], elem.childNodes );
3000  }
3001}, function( name, fn ) {
3002  jQuery.fn[ name ] = function( until, selector ) {
3003    var matched = jQuery.map( this, fn, until );
3004
3005    if ( name.slice( -5 ) !== "Until" ) {
3006      selector = until;
3007    }
3008
3009    if ( selector && typeof selector === "string" ) {
3010      matched = jQuery.filter( selector, matched );
3011    }
3012
3013    if ( this.length > 1 ) {
3014      // Remove duplicates
3015      if ( !guaranteedUnique[ name ] ) {
3016        jQuery.unique( matched );
3017      }
3018
3019      // Reverse order for parents* and prev-derivatives
3020      if ( rparentsprev.test( name ) ) {
3021        matched.reverse();
3022      }
3023    }
3024
3025    return this.pushStack( matched );
3026  };
3027});
3028var rnotwhite = (/\S+/g);
3029
3030
3031
3032// String to Object options format cache
3033var optionsCache = {};
3034
3035// Convert String-formatted options into Object-formatted ones and store in cache
3036function createOptions( options ) {
3037  var object = optionsCache[ options ] = {};
3038  jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3039    object[ flag ] = true;
3040  });
3041  return object;
3042}
3043
3044/*
3045 * Create a callback list using the following parameters:
3046 *
3047 *  options: an optional list of space-separated options that will change how
3048 *      the callback list behaves or a more traditional option object
3049 *
3050 * By default a callback list will act like an event callback list and can be
3051 * "fired" multiple times.
3052 *
3053 * Possible options:
3054 *
3055 *  once:     will ensure the callback list can only be fired once (like a Deferred)
3056 *
3057 *  memory:     will keep track of previous values and will call any callback added
3058 *          after the list has been fired right away with the latest "memorized"
3059 *          values (like a Deferred)
3060 *
3061 *  unique:     will ensure a callback can only be added once (no duplicate in the list)
3062 *
3063 *  stopOnFalse:  interrupt callings when a callback returns false
3064 *
3065 */
3066jQuery.Callbacks = function( options ) {
3067
3068  // Convert options from String-formatted to Object-formatted if needed
3069  // (we check in cache first)
3070  options = typeof options === "string" ?
3071    ( optionsCache[ options ] || createOptions( options ) ) :
3072    jQuery.extend( {}, options );
3073
3074  var // Last fire value (for non-forgettable lists)
3075    memory,
3076    // Flag to know if list was already fired
3077    fired,
3078    // Flag to know if list is currently firing
3079    firing,
3080    // First callback to fire (used internally by add and fireWith)
3081    firingStart,
3082    // End of the loop when firing
3083    firingLength,
3084    // Index of currently firing callback (modified by remove if needed)
3085    firingIndex,
3086    // Actual callback list
3087    list = [],
3088    // Stack of fire calls for repeatable lists
3089    stack = !options.once && [],
3090    // Fire callbacks
3091    fire = function( data ) {
3092      memory = options.memory && data;
3093      fired = true;
3094      firingIndex = firingStart || 0;
3095      firingStart = 0;
3096      firingLength = list.length;
3097      firing = true;
3098      for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3099        if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3100          memory = false; // To prevent further calls using add
3101          break;
3102        }
3103      }
3104      firing = false;
3105      if ( list ) {
3106        if ( stack ) {
3107          if ( stack.length ) {
3108            fire( stack.shift() );
3109          }
3110        } else if ( memory ) {
3111          list = [];
3112        } else {
3113          self.disable();
3114        }
3115      }
3116    },
3117    // Actual Callbacks object
3118    self = {
3119      // Add a callback or a collection of callbacks to the list
3120      add: function() {
3121        if ( list ) {
3122          // First, we save the current length
3123          var start = list.length;
3124          (function add( args ) {
3125            jQuery.each( args, function( _, arg ) {
3126              var type = jQuery.type( arg );
3127              if ( type === "function" ) {
3128                if ( !options.unique || !self.has( arg ) ) {
3129                  list.push( arg );
3130                }
3131              } else if ( arg && arg.length && type !== "string" ) {
3132                // Inspect recursively
3133                add( arg );
3134              }
3135            });
3136          })( arguments );
3137          // Do we need to add the callbacks to the
3138          // current firing batch?
3139          if ( firing ) {
3140            firingLength = list.length;
3141          // With memory, if we're not firing then
3142          // we should call right away
3143          } else if ( memory ) {
3144            firingStart = start;
3145            fire( memory );
3146          }
3147        }
3148        return this;
3149      },
3150      // Remove a callback from the list
3151      remove: function() {
3152        if ( list ) {
3153          jQuery.each( arguments, function( _, arg ) {
3154            var index;
3155            while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3156              list.splice( index, 1 );
3157              // Handle firing indexes
3158              if ( firing ) {
3159                if ( index <= firingLength ) {
3160                  firingLength--;
3161                }
3162                if ( index <= firingIndex ) {
3163                  firingIndex--;
3164                }
3165              }
3166            }
3167          });
3168        }
3169        return this;
3170      },
3171      // Check if a given callback is in the list.
3172      // If no argument is given, return whether or not list has callbacks attached.
3173      has: function( fn ) {
3174        return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3175      },
3176      // Remove all callbacks from the list
3177      empty: function() {
3178        list = [];
3179        firingLength = 0;
3180        return this;
3181      },
3182      // Have the list do nothing anymore
3183      disable: function() {
3184        list = stack = memory = undefined;
3185        return this;
3186      },
3187      // Is it disabled?
3188      disabled: function() {
3189        return !list;
3190      },
3191      // Lock the list in its current state
3192      lock: function() {
3193        stack = undefined;
3194        if ( !memory ) {
3195          self.disable();
3196        }
3197        return this;
3198      },
3199      // Is it locked?
3200      locked: function() {
3201        return !stack;
3202      },
3203      // Call all callbacks with the given context and arguments
3204      fireWith: function( context, args ) {
3205        if ( list && ( !fired || stack ) ) {
3206          args = args || [];
3207          args = [ context, args.slice ? args.slice() : args ];
3208          if ( firing ) {
3209            stack.push( args );
3210          } else {
3211            fire( args );
3212          }
3213        }
3214        return this;
3215      },
3216      // Call all the callbacks with the given arguments
3217      fire: function() {
3218        self.fireWith( this, arguments );
3219        return this;
3220      },
3221      // To know if the callbacks have already been called at least once
3222      fired: function() {
3223        return !!fired;
3224      }
3225    };
3226
3227  return self;
3228};
3229
3230
3231jQuery.extend({
3232
3233  Deferred: function( func ) {
3234    var tuples = [
3235        // action, add listener, listener list, final state
3236        [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3237        [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3238        [ "notify", "progress", jQuery.Callbacks("memory") ]
3239      ],
3240      state = "pending",
3241      promise = {
3242        state: function() {
3243          return state;
3244        },
3245        always: function() {
3246          deferred.done( arguments ).fail( arguments );
3247          return this;
3248        },
3249        then: function( /* fnDone, fnFail, fnProgress */ ) {
3250          var fns = arguments;
3251          return jQuery.Deferred(function( newDefer ) {
3252            jQuery.each( tuples, function( i, tuple ) {
3253              var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3254              // deferred[ done | fail | progress ] for forwarding actions to newDefer
3255              deferred[ tuple[1] ](function() {
3256                var returned = fn && fn.apply( this, arguments );
3257                if ( returned && jQuery.isFunction( returned.promise ) ) {
3258                  returned.promise()
3259                    .done( newDefer.resolve )
3260                    .fail( newDefer.reject )
3261                    .progress( newDefer.notify );
3262                } else {
3263                  newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3264                }
3265              });
3266            });
3267            fns = null;
3268          }).promise();
3269        },
3270        // Get a promise for this deferred
3271        // If obj is provided, the promise aspect is added to the object
3272        promise: function( obj ) {
3273          return obj != null ? jQuery.extend( obj, promise ) : promise;
3274        }
3275      },
3276      deferred = {};
3277
3278    // Keep pipe for back-compat
3279    promise.pipe = promise.then;
3280
3281    // Add list-specific methods
3282    jQuery.each( tuples, function( i, tuple ) {
3283      var list = tuple[ 2 ],
3284        stateString = tuple[ 3 ];
3285
3286      // promise[ done | fail | progress ] = list.add
3287      promise[ tuple[1] ] = list.add;
3288
3289      // Handle state
3290      if ( stateString ) {
3291        list.add(function() {
3292          // state = [ resolved | rejected ]
3293          state = stateString;
3294
3295        // [ reject_list | resolve_list ].disable; progress_list.lock
3296        }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3297      }
3298
3299      // deferred[ resolve | reject | notify ]
3300      deferred[ tuple[0] ] = function() {
3301        deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3302        return this;
3303      };
3304      deferred[ tuple[0] + "With" ] = list.fireWith;
3305    });
3306
3307    // Make the deferred a promise
3308    promise.promise( deferred );
3309
3310    // Call given func if any
3311    if ( func ) {
3312      func.call( deferred, deferred );
3313    }
3314
3315    // All done!
3316    return deferred;
3317  },
3318
3319  // Deferred helper
3320  when: function( subordinate /* , ..., subordinateN */ ) {
3321    var i = 0,
3322      resolveValues = slice.call( arguments ),
3323      length = resolveValues.length,
3324
3325      // the count of uncompleted subordinates
3326      remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3327
3328      // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3329      deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3330
3331      // Update function for both resolve and progress values
3332      updateFunc = function( i, contexts, values ) {
3333        return function( value ) {
3334          contexts[ i ] = this;
3335          values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3336          if ( values === progressValues ) {
3337            deferred.notifyWith( contexts, values );
3338          } else if ( !( --remaining ) ) {
3339            deferred.resolveWith( contexts, values );
3340          }
3341        };
3342      },
3343
3344      progressValues, progressContexts, resolveContexts;
3345
3346    // Add listeners to Deferred subordinates; treat others as resolved
3347    if ( length > 1 ) {
3348      progressValues = new Array( length );
3349      progressContexts = new Array( length );
3350      resolveContexts = new Array( length );
3351      for ( ; i < length; i++ ) {
3352        if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3353          resolveValues[ i ].promise()
3354            .done( updateFunc( i, resolveContexts, resolveValues ) )
3355            .fail( deferred.reject )
3356            .progress( updateFunc( i, progressContexts, progressValues ) );
3357        } else {
3358          --remaining;
3359        }
3360      }
3361    }
3362
3363    // If we're not waiting on anything, resolve the master
3364    if ( !remaining ) {
3365      deferred.resolveWith( resolveContexts, resolveValues );
3366    }
3367
3368    return deferred.promise();
3369  }
3370});
3371
3372
3373// The deferred used on DOM ready
3374var readyList;
3375
3376jQuery.fn.ready = function( fn ) {
3377  // Add the callback
3378  jQuery.ready.promise().done( fn );
3379
3380  return this;
3381};
3382
3383jQuery.extend({
3384  // Is the DOM ready to be used? Set to true once it occurs.
3385  isReady: false,
3386
3387  // A counter to track how many items to wait for before
3388  // the ready event fires. See #6781
3389  readyWait: 1,
3390
3391  // Hold (or release) the ready event
3392  holdReady: function( hold ) {
3393    if ( hold ) {
3394      jQuery.readyWait++;
3395    } else {
3396      jQuery.ready( true );
3397    }
3398  },
3399
3400  // Handle when the DOM is ready
3401  ready: function( wait ) {
3402
3403    // Abort if there are pending holds or we're already ready
3404    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3405      return;
3406    }
3407
3408    // Remember that the DOM is ready
3409    jQuery.isReady = true;
3410
3411    // If a normal DOM Ready event fired, decrement, and wait if need be
3412    if ( wait !== true && --jQuery.readyWait > 0 ) {
3413      return;
3414    }
3415
3416    // If there are functions bound, to execute
3417    readyList.resolveWith( document, [ jQuery ] );
3418
3419    // Trigger any bound ready events
3420    if ( jQuery.fn.triggerHandler ) {
3421      jQuery( document ).triggerHandler( "ready" );
3422      jQuery( document ).off( "ready" );
3423    }
3424  }
3425});
3426
3427/**
3428 * The ready event handler and self cleanup method
3429 */
3430function completed() {
3431  document.removeEventListener( "DOMContentLoaded", completed, false );
3432  window.removeEventListener( "load", completed, false );
3433  jQuery.ready();
3434}
3435
3436jQuery.ready.promise = function( obj ) {
3437  if ( !readyList ) {
3438
3439    readyList = jQuery.Deferred();
3440
3441    // Catch cases where $(document).ready() is called after the browser event has already occurred.
3442    // We once tried to use readyState "interactive" here, but it caused issues like the one
3443    // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
3444    if ( document.readyState === "complete" ) {
3445      // Handle it asynchronously to allow scripts the opportunity to delay ready
3446      setTimeout( jQuery.ready );
3447
3448    } else {
3449
3450      // Use the handy event callback
3451      document.addEventListener( "DOMContentLoaded", completed, false );
3452
3453      // A fallback to window.onload, that will always work
3454      window.addEventListener( "load", completed, false );
3455    }
3456  }
3457  return readyList.promise( obj );
3458};
3459
3460// Kick off the DOM ready check even if the user does not
3461jQuery.ready.promise();
3462
3463
3464
3465
3466// Multifunctional method to get and set values of a collection
3467// The value/s can optionally be executed if it's a function
3468var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3469  var i = 0,
3470    len = elems.length,
3471    bulk = key == null;
3472
3473  // Sets many values
3474  if ( jQuery.type( key ) === "object" ) {
3475    chainable = true;
3476    for ( i in key ) {
3477      jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
3478    }
3479
3480  // Sets one value
3481  } else if ( value !== undefined ) {
3482    chainable = true;
3483
3484    if ( !jQuery.isFunction( value ) ) {
3485      raw = true;
3486    }
3487
3488    if ( bulk ) {
3489      // Bulk operations run against the entire set
3490      if ( raw ) {
3491        fn.call( elems, value );
3492        fn = null;
3493
3494      // ...except when executing function values
3495      } else {
3496        bulk = fn;
3497        fn = function( elem, key, value ) {
3498          return bulk.call( jQuery( elem ), value );
3499        };
3500      }
3501    }
3502
3503    if ( fn ) {
3504      for ( ; i < len; i++ ) {
3505        fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
3506      }
3507    }
3508  }
3509
3510  return chainable ?
3511    elems :
3512
3513    // Gets
3514    bulk ?
3515      fn.call( elems ) :
3516      len ? fn( elems[0], key ) : emptyGet;
3517};
3518
3519
3520/**
3521 * Determines whether an object can have data
3522 */
3523jQuery.acceptData = function( owner ) {
3524  // Accepts only:
3525  //  - Node
3526  //    - Node.ELEMENT_NODE
3527  //    - Node.DOCUMENT_NODE
3528  //  - Object
3529  //    - Any
3530  /* jshint -W018 */
3531  return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3532};
3533
3534
3535function Data() {
3536  // Support: Android<4,
3537  // Old WebKit does not have Object.preventExtensions/freeze method,
3538  // return new empty object instead with no [[set]] accessor
3539  Object.defineProperty( this.cache = {}, 0, {
3540    get: function() {
3541      return {};
3542    }
3543  });
3544
3545  this.expando = jQuery.expando + Data.uid++;
3546}
3547
3548Data.uid = 1;
3549Data.accepts = jQuery.acceptData;
3550
3551Data.prototype = {
3552  key: function( owner ) {
3553    // We can accept data for non-element nodes in modern browsers,
3554    // but we should not, see #8335.
3555    // Always return the key for a frozen object.
3556    if ( !Data.accepts( owner ) ) {
3557      return 0;
3558    }
3559
3560    var descriptor = {},
3561      // Check if the owner object already has a cache key
3562      unlock = owner[ this.expando ];
3563
3564    // If not, create one
3565    if ( !unlock ) {
3566      unlock = Data.uid++;
3567
3568      // Secure it in a non-enumerable, non-writable property
3569      try {
3570        descriptor[ this.expando ] = { value: unlock };
3571        Object.defineProperties( owner, descriptor );
3572
3573      // Support: Android<4
3574      // Fallback to a less secure definition
3575      } catch ( e ) {
3576        descriptor[ this.expando ] = unlock;
3577        jQuery.extend( owner, descriptor );
3578      }
3579    }
3580
3581    // Ensure the cache object
3582    if ( !this.cache[ unlock ] ) {
3583      this.cache[ unlock ] = {};
3584    }
3585
3586    return unlock;
3587  },
3588  set: function( owner, data, value ) {
3589    var prop,
3590      // There may be an unlock assigned to this node,
3591      // if there is no entry for this "owner", create one inline
3592      // and set the unlock as though an owner entry had always existed
3593      unlock = this.key( owner ),
3594      cache = this.cache[ unlock ];
3595
3596    // Handle: [ owner, key, value ] args
3597    if ( typeof data === "string" ) {
3598      cache[ data ] = value;
3599
3600    // Handle: [ owner, { properties } ] args
3601    } else {
3602      // Fresh assignments by object are shallow copied
3603      if ( jQuery.isEmptyObject( cache ) ) {
3604        jQuery.extend( this.cache[ unlock ], data );
3605      // Otherwise, copy the properties one-by-one to the cache object
3606      } else {
3607        for ( prop in data ) {
3608          cache[ prop ] = data[ prop ];
3609        }
3610      }
3611    }
3612    return cache;
3613  },
3614  get: function( owner, key ) {
3615    // Either a valid cache is found, or will be created.
3616    // New caches will be created and the unlock returned,
3617    // allowing direct access to the newly created
3618    // empty data object. A valid owner object must be provided.
3619    var cache = this.cache[ this.key( owner ) ];
3620
3621    return key === undefined ?
3622      cache : cache[ key ];
3623  },
3624  access: function( owner, key, value ) {
3625    var stored;
3626    // In cases where either:
3627    //
3628    //   1. No key was specified
3629    //   2. A string key was specified, but no value provided
3630    //
3631    // Take the "read" path and allow the get method to determine
3632    // which value to return, respectively either:
3633    //
3634    //   1. The entire cache object
3635    //   2. The data stored at the key
3636    //
3637    if ( key === undefined ||
3638        ((key && typeof key === "string") && value === undefined) ) {
3639
3640      stored = this.get( owner, key );
3641
3642      return stored !== undefined ?
3643        stored : this.get( owner, jQuery.camelCase(key) );
3644    }
3645
3646    // [*]When the key is not a string, or both a key and value
3647    // are specified, set or extend (existing objects) with either:
3648    //
3649    //   1. An object of properties
3650    //   2. A key and value
3651    //
3652    this.set( owner, key, value );
3653
3654    // Since the "set" path can have two possible entry points
3655    // return the expected data based on which path was taken[*]
3656    return value !== undefined ? value : key;
3657  },
3658  remove: function( owner, key ) {
3659    var i, name, camel,
3660      unlock = this.key( owner ),
3661      cache = this.cache[ unlock ];
3662
3663    if ( key === undefined ) {
3664      this.cache[ unlock ] = {};
3665
3666    } else {
3667      // Support array or space separated string of keys
3668      if ( jQuery.isArray( key ) ) {
3669        // If "name" is an array of keys...
3670        // When data is initially created, via ("key", "val") signature,
3671        // keys will be converted to camelCase.
3672        // Since there is no way to tell _how_ a key was added, remove
3673        // both plain key and camelCase key. #12786
3674        // This will only penalize the array argument path.
3675        name = key.concat( key.map( jQuery.camelCase ) );
3676      } else {
3677        camel = jQuery.camelCase( key );
3678        // Try the string as a key before any manipulation
3679        if ( key in cache ) {
3680          name = [ key, camel ];
3681        } else {
3682          // If a key with the spaces exists, use it.
3683          // Otherwise, create an array by matching non-whitespace
3684          name = camel;
3685          name = name in cache ?
3686            [ name ] : ( name.match( rnotwhite ) || [] );
3687        }
3688      }
3689
3690      i = name.length;
3691      while ( i-- ) {
3692        delete cache[ name[ i ] ];
3693      }
3694    }
3695  },
3696  hasData: function( owner ) {
3697    return !jQuery.isEmptyObject(
3698      this.cache[ owner[ this.expando ] ] || {}
3699    );
3700  },
3701  discard: function( owner ) {
3702    if ( owner[ this.expando ] ) {
3703      delete this.cache[ owner[ this.expando ] ];
3704    }
3705  }
3706};
3707var data_priv = new Data();
3708
3709var data_user = new Data();
3710
3711
3712
3713//  Implementation Summary
3714//
3715//  1. Enforce API surface and semantic compatibility with 1.9.x branch
3716//  2. Improve the module's maintainability by reducing the storage
3717//    paths to a single mechanism.
vendor: 4,560 bytes, lines 3718-3864
3718//  3. Use the same single mechanism to support "private" and "user" data.
3719//  4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
3720//  5. Avoid exposing implementation details on user objects (eg. expando properties)
3721//  6. Provide a clear path for implementation upgrade to WeakMap in 2014
3722
3723var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3724  rmultiDash = /([A-Z])/g;
3725
3726function dataAttr( elem, key, data ) {
3727  var name;
3728
3729  // If nothing was found internally, try to fetch any
3730  // data from the HTML5 data-* attribute
3731  if ( data === undefined && elem.nodeType === 1 ) {
3732    name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3733    data = elem.getAttribute( name );
3734
3735    if ( typeof data === "string" ) {
3736      try {
3737        data = data === "true" ? true :
3738          data === "false" ? false :
3739          data === "null" ? null :
3740          // Only convert to a number if it doesn't change the string
3741          +data + "" === data ? +data :
3742          rbrace.test( data ) ? jQuery.parseJSON( data ) :
3743          data;
3744      } catch( e ) {}
3745
3746      // Make sure we set the data so it isn't changed later
3747      data_user.set( elem, key, data );
3748    } else {
3749      data = undefined;
3750    }
3751  }
3752  return data;
3753}
3754
3755jQuery.extend({
3756  hasData: function( elem ) {
3757    return data_user.hasData( elem ) || data_priv.hasData( elem );
3758  },
3759
3760  data: function( elem, name, data ) {
3761    return data_user.access( elem, name, data );
3762  },
3763
3764  removeData: function( elem, name ) {
3765    data_user.remove( elem, name );
3766  },
3767
3768  // TODO: Now that all calls to _data and _removeData have been replaced
3769  // with direct calls to data_priv methods, these can be deprecated.
3770  _data: function( elem, name, data ) {
3771    return data_priv.access( elem, name, data );
3772  },
3773
3774  _removeData: function( elem, name ) {
3775    data_priv.remove( elem, name );
3776  }
3777});
3778
3779jQuery.fn.extend({
3780  data: function( key, value ) {
3781    var i, name, data,
3782      elem = this[ 0 ],
3783      attrs = elem && elem.attributes;
3784
3785    // Gets all values
3786    if ( key === undefined ) {
3787      if ( this.length ) {
3788        data = data_user.get( elem );
3789
3790        if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
3791          i = attrs.length;
3792          while ( i-- ) {
3793
3794            // Support: IE11+
3795            // The attrs elements can be null (#14894)
3796            if ( attrs[ i ] ) {
3797              name = attrs[ i ].name;
3798              if ( name.indexOf( "data-" ) === 0 ) {
3799                name = jQuery.camelCase( name.slice(5) );
3800                dataAttr( elem, name, data[ name ] );
3801              }
3802            }
3803          }
3804          data_priv.set( elem, "hasDataAttrs", true );
3805        }
3806      }
3807
3808      return data;
3809    }
3810
3811    // Sets multiple values
3812    if ( typeof key === "object" ) {
3813      return this.each(function() {
3814        data_user.set( this, key );
3815      });
3816    }
3817
3818    return access( this, function( value ) {
3819      var data,
3820        camelKey = jQuery.camelCase( key );
3821
3822      // The calling jQuery object (element matches) is not empty
3823      // (and therefore has an element appears at this[ 0 ]) and the
3824      // `value` parameter was not undefined. An empty jQuery object
3825      // will result in `undefined` for elem = this[ 0 ] which will
3826      // throw an exception if an attempt to read a data cache is made.
3827      if ( elem && value === undefined ) {
3828        // Attempt to get data from the cache
3829        // with the key as-is
3830        data = data_user.get( elem, key );
3831        if ( data !== undefined ) {
3832          return data;
3833        }
3834
3835        // Attempt to get data from the cache
3836        // with the key camelized
3837        data = data_user.get( elem, camelKey );
3838        if ( data !== undefined ) {
3839          return data;
3840        }
3841
3842        // Attempt to "discover" the data in
3843        // HTML5 custom data-* attrs
3844        data = dataAttr( elem, camelKey, undefined );
3845        if ( data !== undefined ) {
3846          return data;
3847        }
3848
3849        // We tried really hard, but the data doesn't exist.
3850        return;
3851      }
3852
3853      // Set the data...
3854      this.each(function() {
3855        // First, attempt to store a copy or reference of any
3856        // data that might've been store with a camelCased key.
3857        var data = data_user.get( this, camelKey );
3858
3859        // For HTML5 data-* attribute interop, we have to
3860        // store property names with dashes in a camelCase form.
3861        // This might not apply to all properties...*
3862        data_user.set( this, camelKey, value );
3863
3864        // *... In the case of properties that might _actually_
vendor: 4,251 bytes, lines 3865-4033
3865        // have dashes, we need to also store a copy of that
3866        // unchanged property.
3867        if ( key.indexOf("-") !== -1 && data !== undefined ) {
3868          data_user.set( this, key, value );
3869        }
3870      });
3871    }, null, value, arguments.length > 1, null, true );
3872  },
3873
3874  removeData: function( key ) {
3875    return this.each(function() {
3876      data_user.remove( this, key );
3877    });
3878  }
3879});
3880
3881
3882jQuery.extend({
3883  queue: function( elem, type, data ) {
3884    var queue;
3885
3886    if ( elem ) {
3887      type = ( type || "fx" ) + "queue";
3888      queue = data_priv.get( elem, type );
3889
3890      // Speed up dequeue by getting out quickly if this is just a lookup
3891      if ( data ) {
3892        if ( !queue || jQuery.isArray( data ) ) {
3893          queue = data_priv.access( elem, type, jQuery.makeArray(data) );
3894        } else {
3895          queue.push( data );
3896        }
3897      }
3898      return queue || [];
3899    }
3900  },
3901
3902  dequeue: function( elem, type ) {
3903    type = type || "fx";
3904
3905    var queue = jQuery.queue( elem, type ),
3906      startLength = queue.length,
3907      fn = queue.shift(),
3908      hooks = jQuery._queueHooks( elem, type ),
3909      next = function() {
3910        jQuery.dequeue( elem, type );
3911      };
3912
3913    // If the fx queue is dequeued, always remove the progress sentinel
3914    if ( fn === "inprogress" ) {
3915      fn = queue.shift();
3916      startLength--;
3917    }
3918
3919    if ( fn ) {
3920
3921      // Add a progress sentinel to prevent the fx queue from being
3922      // automatically dequeued
3923      if ( type === "fx" ) {
3924        queue.unshift( "inprogress" );
3925      }
3926
3927      // Clear up the last queue stop function
3928      delete hooks.stop;
3929      fn.call( elem, next, hooks );
3930    }
3931
3932    if ( !startLength && hooks ) {
3933      hooks.empty.fire();
3934    }
3935  },
3936
3937  // Not public - generate a queueHooks object, or return the current one
3938  _queueHooks: function( elem, type ) {
3939    var key = type + "queueHooks";
3940    return data_priv.get( elem, key ) || data_priv.access( elem, key, {
3941      empty: jQuery.Callbacks("once memory").add(function() {
3942        data_priv.remove( elem, [ type + "queue", key ] );
3943      })
3944    });
3945  }
3946});
3947
3948jQuery.fn.extend({
3949  queue: function( type, data ) {
3950    var setter = 2;
3951
3952    if ( typeof type !== "string" ) {
3953      data = type;
3954      type = "fx";
3955      setter--;
3956    }
3957
3958    if ( arguments.length < setter ) {
3959      return jQuery.queue( this[0], type );
3960    }
3961
3962    return data === undefined ?
3963      this :
3964      this.each(function() {
3965        var queue = jQuery.queue( this, type, data );
3966
3967        // Ensure a hooks for this queue
3968        jQuery._queueHooks( this, type );
3969
3970        if ( type === "fx" && queue[0] !== "inprogress" ) {
3971          jQuery.dequeue( this, type );
3972        }
3973      });
3974  },
3975  dequeue: function( type ) {
3976    return this.each(function() {
3977      jQuery.dequeue( this, type );
3978    });
3979  },
3980  clearQueue: function( type ) {
3981    return this.queue( type || "fx", [] );
3982  },
3983  // Get a promise resolved when queues of a certain type
3984  // are emptied (fx is the type by default)
3985  promise: function( type, obj ) {
3986    var tmp,
3987      count = 1,
3988      defer = jQuery.Deferred(),
3989      elements = this,
3990      i = this.length,
3991      resolve = function() {
3992        if ( !( --count ) ) {
3993          defer.resolveWith( elements, [ elements ] );
3994        }
3995      };
3996
3997    if ( typeof type !== "string" ) {
3998      obj = type;
3999      type = undefined;
4000    }
4001    type = type || "fx";
4002
4003    while ( i-- ) {
4004      tmp = data_priv.get( elements[ i ], type + "queueHooks" );
4005      if ( tmp && tmp.empty ) {
4006        count++;
4007        tmp.empty.add( resolve );
4008      }
4009    }
4010    resolve();
4011    return defer.promise( obj );
4012  }
4013});
4014var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
4015
4016var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4017
4018var isHidden = function( elem, el ) {
4019    // isHidden might be called from jQuery#filter function;
4020    // in that case, element will be second argument
4021    elem = el || elem;
4022    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
4023  };
4024
4025var rcheckableType = (/^(?:checkbox|radio)$/i);
4026
4027
4028
4029(function() {
4030  var fragment = document.createDocumentFragment(),
4031    div = fragment.appendChild( document.createElement( "div" ) ),
4032    input = document.createElement( "input" );
4033
vendor: 14,010 bytes, lines 4034-4462
4034  // Support: Safari<=5.1
4035  // Check state lost if the name is set (#11217)
4036  // Support: Windows Web Apps (WWA)
4037  // `name` and `type` must use .setAttribute for WWA (#14901)
4038  input.setAttribute( "type", "radio" );
4039  input.setAttribute( "checked", "checked" );
4040  input.setAttribute( "name", "t" );
4041
4042  div.appendChild( input );
4043
4044  // Support: Safari<=5.1, Android<4.2
4045  // Older WebKit doesn't clone checked state correctly in fragments
4046  support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4047
4048  // Support: IE<=11+
4049  // Make sure textarea (and checkbox) defaultValue is properly cloned
4050  div.innerHTML = "<textarea>x</textarea>";
4051  support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4052})();
4053var strundefined = typeof undefined;
4054
4055
4056
4057support.focusinBubbles = "onfocusin" in window;
4058
4059
4060var
4061  rkeyEvent = /^key/,
4062  rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
4063  rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4064  rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4065
4066function returnTrue() {
4067  return true;
4068}
4069
4070function returnFalse() {
4071  return false;
4072}
4073
4074function safeActiveElement() {
4075  try {
4076    return document.activeElement;
4077  } catch ( err ) { }
4078}
4079
4080/*
4081 * Helper functions for managing events -- not part of the public interface.
4082 * Props to Dean Edwards' addEvent library for many of the ideas.
4083 */
4084jQuery.event = {
4085
4086  global: {},
4087
4088  add: function( elem, types, handler, data, selector ) {
4089
4090    var handleObjIn, eventHandle, tmp,
4091      events, t, handleObj,
4092      special, handlers, type, namespaces, origType,
4093      elemData = data_priv.get( elem );
4094
4095    // Don't attach events to noData or text/comment nodes (but allow plain objects)
4096    if ( !elemData ) {
4097      return;
4098    }
4099
4100    // Caller can pass in an object of custom data in lieu of the handler
4101    if ( handler.handler ) {
4102      handleObjIn = handler;
4103      handler = handleObjIn.handler;
4104      selector = handleObjIn.selector;
4105    }
4106
4107    // Make sure that the handler has a unique ID, used to find/remove it later
4108    if ( !handler.guid ) {
4109      handler.guid = jQuery.guid++;
4110    }
4111
4112    // Init the element's event structure and main handler, if this is the first
4113    if ( !(events = elemData.events) ) {
4114      events = elemData.events = {};
4115    }
4116    if ( !(eventHandle = elemData.handle) ) {
4117      eventHandle = elemData.handle = function( e ) {
4118        // Discard the second event of a jQuery.event.trigger() and
4119        // when an event is called after a page has unloaded
4120        return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
4121          jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4122      };
4123    }
4124
4125    // Handle multiple events separated by a space
4126    types = ( types || "" ).match( rnotwhite ) || [ "" ];
4127    t = types.length;
4128    while ( t-- ) {
4129      tmp = rtypenamespace.exec( types[t] ) || [];
4130      type = origType = tmp[1];
4131      namespaces = ( tmp[2] || "" ).split( "." ).sort();
4132
4133      // There *must* be a type, no attaching namespace-only handlers
4134      if ( !type ) {
4135        continue;
4136      }
4137
4138      // If event changes its type, use the special event handlers for the changed type
4139      special = jQuery.event.special[ type ] || {};
4140
4141      // If selector defined, determine special event api type, otherwise given type
4142      type = ( selector ? special.delegateType : special.bindType ) || type;
4143
4144      // Update special based on newly reset type
4145      special = jQuery.event.special[ type ] || {};
4146
4147      // handleObj is passed to all event handlers
4148      handleObj = jQuery.extend({
4149        type: type,
4150        origType: origType,
4151        data: data,
4152        handler: handler,
4153        guid: handler.guid,
4154        selector: selector,
4155        needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4156        namespace: namespaces.join(".")
4157      }, handleObjIn );
4158
4159      // Init the event handler queue if we're the first
4160      if ( !(handlers = events[ type ]) ) {
4161        handlers = events[ type ] = [];
4162        handlers.delegateCount = 0;
4163
4164        // Only use addEventListener if the special events handler returns false
4165        if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4166          if ( elem.addEventListener ) {
4167            elem.addEventListener( type, eventHandle, false );
4168          }
4169        }
4170      }
4171
4172      if ( special.add ) {
4173        special.add.call( elem, handleObj );
4174
4175        if ( !handleObj.handler.guid ) {
4176          handleObj.handler.guid = handler.guid;
4177        }
4178      }
4179
4180      // Add to the element's handler list, delegates in front
4181      if ( selector ) {
4182        handlers.splice( handlers.delegateCount++, 0, handleObj );
4183      } else {
4184        handlers.push( handleObj );
4185      }
4186
4187      // Keep track of which events have ever been used, for event optimization
4188      jQuery.event.global[ type ] = true;
4189    }
4190
4191  },
4192
4193  // Detach an event or set of events from an element
4194  remove: function( elem, types, handler, selector, mappedTypes ) {
4195
4196    var j, origCount, tmp,
4197      events, t, handleObj,
4198      special, handlers, type, namespaces, origType,
4199      elemData = data_priv.hasData( elem ) && data_priv.get( elem );
4200
4201    if ( !elemData || !(events = elemData.events) ) {
4202      return;
4203    }
4204
4205    // Once for each type.namespace in types; type may be omitted
4206    types = ( types || "" ).match( rnotwhite ) || [ "" ];
4207    t = types.length;
4208    while ( t-- ) {
4209      tmp = rtypenamespace.exec( types[t] ) || [];
4210      type = origType = tmp[1];
4211      namespaces = ( tmp[2] || "" ).split( "." ).sort();
4212
4213      // Unbind all events (on this namespace, if provided) for the element
4214      if ( !type ) {
4215        for ( type in events ) {
4216          jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4217        }
4218        continue;
4219      }
4220
4221      special = jQuery.event.special[ type ] || {};
4222      type = ( selector ? special.delegateType : special.bindType ) || type;
4223      handlers = events[ type ] || [];
4224      tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4225
4226      // Remove matching events
4227      origCount = j = handlers.length;
4228      while ( j-- ) {
4229        handleObj = handlers[ j ];
4230
4231        if ( ( mappedTypes || origType === handleObj.origType ) &&
4232          ( !handler || handler.guid === handleObj.guid ) &&
4233          ( !tmp || tmp.test( handleObj.namespace ) ) &&
4234          ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4235          handlers.splice( j, 1 );
4236
4237          if ( handleObj.selector ) {
4238            handlers.delegateCount--;
4239          }
4240          if ( special.remove ) {
4241            special.remove.call( elem, handleObj );
4242          }
4243        }
4244      }
4245
4246      // Remove generic event handler if we removed something and no more handlers exist
4247      // (avoids potential for endless recursion during removal of special event handlers)
4248      if ( origCount && !handlers.length ) {
4249        if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4250          jQuery.removeEvent( elem, type, elemData.handle );
4251        }
4252
4253        delete events[ type ];
4254      }
4255    }
4256
4257    // Remove the expando if it's no longer used
4258    if ( jQuery.isEmptyObject( events ) ) {
4259      delete elemData.handle;
4260      data_priv.remove( elem, "events" );
4261    }
4262  },
4263
4264  trigger: function( event, data, elem, onlyHandlers ) {
4265
4266    var i, cur, tmp, bubbleType, ontype, handle, special,
4267      eventPath = [ elem || document ],
4268      type = hasOwn.call( event, "type" ) ? event.type : event,
4269      namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4270
4271    cur = tmp = elem = elem || document;
4272
4273    // Don't do events on text and comment nodes
4274    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4275      return;
4276    }
4277
4278    // focus/blur morphs to focusin/out; ensure we're not firing them right now
4279    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4280      return;
4281    }
4282
4283    if ( type.indexOf(".") >= 0 ) {
4284      // Namespaced trigger; create a regexp to match event type in handle()
4285      namespaces = type.split(".");
4286      type = namespaces.shift();
4287      namespaces.sort();
4288    }
4289    ontype = type.indexOf(":") < 0 && "on" + type;
4290
4291    // Caller can pass in a jQuery.Event object, Object, or just an event type string
4292    event = event[ jQuery.expando ] ?
4293      event :
4294      new jQuery.Event( type, typeof event === "object" && event );
4295
4296    // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4297    event.isTrigger = onlyHandlers ? 2 : 3;
4298    event.namespace = namespaces.join(".");
4299    event.namespace_re = event.namespace ?
4300      new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4301      null;
4302
4303    // Clean up the event in case it is being reused
4304    event.result = undefined;
4305    if ( !event.target ) {
4306      event.target = elem;
4307    }
4308
4309    // Clone any incoming data and prepend the event, creating the handler arg list
4310    data = data == null ?
4311      [ event ] :
4312      jQuery.makeArray( data, [ event ] );
4313
4314    // Allow special events to draw outside the lines
4315    special = jQuery.event.special[ type ] || {};
4316    if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4317      return;
4318    }
4319
4320    // Determine event propagation path in advance, per W3C events spec (#9951)
4321    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4322    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4323
4324      bubbleType = special.delegateType || type;
4325      if ( !rfocusMorph.test( bubbleType + type ) ) {
4326        cur = cur.parentNode;
4327      }
4328      for ( ; cur; cur = cur.parentNode ) {
4329        eventPath.push( cur );
4330        tmp = cur;
4331      }
4332
4333      // Only add window if we got to document (e.g., not plain obj or detached DOM)
4334      if ( tmp === (elem.ownerDocument || document) ) {
4335        eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4336      }
4337    }
4338
4339    // Fire handlers on the event path
4340    i = 0;
4341    while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4342
4343      event.type = i > 1 ?
4344        bubbleType :
4345        special.bindType || type;
4346
4347      // jQuery handler
4348      handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
4349      if ( handle ) {
4350        handle.apply( cur, data );
4351      }
4352
4353      // Native handler
4354      handle = ontype && cur[ ontype ];
4355      if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
4356        event.result = handle.apply( cur, data );
4357        if ( event.result === false ) {
4358          event.preventDefault();
4359        }
4360      }
4361    }
4362    event.type = type;
4363
4364    // If nobody prevented the default action, do it now
4365    if ( !onlyHandlers && !event.isDefaultPrevented() ) {
4366
4367      if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
4368        jQuery.acceptData( elem ) ) {
4369
4370        // Call a native DOM method on the target with the same name name as the event.
4371        // Don't do default actions on window, that's where global variables be (#6170)
4372        if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
4373
4374          // Don't re-trigger an onFOO event when we call its FOO() method
4375          tmp = elem[ ontype ];
4376
4377          if ( tmp ) {
4378            elem[ ontype ] = null;
4379          }
4380
4381          // Prevent re-triggering of the same event, since we already bubbled it above
4382          jQuery.event.triggered = type;
4383          elem[ type ]();
4384          jQuery.event.triggered = undefined;
4385
4386          if ( tmp ) {
4387            elem[ ontype ] = tmp;
4388          }
4389        }
4390      }
4391    }
4392
4393    return event.result;
4394  },
4395
4396  dispatch: function( event ) {
4397
4398    // Make a writable jQuery.Event from the native event object
4399    event = jQuery.event.fix( event );
4400
4401    var i, j, ret, matched, handleObj,
4402      handlerQueue = [],
4403      args = slice.call( arguments ),
4404      handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
4405      special = jQuery.event.special[ event.type ] || {};
4406
4407    // Use the fix-ed jQuery.Event rather than the (read-only) native event
4408    args[0] = event;
4409    event.delegateTarget = this;
4410
4411    // Call the preDispatch hook for the mapped type, and let it bail if desired
4412    if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4413      return;
4414    }
4415
4416    // Determine handlers
4417    handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4418
4419    // Run delegates first; they may want to stop propagation beneath us
4420    i = 0;
4421    while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
4422      event.currentTarget = matched.elem;
4423
4424      j = 0;
4425      while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
4426
4427        // Triggered event must either 1) have no namespace, or 2) have namespace(s)
4428        // a subset or equal to those in the bound event (both can have no namespace).
4429        if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
4430
4431          event.handleObj = handleObj;
4432          event.data = handleObj.data;
4433
4434          ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
4435              .apply( matched.elem, args );
4436
4437          if ( ret !== undefined ) {
4438            if ( (event.result = ret) === false ) {
4439              event.preventDefault();
4440              event.stopPropagation();
4441            }
4442          }
4443        }
4444      }
4445    }
4446
4447    // Call the postDispatch hook for the mapped type
4448    if ( special.postDispatch ) {
4449      special.postDispatch.call( this, event );
4450    }
4451
4452    return event.result;
4453  },
4454
4455  handlers: function( event, handlers ) {
4456    var i, matches, sel, handleObj,
4457      handlerQueue = [],
4458      delegateCount = handlers.delegateCount,
4459      cur = event.target;
4460
4461    // Find delegate handlers
4462    // Black-hole SVG <use> instance trees (#13180)
4463    // Avoid non-left-click bubbling in Firefox (#3861)
4464    if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
4465
4466      for ( ; cur !== this; cur = cur.parentNode || this ) {
4467
4468        // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4469        if ( cur.disabled !== true || event.type !== "click" ) {
4470          matches = [];
4471          for ( i = 0; i < delegateCount; i++ ) {
4472            handleObj = handlers[ i ];
4473
4474            // Don't conflict with Object.prototype properties (#13203)
4475            sel = handleObj.selector + " ";
4476
4477            if ( matches[ sel ] === undefined ) {
4478              matches[ sel ] = handleObj.needsContext ?
4479                jQuery( sel, this ).index( cur ) >= 0 :
4480                jQuery.find( sel, this, null, [ cur ] ).length;
4481            }
4482            if ( matches[ sel ] ) {
4483              matches.push( handleObj );
4484            }
4485          }
4486          if ( matches.length ) {
4487            handlerQueue.push({ elem: cur, handlers: matches });
4488          }
4489        }
4490      }
4491    }
4492
4493    // Add the remaining (directly-bound) handlers
4494    if ( delegateCount < handlers.length ) {
4495      handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
4496    }
4497
4498    return handlerQueue;
4499  },
4500
4501  // Includes some event props shared by KeyEvent and MouseEvent
4502  props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
4503
4504  fixHooks: {},
4505
4506  keyHooks: {
4507    props: "char charCode key keyCode".split(" "),
4508    filter: function( event, original ) {
4509
4510      // Add which for key events
4511      if ( event.which == null ) {
4512        event.which = original.charCode != null ? original.charCode : original.keyCode;
4513      }
4514
4515      return event;
4516    }
4517  },
4518
4519  mouseHooks: {
4520    props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
4521    filter: function( event, original ) {
4522      var eventDoc, doc, body,
4523        button = original.button;
4524
4525      // Calculate pageX/Y if missing and clientX/Y available
4526      if ( event.pageX == null && original.clientX != null ) {
4527        eventDoc = event.target.ownerDocument || document;
4528        doc = eventDoc.documentElement;
4529        body = eventDoc.body;
4530
4531        event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4532        event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
4533      }
4534
4535      // Add which for click: 1 === left; 2 === middle; 3 === right
4536      // Note: button is not normalized, so don't use it
4537      if ( !event.which && button !== undefined ) {
4538        event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4539      }
4540
4541      return event;
4542    }
4543  },
4544
4545  fix: function( event ) {
4546    if ( event[ jQuery.expando ] ) {
4547      return event;
4548    }
4549
4550    // Create a writable copy of the event object and normalize some properties
4551    var i, prop, copy,
4552      type = event.type,
4553      originalEvent = event,
4554      fixHook = this.fixHooks[ type ];
4555
4556    if ( !fixHook ) {
4557      this.fixHooks[ type ] = fixHook =
4558        rmouseEvent.test( type ) ? this.mouseHooks :
4559        rkeyEvent.test( type ) ? this.keyHooks :
4560        {};
4561    }
4562    copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4563
4564    event = new jQuery.Event( originalEvent );
4565
4566    i = copy.length;
4567    while ( i-- ) {
4568      prop = copy[ i ];
4569      event[ prop ] = originalEvent[ prop ];
4570    }
4571
4572    // Support: Cordova 2.5 (WebKit) (#13255)
4573    // All events should have a target; Cordova deviceready doesn't
4574    if ( !event.target ) {
4575      event.target = document;
4576    }
4577
4578    // Support: Safari 6.0+, Chrome<28
4579    // Target should not be a text node (#504, #13143)
4580    if ( event.target.nodeType === 3 ) {
4581      event.target = event.target.parentNode;
4582    }
4583
4584    return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4585  },
4586
4587  special: {
4588    load: {
4589      // Prevent triggered image.load events from bubbling to window.load
4590      noBubble: true
4591    },
4592    focus: {
4593      // Fire native event if possible so blur/focus sequence is correct
4594      trigger: function() {
4595        if ( this !== safeActiveElement() && this.focus ) {
4596          this.focus();
4597          return false;
4598        }
4599      },
4600      delegateType: "focusin"
4601    },
4602    blur: {
4603      trigger: function() {
4604        if ( this === safeActiveElement() && this.blur ) {
4605          this.blur();
4606          return false;
4607        }
4608      },
4609      delegateType: "focusout"
4610    },
4611    click: {
4612      // For checkbox, fire native event so checked state will be right
4613      trigger: function() {
4614        if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
4615          this.click();
4616          return false;
4617        }
4618      },
4619
4620      // For cross-browser consistency, don't fire native .click() on links
4621      _default: function( event ) {
4622        return jQuery.nodeName( event.target, "a" );
4623      }
4624    },
4625
4626    beforeunload: {
4627      postDispatch: function( event ) {
4628
4629        // Support: Firefox 20+
4630        // Firefox doesn't alert if the returnValue field is not set.
4631        if ( event.result !== undefined && event.originalEvent ) {
4632          event.originalEvent.returnValue = event.result;
4633        }
4634      }
4635    }
4636  },
4637
4638  simulate: function( type, elem, event, bubble ) {
4639    // Piggyback on a donor event to simulate a different one.
4640    // Fake originalEvent to avoid donor's stopPropagation, but if the
4641    // simulated event prevents default then we do the same on the donor.
4642    var e = jQuery.extend(
4643      new jQuery.Event(),
4644      event,
4645      {
4646        type: type,
4647        isSimulated: true,
4648        originalEvent: {}
4649      }
4650    );
4651    if ( bubble ) {
4652      jQuery.event.trigger( e, null, elem );
4653    } else {
4654      jQuery.event.dispatch.call( elem, e );
4655    }
4656    if ( e.isDefaultPrevented() ) {
4657      event.preventDefault();
4658    }
4659  }
4660};
4661
4662jQuery.removeEvent = function( elem, type, handle ) {
4663  if ( elem.removeEventListener ) {
4664    elem.removeEventListener( type, handle, false );
4665  }
4666};
4667
4668jQuery.Event = function( src, props ) {
4669  // Allow instantiation without the 'new' keyword
4670  if ( !(this instanceof jQuery.Event) ) {
4671    return new jQuery.Event( src, props );
4672  }
4673
4674  // Event object
4675  if ( src && src.type ) {
4676    this.originalEvent = src;
4677    this.type = src.type;
4678
4679    // Events bubbling up the document may have been marked as prevented
4680    // by a handler lower down the tree; reflect the correct value.
4681    this.isDefaultPrevented = src.defaultPrevented ||
4682        src.defaultPrevented === undefined &&
4683        // Support: Android<4.0
4684        src.returnValue === false ?
4685      returnTrue :
4686      returnFalse;
4687
4688  // Event type
4689  } else {
4690    this.type = src;
4691  }
4692
4693  // Put explicitly provided properties onto the event object
4694  if ( props ) {
4695    jQuery.extend( this, props );
4696  }
4697
4698  // Create a timestamp if incoming event doesn't have one
4699  this.timeStamp = src && src.timeStamp || jQuery.now();
4700
4701  // Mark it as fixed
4702  this[ jQuery.expando ] = true;
4703};
4704
4705// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4706// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4707jQuery.Event.prototype = {
4708  isDefaultPrevented: returnFalse,
4709  isPropagationStopped: returnFalse,
4710  isImmediatePropagationStopped: returnFalse,
4711
4712  preventDefault: function() {
4713    var e = this.originalEvent;
4714
4715    this.isDefaultPrevented = returnTrue;
4716
4717    if ( e && e.preventDefault ) {
4718      e.preventDefault();
4719    }
4720  },
4721  stopPropagation: function() {
4722    var e = this.originalEvent;
4723
4724    this.isPropagationStopped = returnTrue;
4725
4726    if ( e && e.stopPropagation ) {
4727      e.stopPropagation();
4728    }
4729  },
4730  stopImmediatePropagation: function() {
4731    var e = this.originalEvent;
4732
4733    this.isImmediatePropagationStopped = returnTrue;
4734
4735    if ( e && e.stopImmediatePropagation ) {
4736      e.stopImmediatePropagation();
4737    }
4738
4739    this.stopPropagation();
4740  }
4741};
4742
4743// Create mouseenter/leave events using mouseover/out and event-time checks
4744// Support: Chrome 15+
4745jQuery.each({
4746  mouseenter: "mouseover",
4747  mouseleave: "mouseout",
4748  pointerenter: "pointerover",
4749  pointerleave: "pointerout"
4750}, function( orig, fix ) {
4751  jQuery.event.special[ orig ] = {
4752    delegateType: fix,
4753    bindType: fix,
4754
4755    handle: function( event ) {
4756      var ret,
4757        target = this,
4758        related = event.relatedTarget,
4759        handleObj = event.handleObj;
4760
4761      // For mousenter/leave call the handler if related is outside the target.
4762      // NB: No relatedTarget if the mouse left/entered the browser window
4763      if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
4764        event.type = handleObj.origType;
4765        ret = handleObj.handler.apply( this, arguments );
4766        event.type = fix;
4767      }
4768      return ret;
4769    }
4770  };
4771});
4772
4773// Support: Firefox, Chrome, Safari
4774// Create "bubbling" focus and blur events
4775if ( !support.focusinBubbles ) {
4776  jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
4777
4778    // Attach a single capturing handler on the document while someone wants focusin/focusout
4779    var handler = function( event ) {
4780        jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
4781      };
4782
4783    jQuery.event.special[ fix ] = {
4784      setup: function() {
4785        var doc = this.ownerDocument || this,
4786          attaches = data_priv.access( doc, fix );
4787
4788        if ( !attaches ) {
4789          doc.addEventListener( orig, handler, true );
4790        }
4791        data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
4792      },
4793      teardown: function() {
4794        var doc = this.ownerDocument || this,
4795          attaches = data_priv.access( doc, fix ) - 1;
4796
4797        if ( !attaches ) {
4798          doc.removeEventListener( orig, handler, true );
4799          data_priv.remove( doc, fix );
4800
4801        } else {
4802          data_priv.access( doc, fix, attaches );
4803        }
4804      }
4805    };
4806  });
4807}
4808
4809jQuery.fn.extend({
4810
4811  on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
4812    var origFn, type;
4813
4814    // Types can be a map of types/handlers
4815    if ( typeof types === "object" ) {
4816      // ( types-Object, selector, data )
4817      if ( typeof selector !== "string" ) {
4818        // ( types-Object, data )
4819        data = data || selector;
4820        selector = undefined;
4821      }
4822      for ( type in types ) {
4823        this.on( type, selector, data, types[ type ], one );
4824      }
4825      return this;
4826    }
4827
4828    if ( data == null && fn == null ) {
4829      // ( types, fn )
4830      fn = selector;
4831      data = selector = undefined;
4832    } else if ( fn == null ) {
4833      if ( typeof selector === "string" ) {
4834        // ( types, selector, fn )
4835        fn = data;
4836        data = undefined;
4837      } else {
4838        // ( types, data, fn )
4839        fn = data;
4840        data = selector;
4841        selector = undefined;
4842      }
4843    }
4844    if ( fn === false ) {
4845      fn = returnFalse;
4846    } else if ( !fn ) {
4847      return this;
4848    }
4849
4850    if ( one === 1 ) {
4851      origFn = fn;
4852      fn = function( event ) {
4853        // Can use an empty set, since event contains the info
4854        jQuery().off( event );
4855        return origFn.apply( this, arguments );
4856      };
4857      // Use same guid so caller can remove using origFn
4858      fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4859    }
4860    return this.each( function() {
4861      jQuery.event.add( this, types, fn, data, selector );
4862    });
4863  },
4864  one: function( types, selector, data, fn ) {
4865    return this.on( types, selector, data, fn, 1 );
4866  },
4867  off: function( types, selector, fn ) {
4868    var handleObj, type;
4869    if ( types && types.preventDefault && types.handleObj ) {
4870      // ( event )  dispatched jQuery.Event
4871      handleObj = types.handleObj;
4872      jQuery( types.delegateTarget ).off(
4873        handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
4874        handleObj.selector,
4875        handleObj.handler
4876      );
4877      return this;
4878    }
4879    if ( typeof types === "object" ) {
4880      // ( types-object [, selector] )
4881      for ( type in types ) {
4882        this.off( type, selector, types[ type ] );
4883      }
4884      return this;
4885    }
4886    if ( selector === false || typeof selector === "function" ) {
4887      // ( types [, fn] )
4888      fn = selector;
4889      selector = undefined;
4890    }
4891    if ( fn === false ) {
4892      fn = returnFalse;
4893    }
4894    return this.each(function() {
4895      jQuery.event.remove( this, types, fn, selector );
4896    });
4897  },
4898
4899  trigger: function( type, data ) {
4900    return this.each(function() {
4901      jQuery.event.trigger( type, data, this );
4902    });
4903  },
4904  triggerHandler: function( type, data ) {
4905    var elem = this[0];
4906    if ( elem ) {
4907      return jQuery.event.trigger( type, data, elem, true );
4908    }
4909  }
4910});
4911
4912
4913var
4914  rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
4915  rtagName = /<([\w:]+)/,
vendor: 12,395 bytes, lines 4916-5352
4916  rhtml = /<|&#?\w+;/,
4917  rnoInnerhtml = /<(?:script|style|link)/i,
4918  // checked="checked" or checked
4919  rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
4920  rscriptType = /^$|\/(?:java|ecma)script/i,
4921  rscriptTypeMasked = /^true\/(.*)/,
4922  rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
4923
4924  // We have to close these tags to support XHTML (#13200)
4925  wrapMap = {
4926
4927    // Support: IE9
4928    option: [ 1, "<select multiple='multiple'>", "</select>" ],
4929
4930    thead: [ 1, "<table>", "</table>" ],
4931    col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4932    tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4933    td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4934
4935    _default: [ 0, "", "" ]
4936  };
4937
4938// Support: IE9
4939wrapMap.optgroup = wrapMap.option;
4940
4941wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4942wrapMap.th = wrapMap.td;
4943
4944// Support: 1.x compatibility
4945// Manipulating tables requires a tbody
4946function manipulationTarget( elem, content ) {
4947  return jQuery.nodeName( elem, "table" ) &&
4948    jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
4949
4950    elem.getElementsByTagName("tbody")[0] ||
4951      elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
4952    elem;
4953}
4954
4955// Replace/restore the type attribute of script elements for safe DOM manipulation
4956function disableScript( elem ) {
4957  elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
4958  return elem;
4959}
4960function restoreScript( elem ) {
4961  var match = rscriptTypeMasked.exec( elem.type );
4962
4963  if ( match ) {
4964    elem.type = match[ 1 ];
4965  } else {
4966    elem.removeAttribute("type");
4967  }
4968
4969  return elem;
4970}
4971
4972// Mark scripts as having already been evaluated
4973function setGlobalEval( elems, refElements ) {
4974  var i = 0,
4975    l = elems.length;
4976
4977  for ( ; i < l; i++ ) {
4978    data_priv.set(
4979      elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
4980    );
4981  }
4982}
4983
4984function cloneCopyEvent( src, dest ) {
4985  var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
4986
4987  if ( dest.nodeType !== 1 ) {
4988    return;
4989  }
4990
4991  // 1. Copy private data: events, handlers, etc.
4992  if ( data_priv.hasData( src ) ) {
4993    pdataOld = data_priv.access( src );
4994    pdataCur = data_priv.set( dest, pdataOld );
4995    events = pdataOld.events;
4996
4997    if ( events ) {
4998      delete pdataCur.handle;
4999      pdataCur.events = {};
5000
5001      for ( type in events ) {
5002        for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5003          jQuery.event.add( dest, type, events[ type ][ i ] );
5004        }
5005      }
5006    }
5007  }
5008
5009  // 2. Copy user data
5010  if ( data_user.hasData( src ) ) {
5011    udataOld = data_user.access( src );
5012    udataCur = jQuery.extend( {}, udataOld );
5013
5014    data_user.set( dest, udataCur );
5015  }
5016}
5017
5018function getAll( context, tag ) {
5019  var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
5020      context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
5021      [];
5022
5023  return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
5024    jQuery.merge( [ context ], ret ) :
5025    ret;
5026}
5027
5028// Fix IE bugs, see support tests
5029function fixInput( src, dest ) {
5030  var nodeName = dest.nodeName.toLowerCase();
5031
5032  // Fails to persist the checked state of a cloned checkbox or radio button.
5033  if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5034    dest.checked = src.checked;
5035
5036  // Fails to return the selected option to the default selected state when cloning options
5037  } else if ( nodeName === "input" || nodeName === "textarea" ) {
5038    dest.defaultValue = src.defaultValue;
5039  }
5040}
5041
5042jQuery.extend({
5043  clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5044    var i, l, srcElements, destElements,
5045      clone = elem.cloneNode( true ),
5046      inPage = jQuery.contains( elem.ownerDocument, elem );
5047
5048    // Fix IE cloning issues
5049    if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5050        !jQuery.isXMLDoc( elem ) ) {
5051
5052      // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
5053      destElements = getAll( clone );
5054      srcElements = getAll( elem );
5055
5056      for ( i = 0, l = srcElements.length; i < l; i++ ) {
5057        fixInput( srcElements[ i ], destElements[ i ] );
5058      }
5059    }
5060
5061    // Copy the events from the original to the clone
5062    if ( dataAndEvents ) {
5063      if ( deepDataAndEvents ) {
5064        srcElements = srcElements || getAll( elem );
5065        destElements = destElements || getAll( clone );
5066
5067        for ( i = 0, l = srcElements.length; i < l; i++ ) {
5068          cloneCopyEvent( srcElements[ i ], destElements[ i ] );
5069        }
5070      } else {
5071        cloneCopyEvent( elem, clone );
5072      }
5073    }
5074
5075    // Preserve script evaluation history
5076    destElements = getAll( clone, "script" );
5077    if ( destElements.length > 0 ) {
5078      setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5079    }
5080
5081    // Return the cloned set
5082    return clone;
5083  },
5084
5085  buildFragment: function( elems, context, scripts, selection ) {
5086    var elem, tmp, tag, wrap, contains, j,
5087      fragment = context.createDocumentFragment(),
5088      nodes = [],
5089      i = 0,
5090      l = elems.length;
5091
5092    for ( ; i < l; i++ ) {
5093      elem = elems[ i ];
5094
5095      if ( elem || elem === 0 ) {
5096
5097        // Add nodes directly
5098        if ( jQuery.type( elem ) === "object" ) {
5099          // Support: QtWebKit, PhantomJS
5100          // push.apply(_, arraylike) throws on ancient WebKit
5101          jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5102
5103        // Convert non-html into a text node
5104        } else if ( !rhtml.test( elem ) ) {
5105          nodes.push( context.createTextNode( elem ) );
5106
5107        // Convert html into DOM nodes
5108        } else {
5109          tmp = tmp || fragment.appendChild( context.createElement("div") );
5110
5111          // Deserialize a standard representation
5112          tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
5113          wrap = wrapMap[ tag ] || wrapMap._default;
5114          tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
5115
5116          // Descend through wrappers to the right content
5117          j = wrap[ 0 ];
5118          while ( j-- ) {
5119            tmp = tmp.lastChild;
5120          }
5121
5122          // Support: QtWebKit, PhantomJS
5123          // push.apply(_, arraylike) throws on ancient WebKit
5124          jQuery.merge( nodes, tmp.childNodes );
5125
5126          // Remember the top-level container
5127          tmp = fragment.firstChild;
5128
5129          // Ensure the created nodes are orphaned (#12392)
5130          tmp.textContent = "";
5131        }
5132      }
5133    }
5134
5135    // Remove wrapper from fragment
5136    fragment.textContent = "";
5137
5138    i = 0;
5139    while ( (elem = nodes[ i++ ]) ) {
5140
5141      // #4087 - If origin and destination elements are the same, and this is
5142      // that element, do not do anything
5143      if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
5144        continue;
5145      }
5146
5147      contains = jQuery.contains( elem.ownerDocument, elem );
5148
5149      // Append to fragment
5150      tmp = getAll( fragment.appendChild( elem ), "script" );
5151
5152      // Preserve script evaluation history
5153      if ( contains ) {
5154        setGlobalEval( tmp );
5155      }
5156
5157      // Capture executables
5158      if ( scripts ) {
5159        j = 0;
5160        while ( (elem = tmp[ j++ ]) ) {
5161          if ( rscriptType.test( elem.type || "" ) ) {
5162            scripts.push( elem );
5163          }
5164        }
5165      }
5166    }
5167
5168    return fragment;
5169  },
5170
5171  cleanData: function( elems ) {
5172    var data, elem, type, key,
5173      special = jQuery.event.special,
5174      i = 0;
5175
5176    for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
5177      if ( jQuery.acceptData( elem ) ) {
5178        key = elem[ data_priv.expando ];
5179
5180        if ( key && (data = data_priv.cache[ key ]) ) {
5181          if ( data.events ) {
5182            for ( type in data.events ) {
5183              if ( special[ type ] ) {
5184                jQuery.event.remove( elem, type );
5185
5186              // This is a shortcut to avoid jQuery.event.remove's overhead
5187              } else {
5188                jQuery.removeEvent( elem, type, data.handle );
5189              }
5190            }
5191          }
5192          if ( data_priv.cache[ key ] ) {
5193            // Discard any remaining `private` data
5194            delete data_priv.cache[ key ];
5195          }
5196        }
5197      }
5198      // Discard any remaining `user` data
5199      delete data_user.cache[ elem[ data_user.expando ] ];
5200    }
5201  }
5202});
5203
5204jQuery.fn.extend({
5205  text: function( value ) {
5206    return access( this, function( value ) {
5207      return value === undefined ?
5208        jQuery.text( this ) :
5209        this.empty().each(function() {
5210          if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5211            this.textContent = value;
5212          }
5213        });
5214    }, null, value, arguments.length );
5215  },
5216
5217  append: function() {
5218    return this.domManip( arguments, function( elem ) {
5219      if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5220        var target = manipulationTarget( this, elem );
5221        target.appendChild( elem );
5222      }
5223    });
5224  },
5225
5226  prepend: function() {
5227    return this.domManip( arguments, function( elem ) {
5228      if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5229        var target = manipulationTarget( this, elem );
5230        target.insertBefore( elem, target.firstChild );
5231      }
5232    });
5233  },
5234
5235  before: function() {
5236    return this.domManip( arguments, function( elem ) {
5237      if ( this.parentNode ) {
5238        this.parentNode.insertBefore( elem, this );
5239      }
5240    });
5241  },
5242
5243  after: function() {
5244    return this.domManip( arguments, function( elem ) {
5245      if ( this.parentNode ) {
5246        this.parentNode.insertBefore( elem, this.nextSibling );
5247      }
5248    });
5249  },
5250
5251  remove: function( selector, keepData /* Internal Use Only */ ) {
5252    var elem,
5253      elems = selector ? jQuery.filter( selector, this ) : this,
5254      i = 0;
5255
5256    for ( ; (elem = elems[i]) != null; i++ ) {
5257      if ( !keepData && elem.nodeType === 1 ) {
5258        jQuery.cleanData( getAll( elem ) );
5259      }
5260
5261      if ( elem.parentNode ) {
5262        if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5263          setGlobalEval( getAll( elem, "script" ) );
5264        }
5265        elem.parentNode.removeChild( elem );
5266      }
5267    }
5268
5269    return this;
5270  },
5271
5272  empty: function() {
5273    var elem,
5274      i = 0;
5275
5276    for ( ; (elem = this[i]) != null; i++ ) {
5277      if ( elem.nodeType === 1 ) {
5278
5279        // Prevent memory leaks
5280        jQuery.cleanData( getAll( elem, false ) );
5281
5282        // Remove any remaining nodes
5283        elem.textContent = "";
5284      }
5285    }
5286
5287    return this;
5288  },
5289
5290  clone: function( dataAndEvents, deepDataAndEvents ) {
5291    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5292    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5293
5294    return this.map(function() {
5295      return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5296    });
5297  },
5298
5299  html: function( value ) {
5300    return access( this, function( value ) {
5301      var elem = this[ 0 ] || {},
5302        i = 0,
5303        l = this.length;
5304
5305      if ( value === undefined && elem.nodeType === 1 ) {
5306        return elem.innerHTML;
5307      }
5308
5309      // See if we can take a shortcut and just use innerHTML
5310      if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5311        !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
5312
5313        value = value.replace( rxhtmlTag, "<$1></$2>" );
5314
5315        try {
5316          for ( ; i < l; i++ ) {
5317            elem = this[ i ] || {};
5318
5319            // Remove element nodes and prevent memory leaks
5320            if ( elem.nodeType === 1 ) {
5321              jQuery.cleanData( getAll( elem, false ) );
5322              elem.innerHTML = value;
5323            }
5324          }
5325
5326          elem = 0;
5327
5328        // If using innerHTML throws an exception, use the fallback method
5329        } catch( e ) {}
5330      }
5331
5332      if ( elem ) {
5333        this.empty().append( value );
5334      }
5335    }, null, value, arguments.length );
5336  },
5337
5338  replaceWith: function() {
5339    var arg = arguments[ 0 ];
5340
5341    // Make the changes, replacing each context element with the new content
5342    this.domManip( arguments, function( elem ) {
5343      arg = this.parentNode;
5344
5345      jQuery.cleanData( getAll( this ) );
5346
5347      if ( arg ) {
5348        arg.replaceChild( elem, this );
5349      }
5350    });
5351
5352    // Force removal if there was no new content (e.g., from empty arguments)
5353    return arg && (arg.length || arg.nodeType) ? this : this.remove();
5354  },
5355
5356  detach: function( selector ) {
5357    return this.remove( selector, true );
5358  },
5359
5360  domManip: function( args, callback ) {
5361
5362    // Flatten any nested arrays
5363    args = concat.apply( [], args );
5364
5365    var fragment, first, scripts, hasScripts, node, doc,
5366      i = 0,
5367      l = this.length,
5368      set = this,
5369      iNoClone = l - 1,
5370      value = args[ 0 ],
5371      isFunction = jQuery.isFunction( value );
5372
5373    // We can't cloneNode fragments that contain checked, in WebKit
5374    if ( isFunction ||
5375        ( l > 1 && typeof value === "string" &&
5376          !support.checkClone && rchecked.test( value ) ) ) {
5377      return this.each(function( index ) {
5378        var self = set.eq( index );
5379        if ( isFunction ) {
5380          args[ 0 ] = value.call( this, index, self.html() );
5381        }
5382        self.domManip( args, callback );
5383      });
5384    }
5385
5386    if ( l ) {
5387      fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
5388      first = fragment.firstChild;
5389
5390      if ( fragment.childNodes.length === 1 ) {
5391        fragment = first;
5392      }
5393
5394      if ( first ) {
5395        scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5396        hasScripts = scripts.length;
5397
5398        // Use the original fragment for the last item instead of the first because it can end up
5399        // being emptied incorrectly in certain situations (#8070).
5400        for ( ; i < l; i++ ) {
5401          node = fragment;
5402
5403          if ( i !== iNoClone ) {
5404            node = jQuery.clone( node, true, true );
5405
5406            // Keep references to cloned scripts for later restoration
5407            if ( hasScripts ) {
5408              // Support: QtWebKit
5409              // jQuery.merge because push.apply(_, arraylike) throws
5410              jQuery.merge( scripts, getAll( node, "script" ) );
5411            }
5412          }
5413
5414          callback.call( this[ i ], node, i );
5415        }
5416
5417        if ( hasScripts ) {
5418          doc = scripts[ scripts.length - 1 ].ownerDocument;
5419
5420          // Reenable scripts
5421          jQuery.map( scripts, restoreScript );
5422
5423          // Evaluate executable scripts on first document insertion
5424          for ( i = 0; i < hasScripts; i++ ) {
5425            node = scripts[ i ];
5426            if ( rscriptType.test( node.type || "" ) &&
5427              !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
5428
5429              if ( node.src ) {
5430                // Optional AJAX dependency, but won't run scripts if not present
5431                if ( jQuery._evalUrl ) {
5432                  jQuery._evalUrl( node.src );
5433                }
5434              } else {
5435                jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
5436              }
5437            }
5438          }
5439        }
5440      }
5441    }
5442
5443    return this;
5444  }
5445});
5446
5447jQuery.each({
5448  appendTo: "append",
5449  prependTo: "prepend",
5450  insertBefore: "before",
5451  insertAfter: "after",
5452  replaceAll: "replaceWith"
5453}, function( name, original ) {
5454  jQuery.fn[ name ] = function( selector ) {
5455    var elems,
5456      ret = [],
5457      insert = jQuery( selector ),
5458      last = insert.length - 1,
5459      i = 0;
5460
5461    for ( ; i <= last; i++ ) {
5462      elems = i === last ? this : this.clone( true );
5463      jQuery( insert[ i ] )[ original ]( elems );
5464
5465      // Support: QtWebKit
5466      // .get() because push.apply(_, arraylike) throws
5467      push.apply( ret, elems.get() );
5468    }
5469
5470    return this.pushStack( ret );
5471  };
5472});
5473
5474
5475var iframe,
5476  elemdisplay = {};
5477
5478/**
5479 * Retrieve the actual display of a element
5480 * @param {String} name nodeName of the element
5481 * @param {Object} doc Document object
5482 */
5483// Called only from within defaultDisplay
5484function actualDisplay( name, doc ) {
5485  var style,
5486    elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
5487
5488    // getDefaultComputedStyle might be reliably used only on attached element
5489    display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
5490
5491      // Use of this method is a temporary fix (more like optimization) until something better comes along,
5492      // since it was removed from specification and supported only in FF
5493      style.display : jQuery.css( elem[ 0 ], "display" );
5494
5495  // We don't have any data stored on the element,
5496  // so use "detach" method as fast way to get rid of the element
5497  elem.detach();
5498
5499  return display;
5500}
5501
5502/**
5503 * Try to determine the default display value of an element
5504 * @param {String} nodeName
5505 */
5506function defaultDisplay( nodeName ) {
5507  var doc = document,
5508    display = elemdisplay[ nodeName ];
5509
5510  if ( !display ) {
5511    display = actualDisplay( nodeName, doc );
5512
5513    // If the simple way fails, read from inside an iframe
5514    if ( display === "none" || !display ) {
5515
5516      // Use the already-created iframe if possible
5517      iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
5518
5519      // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
5520      doc = iframe[ 0 ].contentDocument;
5521
5522      // Support: IE
5523      doc.write();
5524      doc.close();
5525
5526      display = actualDisplay( nodeName, doc );
5527      iframe.detach();
5528    }
5529
5530    // Store the correct default display
5531    elemdisplay[ nodeName ] = display;
5532  }
5533
5534  return display;
5535}
5536var rmargin = (/^margin/);
5537
5538var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
5539
5540var getStyles = function( elem ) {
5541    // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
5542    // IE throws on elements created in popups
5543    // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
5544    if ( elem.ownerDocument.defaultView.opener ) {
5545      return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
5546    }
5547
5548    return window.getComputedStyle( elem, null );
5549  };
5550
5551
5552
5553function curCSS( elem, name, computed ) {
5554  var width, minWidth, maxWidth, ret,
5555    style = elem.style;
5556
5557  computed = computed || getStyles( elem );
5558
5559  // Support: IE9
5560  // getPropertyValue is only needed for .css('filter') (#12537)
5561  if ( computed ) {
5562    ret = computed.getPropertyValue( name ) || computed[ name ];
5563  }
5564
5565  if ( computed ) {
5566
5567    if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
5568      ret = jQuery.style( elem, name );
5569    }
5570
5571    // Support: iOS < 6
5572    // A tribute to the "awesome hack by Dean Edwards"
5573    // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
5574    // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
5575    if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
5576
5577      // Remember the original values
5578      width = style.width;
5579      minWidth = style.minWidth;
5580      maxWidth = style.maxWidth;
5581
5582      // Put in the new values to get a computed value out
5583      style.minWidth = style.maxWidth = style.width = ret;
5584      ret = computed.width;
5585
5586      // Revert the changed values
5587      style.width = width;
5588      style.minWidth = minWidth;
5589      style.maxWidth = maxWidth;
5590    }
5591  }
5592
5593  return ret !== undefined ?
5594    // Support: IE
5595    // IE returns zIndex value as an integer.
5596    ret + "" :
5597    ret;
5598}
5599
5600
5601function addGetHookIf( conditionFn, hookFn ) {
5602  // Define the hook, we'll check on the first run if it's really needed.
5603  return {
5604    get: function() {
5605      if ( conditionFn() ) {
5606        // Hook not needed (or it's not possible to use it due
5607        // to missing dependency), remove it.
5608        delete this.get;
5609        return;
5610      }
5611
5612      // Hook needed; redefine it so that the support test is not executed again.
5613      return (this.get = hookFn).apply( this, arguments );
5614    }
5615  };
5616}
5617
5618
5619(function() {
5620  var pixelPositionVal, boxSizingReliableVal,
5621    docElem = document.documentElement,
5622    container = document.createElement( "div" ),
5623    div = document.createElement( "div" );
5624
5625  if ( !div.style ) {
5626    return;
5627  }
5628
5629  // Support: IE9-11+
5630  // Style of cloned element affects source element cloned (#8908)
5631  div.style.backgroundClip = "content-box";
5632  div.cloneNode( true ).style.backgroundClip = "";
5633  support.clearCloneStyle = div.style.backgroundClip === "content-box";
5634
5635  container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
5636    "position:absolute";
5637  container.appendChild( div );
5638
5639  // Executing both pixelPosition & boxSizingReliable tests require only one layout
5640  // so they're executed at the same time to save the second computation.
5641  function computePixelPositionAndBoxSizingReliable() {
5642    div.style.cssText =
5643      // Support: Firefox<29, Android 2.3
5644      // Vendor-prefix box-sizing
5645      "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
5646      "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
5647      "border:1px;padding:1px;width:4px;position:absolute";
5648    div.innerHTML = "";
5649    docElem.appendChild( container );
5650
5651    var divStyle = window.getComputedStyle( div, null );
5652    pixelPositionVal = divStyle.top !== "1%";
5653    boxSizingReliableVal = divStyle.width === "4px";
5654
5655    docElem.removeChild( container );
5656  }
5657
5658  // Support: node.js jsdom
5659  // Don't assume that getComputedStyle is a property of the global object
5660  if ( window.getComputedStyle ) {
5661    jQuery.extend( support, {
5662      pixelPosition: function() {
5663
5664        // This test is executed only once but we still do memoizing
5665        // since we can use the boxSizingReliable pre-computing.
5666        // No need to check if the test was already performed, though.
5667        computePixelPositionAndBoxSizingReliable();
5668        return pixelPositionVal;
5669      },
5670      boxSizingReliable: function() {
5671        if ( boxSizingReliableVal == null ) {
5672          computePixelPositionAndBoxSizingReliable();
5673        }
5674        return boxSizingReliableVal;
5675      },
5676      reliableMarginRight: function() {
5677
5678        // Support: Android 2.3
5679        // Check if div with explicit width and no margin-right incorrectly
5680        // gets computed margin-right based on width of container. (#3333)
5681        // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
5682        // This support function is only executed once so no memoizing is needed.
5683        var ret,
5684          marginDiv = div.appendChild( document.createElement( "div" ) );
5685
5686        // Reset CSS: box-sizing; display; margin; border; padding
5687        marginDiv.style.cssText = div.style.cssText =
5688          // Support: Firefox<29, Android 2.3
5689          // Vendor-prefix box-sizing
5690          "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
5691          "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
5692        marginDiv.style.marginRight = marginDiv.style.width = "0";
5693        div.style.width = "1px";
5694        docElem.appendChild( container );
5695
5696        ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
5697
5698        docElem.removeChild( container );
5699        div.removeChild( marginDiv );
5700
5701        return ret;
5702      }
5703    });
5704  }
5705})();
5706
5707
5708// A method for quickly swapping in/out CSS properties to get correct calculations.
5709jQuery.swap = function( elem, options, callback, args ) {
5710  var ret, name,
5711    old = {};
5712
5713  // Remember the old values, and insert the new ones
5714  for ( name in options ) {
5715    old[ name ] = elem.style[ name ];
5716    elem.style[ name ] = options[ name ];
5717  }
5718
5719  ret = callback.apply( elem, args || [] );
5720
5721  // Revert the old values
5722  for ( name in options ) {
5723    elem.style[ name ] = old[ name ];
5724  }
5725
5726  return ret;
5727};
5728
5729
5730var
5731  // Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
5732  // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
5733  rdisplayswap = /^(none|table(?!-c[ea]).+)/,
5734  rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
5735  rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
5736
5737  cssShow = { position: "absolute", visibility: "hidden", display: "block" },
5738  cssNormalTransform = {
5739    letterSpacing: "0",
5740    fontWeight: "400"
5741  },
5742
5743  cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
5744
5745// Return a css property mapped to a potentially vendor prefixed property
5746function vendorPropName( style, name ) {
5747
5748  // Shortcut for names that are not vendor prefixed
5749  if ( name in style ) {
5750    return name;
5751  }
5752
5753  // Check for vendor prefixed names
5754  var capName = name[0].toUpperCase() + name.slice(1),
5755    origName = name,
5756    i = cssPrefixes.length;
5757
5758  while ( i-- ) {
5759    name = cssPrefixes[ i ] + capName;
5760    if ( name in style ) {
5761      return name;
5762    }
5763  }
5764
5765  return origName;
5766}
5767
5768function setPositiveNumber( elem, value, subtract ) {
5769  var matches = rnumsplit.exec( value );
5770  return matches ?
5771    // Guard against undefined "subtract", e.g., when used as in cssHooks
5772    Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
5773    value;
5774}
5775
5776function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
5777  var i = extra === ( isBorderBox ? "border" : "content" ) ?
5778    // If we already have the right measurement, avoid augmentation
5779    4 :
5780    // Otherwise initialize for horizontal or vertical properties
5781    name === "width" ? 1 : 0,
5782
5783    val = 0;
5784
5785  for ( ; i < 4; i += 2 ) {
5786    // Both box models exclude margin, so add it if we want it
5787    if ( extra === "margin" ) {
5788      val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
5789    }
5790
5791    if ( isBorderBox ) {
5792      // border-box includes padding, so remove it if we want content
5793      if ( extra === "content" ) {
5794        val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
5795      }
5796
5797      // At this point, extra isn't border nor margin, so remove border
5798      if ( extra !== "margin" ) {
5799        val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
5800      }
5801    } else {
5802      // At this point, extra isn't content, so add padding
5803      val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
5804
5805      // At this point, extra isn't content nor padding, so add border
5806      if ( extra !== "padding" ) {
5807        val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
5808      }
5809    }
5810  }
5811
5812  return val;
5813}
5814
5815function getWidthOrHeight( elem, name, extra ) {
5816
5817  // Start with offset property, which is equivalent to the border-box value
5818  var valueIsBorderBox = true,
5819    val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
5820    styles = getStyles( elem ),
5821    isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
5822
5823  // Some non-html elements return undefined for offsetWidth, so check for null/undefined
5824  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
5825  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
5826  if ( val <= 0 || val == null ) {
5827    // Fall back to computed then uncomputed css if necessary
5828    val = curCSS( elem, name, styles );
5829    if ( val < 0 || val == null ) {
5830      val = elem.style[ name ];
5831    }
5832
5833    // Computed unit is not pixels. Stop here and return.
5834    if ( rnumnonpx.test(val) ) {
5835      return val;
5836    }
5837
5838    // Check for style in case a browser which returns unreliable values
5839    // for getComputedStyle silently falls back to the reliable elem.style
5840    valueIsBorderBox = isBorderBox &&
5841      ( support.boxSizingReliable() || val === elem.style[ name ] );
5842
5843    // Normalize "", auto, and prepare for extra
5844    val = parseFloat( val ) || 0;
5845  }
5846
5847  // Use the active box-sizing model to add/subtract irrelevant styles
5848  return ( val +
5849    augmentWidthOrHeight(
5850      elem,
5851      name,
5852      extra || ( isBorderBox ? "border" : "content" ),
5853      valueIsBorderBox,
5854      styles
5855    )
5856  ) + "px";
5857}
5858
5859function showHide( elements, show ) {
5860  var display, elem, hidden,
5861    values = [],
5862    index = 0,
5863    length = elements.length;
5864
5865  for ( ; index < length; index++ ) {
5866    elem = elements[ index ];
5867    if ( !elem.style ) {
5868      continue;
5869    }
5870
5871    values[ index ] = data_priv.get( elem, "olddisplay" );
5872    display = elem.style.display;
5873    if ( show ) {
5874      // Reset the inline display of this element to learn if it is
5875      // being hidden by cascaded rules or not
5876      if ( !values[ index ] && display === "none" ) {
5877        elem.style.display = "";
5878      }
5879
5880      // Set elements which have been overridden with display: none
5881      // in a stylesheet to whatever the default browser style is
5882      // for such an element
5883      if ( elem.style.display === "" && isHidden( elem ) ) {
5884        values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
5885      }
5886    } else {
5887      hidden = isHidden( elem );
5888
5889      if ( display !== "none" || !hidden ) {
5890        data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "dis
5890play" ) );
5891      }
5892    }
5893  }
5894
5895  // Set the display of most of the elements in a second loop
5896  // to avoid the constant reflow
5897  for ( index = 0; index < length; index++ ) {
5898    elem = elements[ index ];
5899    if ( !elem.style ) {
5900      continue;
5901    }
5902    if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
5903      elem.style.display = show ? values[ index ] || "" : "none";
5904    }
5905  }
5906
5907  return elements;
5908}
5909
5910jQuery.extend({
5911
5912  // Add in style property hooks for overriding the default
5913  // behavior of getting and setting a style property
5914  cssHooks: {
5915    opacity: {
5916      get: function( elem, computed ) {
5917        if ( computed ) {
5918
5919          // We should always get a number back from opacity
5920          var ret = curCSS( elem, "opacity" );
5921          return ret === "" ? "1" : ret;
5922        }
5923      }
5924    }
5925  },
5926
5927  // Don't automatically add "px" to these possibly-unitless properties
5928  cssNumber: {
5929    "columnCount": true,
5930    "fillOpacity": true,
5931    "flexGrow": true,
5932    "flexShrink": true,
5933    "fontWeight": true,
5934    "lineHeight": true,
5935    "opacity": true,
5936    "order": true,
5937    "orphans": true,
5938    "widows": true,
5939    "zIndex": true,
5940    "zoom": true
5941  },
5942
5943  // Add in properties whose names you wish to fix before
5944  // setting or getting the value
5945  cssProps: {
5946    "float": "cssFloat"
5947  },
5948
5949  // Get and set the style property on a DOM Node
5950  style: function( elem, name, value, extra ) {
5951
5952    // Don't set styles on text and comment nodes
5953    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
5954      return;
5955    }
5956
5957    // Make sure that we're working with the right name
5958    var ret, type, hooks,
5959      origName = jQuery.camelCase( name ),
5960      style = elem.style;
5961
5962    name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
5963
5964    // Gets hook for the prefixed version, then unprefixed version
5965    hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
5966
5967    // Check if we're setting a value
5968    if ( value !== undefined ) {
5969      type = typeof value;
5970
5971      // Convert "+=" or "-=" to relative numbers (#7345)
5972      if ( type === "string" && (ret = rrelNum.exec( value )) ) {
5973        value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
5974        // Fixes bug #9237
5975        type = "number";
5976      }
5977
5978      // Make sure that null and NaN values aren't set (#7116)
5979      if ( value == null || value !== value ) {
5980        return;
5981      }
5982
5983      // If a number, add 'px' to the (except for certain CSS properties)
5984      if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
5985        value += "px";
5986      }
5987
5988      // Support: IE9-11+
5989      // background-* props affect original clone's values
5990      if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
5991        style[ name ] = "inherit";
5992      }
5993
5994      // If a hook was provided, use that value, otherwise just set the specified value
5995      if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
5996        style[ name ] = value;
5997      }
5998
5999    } else {
6000      // If a hook was provided get the non-computed value from there
6001      if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6002        return ret;
6003      }
6004
6005      // Otherwise just get the value from the style object
6006      return style[ name ];
6007    }
6008  },
6009
6010  css: function( elem, name, extra, styles ) {
6011    var val, num, hooks,
6012      origName = jQuery.camelCase( name );
6013
6014    // Make sure that we're working with the right name
6015    name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6016
6017    // Try prefixed name followed by the unprefixed name
6018    hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6019
6020    // If a hook was provided get the computed value from there
6021    if ( hooks && "get" in hooks ) {
6022      val = hooks.get( elem, true, extra );
6023    }
6024
6025    // Otherwise, if a way to get the computed value exists, use that
6026    if ( val === undefined ) {
6027      val = curCSS( elem, name, styles );
6028    }
6029
6030    // Convert "normal" to computed value
6031    if ( val === "normal" && name in cssNormalTransform ) {
6032      val = cssNormalTransform[ name ];
6033    }
6034
6035    // Make numeric if forced or a qualifier was provided and val looks numeric
6036    if ( extra === "" || extra ) {
6037      num = parseFloat( val );
6038      return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6039    }
6040    return val;
6041  }
6042});
6043
6044jQuery.each([ "height", "width" ], function( i, name ) {
6045  jQuery.cssHooks[ name ] = {
6046    get: function( elem, computed, extra ) {
6047      if ( computed ) {
6048
6049        // Certain elements can have dimension info if we invisibly show them
6050        // but it must have a current display style that would benefit
6051        return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
6052          jQuery.swap( elem, cssShow, function() {
6053            return getWidthOrHeight( elem, name, extra );
6054          }) :
6055          getWidthOrHeight( elem, name, extra );
6056      }
6057    },
6058
6059    set: function( elem, value, extra ) {
6060      var styles = extra && getStyles( elem );
6061      return setPositiveNumber( elem, value, extra ?
6062        augmentWidthOrHeight(
6063          elem,
6064          name,
6065          extra,
6066          jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6067          styles
6068        ) : 0
6069      );
6070    }
6071  };
6072});
6073
6074// Support: Android 2.3
6075jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
6076  function( elem, computed ) {
6077    if ( computed ) {
6078      return jQuery.swap( elem, { "display": "inline-block" },
6079        curCSS, [ elem, "marginRight" ] );
6080    }
6081  }
6082);
6083
6084// These hooks are used by animate to expand properties
6085jQuery.each({
6086  margin: "",
6087  padding: "",
6088  border: "Width"
6089}, function( prefix, suffix ) {
6090  jQuery.cssHooks[ prefix + suffix ] = {
6091    expand: function( value ) {
6092      var i = 0,
6093        expanded = {},
6094
6095        // Assumes a single number if not a string
6096        parts = typeof value === "string" ? value.split(" ") : [ value ];
6097
6098      for ( ; i < 4; i++ ) {
6099        expanded[ prefix + cssExpand[ i ] + suffix ] =
6100          parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6101      }
6102
6103      return expanded;
6104    }
6105  };
6106
6107  if ( !rmargin.test( prefix ) ) {
6108    jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6109  }
6110});
6111
6112jQuery.fn.extend({
6113  css: function( name, value ) {
6114    return access( this, function( elem, name, value ) {
6115      var styles, len,
6116        map = {},
6117        i = 0;
6118
6119      if ( jQuery.isArray( name ) ) {
6120        styles = getStyles( elem );
6121        len = name.length;
6122
6123        for ( ; i < len; i++ ) {
6124          map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6125        }
6126
6127        return map;
6128      }
6129
6130      return value !== undefined ?
6131        jQuery.style( elem, name, value ) :
6132        jQuery.css( elem, name );
6133    }, name, value, arguments.length > 1 );
6134  },
6135  show: function() {
6136    return showHide( this, true );
6137  },
6138  hide: function() {
6139    return showHide( this );
6140  },
6141  toggle: function( state ) {
6142    if ( typeof state === "boolean" ) {
6143      return state ? this.show() : this.hide();
6144    }
6145
6146    return this.each(function() {
6147      if ( isHidden( this ) ) {
6148        jQuery( this ).show();
6149      } else {
6150        jQuery( this ).hide();
6151      }
6152    });
6153  }
6154});
6155
6156
6157function Tween( elem, options, prop, end, easing ) {
6158  return new Tween.prototype.init( elem, options, prop, end, easing );
6159}
6160jQuery.Tween = Tween;
6161
6162Tween.prototype = {
6163  constructor: Tween,
6164  init: function( elem, options, prop, end, easing, unit ) {
6165    this.elem = elem;
6166    this.prop = prop;
6167    this.easing = easing || "swing";
6168    this.options = options;
6169    this.start = this.now = this.cur();
6170    this.end = end;
6171    this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6172  },
6173  cur: function() {
6174    var hooks = Tween.propHooks[ this.prop ];
6175
6176    return hooks && hooks.get ?
6177      hooks.get( this ) :
6178      Tween.propHooks._default.get( this );
6179  },
6180  run: function( percent ) {
6181    var eased,
6182      hooks = Tween.propHooks[ this.prop ];
6183
6184    if ( this.options.duration ) {
6185      this.pos = eased = jQuery.easing[ this.easing ](
6186        percent, this.options.duration * percent, 0, 1, this.options.duration
6187      );
6188    } else {
6189      this.pos = eased = percent;
6190    }
6191    this.now = ( this.end - this.start ) * eased + this.start;
6192
6193    if ( this.options.step ) {
6194      this.options.step.call( this.elem, this.now, this );
6195    }
6196
6197    if ( hooks && hooks.set ) {
6198      hooks.set( this );
6199    } else {
6200      Tween.propHooks._default.set( this );
6201    }
6202    return this;
6203  }
6204};
6205
6206Tween.prototype.init.prototype = Tween.prototype;
6207
6208Tween.propHooks = {
6209  _default: {
6210    get: function( tween ) {
6211      var result;
6212
6213      if ( tween.elem[ tween.prop ] != null &&
6214        (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
6215        return tween.elem[ tween.prop ];
6216      }
6217
6218      // Passing an empty string as a 3rd parameter to .css will automatically
6219      // attempt a parseFloat and fallback to a string if the parse fails.
6220      // Simple values such as "10px" are parsed to Float;
6221      // complex values such as "rotate(1rad)" are returned as-is.
6222      result = jQuery.css( tween.elem, tween.prop, "" );
6223      // Empty strings, null, undefined and "auto" are converted to 0.
6224      return !result || result === "auto" ? 0 : result;
6225    },
6226    set: function( tween ) {
6227      // Use step hook for back compat.
6228      // Use cssHook if its there.
6229      // Use .style if available and use plain properties where available.
6230      if ( jQuery.fx.step[ tween.prop ] ) {
6231        jQuery.fx.step[ tween.prop ]( tween );
6232      } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
6233        jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6234      } else {
6235        tween.elem[ tween.prop ] = tween.now;
6236      }
6237    }
6238  }
6239};
6240
6241// Support: IE9
6242// Panic based approach to setting things on disconnected nodes
6243Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6244  set: function( tween ) {
6245    if ( tween.elem.nodeType && tween.elem.parentNode ) {
6246      tween.elem[ tween.prop ] = tween.now;
6247    }
6248  }
6249};
6250
6251jQuery.easing = {
6252  linear: function( p ) {
6253    return p;
6254  },
6255  swing: function( p ) {
6256    return 0.5 - Math.cos( p * Math.PI ) / 2;
6257  }
6258};
6259
6260jQuery.fx = Tween.prototype.init;
6261
6262// Back Compat <1.8 extension point
6263jQuery.fx.step = {};
6264
6265
6266
6267
6268var
6269  fxNow, timerId,
6270  rfxtypes = /^(?:toggle|show|hide)$/,
6271  rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
6272  rrun = /queueHooks$/,
6273  animationPrefilters = [ defaultPrefilter ],
6274  tweeners = {
6275    "*": [ function( prop, value ) {
6276      var tween = this.createTween( prop, value ),
6277        target = tween.cur(),
6278        parts = rfxnum.exec( value ),
6279        unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
6280
6281        // Starting value computation is required for potential unit mismatches
6282        start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
6283          rfxnum.exec( jQuery.css( tween.elem, prop ) ),
6284        scale = 1,
6285        maxIterations = 20;
6286
6287      if ( start && start[ 3 ] !== unit ) {
6288        // Trust units reported by jQuery.css
6289        unit = unit || start[ 3 ];
6290
6291        // Make sure we update the tween properties later on
6292        parts = parts || [];
6293
6294        // Iteratively approximate from a nonzero starting point
6295        start = +target || 1;
6296
6297        do {
6298          // If previous iteration zeroed out, double until we get *something*.
6299          // Use string for doubling so we don't accidentally see scale as unchanged below
6300          scale = scale || ".5";
6301
6302          // Adjust and apply
6303          start = start / scale;
6304          jQuery.style( tween.elem, prop, start + unit );
6305
6306        // Update scale, tolerating zero or NaN from tween.cur(),
6307        // break the loop if scale is unchanged or perfect, or if we've just had enough
6308        } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
6309      }
6310
6311      // Update tween properties
6312      if ( parts ) {
6313        start = tween.start = +start || +target || 0;
6314        tween.unit = unit;
6315        // If a +=/-= token was provided, we're doing a relative animation
6316        tween.end = parts[ 1 ] ?
6317          start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
6318          +parts[ 2 ];
6319      }
6320
6321      return tween;
6322    } ]
6323  };
6324
6325// Animations created synchronously will run synchronously
6326function createFxNow() {
6327  setTimeout(function() {
6328    fxNow = undefined;
6329  });
6330  return ( fxNow = jQuery.now() );
6331}
6332
6333// Generate parameters to create a standard animation
6334function genFx( type, includeWidth ) {
6335  var which,
6336    i = 0,
6337    attrs = { height: type };
6338
6339  // If we include width, step value is 1 to do all cssExpand values,
6340  // otherwise step value is 2 to skip over Left and Right
6341  includeWidth = includeWidth ? 1 : 0;
6342  for ( ; i < 4 ; i += 2 - includeWidth ) {
6343    which = cssExpand[ i ];
6344    attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
6345  }
6346
6347  if ( includeWidth ) {
6348    attrs.opacity = attrs.width = type;
6349  }
6350
6351  return attrs;
6352}
6353
6354function createTween( value, prop, animation ) {
6355  var tween,
6356    collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
6357    index = 0,
6358    length = collection.length;
6359  for ( ; index < length; index++ ) {
6360    if ( (tween = collection[ index ].call( animation, prop, value )) ) {
6361
6362      // We're done with this property
6363      return tween;
6364    }
6365  }
6366}
6367
6368function defaultPrefilter( elem, props, opts ) {
6369  /* jshint validthis: true */
6370  var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
6371    anim = this,
6372    orig = {},
6373    style = elem.style,
6374    hidden = elem.nodeType && isHidden( elem ),
6375    dataShow = data_priv.get( elem, "fxshow" );
6376
6377  // Handle queue: false promises
6378  if ( !opts.queue ) {
6379    hooks = jQuery._queueHooks( elem, "fx" );
6380    if ( hooks.unqueued == null ) {
6381      hooks.unqueued = 0;
6382      oldfire = hooks.empty.fire;
6383      hooks.empty.fire = function() {
6384        if ( !hooks.unqueued ) {
6385          oldfire();
6386        }
6387      };
6388    }
6389    hooks.unqueued++;
6390
6391    anim.always(function() {
6392      // Ensure the complete handler is called before this completes
6393      anim.always(function() {
6394        hooks.unqueued--;
6395        if ( !jQuery.queue( elem, "fx" ).length ) {
6396          hooks.empty.fire();
6397        }
6398      });
6399    });
6400  }
6401
6402  // Height/width overflow pass
6403  if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
6404    // Make sure that nothing sneaks out
6405    // Record all 3 overflow attributes because IE9-10 do not
6406    // change the overflow attribute when overflowX and
6407    // overflowY are set to the same value
6408    opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
6409
6410    // Set display property to inline-block for height/width
6411    // animations on inline elements that are having width/height animated
6412    display = jQuery.css( elem, "display" );
6413
6414    // Test default display if display is currently "none"
6415    checkDisplay = display === "none" ?
6416      data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
6417
6418    if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
6419      style.display = "inline-block";
6420    }
6421  }
6422
6423  if ( opts.overflow ) {
6424    style.overflow = "hidden";
6425    anim.always(function() {
6426      style.overflow = opts.overflow[ 0 ];
6427      style.overflowX = opts.overflow[ 1 ];
6428      style.overflowY = opts.overflow[ 2 ];
6429    });
6430  }
6431
6432  // show/hide pass
6433  for ( prop in props ) {
6434    value = props[ prop ];
6435    if ( rfxtypes.exec( value ) ) {
6436      delete props[ prop ];
6437      toggle = toggle || value === "toggle";
6438      if ( value === ( hidden ? "hide" : "show" ) ) {
6439
6440        // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
6441        if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
6442          hidden = true;
6443        } else {
6444          continue;
6445        }
6446      }
6447      orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
6448
6449    // Any non-fx value stops us from restoring the original display value
6450    } else {
6451      display = undefined;
6452    }
6453  }
6454
6455  if ( !jQuery.isEmptyObject( orig ) ) {
6456    if ( dataShow ) {
6457      if ( "hidden" in dataShow ) {
6458        hidden = dataShow.hidden;
6459      }
6460    } else {
6461      dataShow = data_priv.access( elem, "fxshow", {} );
6462    }
6463
6464    // Store state if its toggle - enables .stop().toggle() to "reverse"
6465    if ( toggle ) {
6466      dataShow.hidden = !hidden;
6467    }
6468    if ( hidden ) {
6469      jQuery( elem ).show();
6470    } else {
6471      anim.done(function() {
6472        jQuery( elem ).hide();
6473      });
6474    }
6475    anim.done(function() {
6476      var prop;
6477
6478      data_priv.remove( elem, "fxshow" );
6479      for ( prop in orig ) {
6480        jQuery.style( elem, prop, orig[ prop ] );
6481      }
6482    });
6483    for ( prop in orig ) {
6484      tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
6485
6486      if ( !( prop in dataShow ) ) {
6487        dataShow[ prop ] = tween.start;
6488        if ( hidden ) {
6489          tween.end = tween.start;
6490          tween.start = prop === "width" || prop === "height" ? 1 : 0;
6491        }
6492      }
6493    }
6494
6495  // If this is a noop like .hide().hide(), restore an overwritten display value
6496  } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
6497    style.display = display;
6498  }
6499}
6500
6501function propFilter( props, specialEasing ) {
6502  var index, name, easing, value, hooks;
6503
6504  // camelCase, specialEasing and expand cssHook pass
6505  for ( index in props ) {
6506    name = jQuery.camelCase( index );
6507    easing = specialEasing[ name ];
6508    value = props[ index ];
6509    if ( jQuery.isArray( value ) ) {
6510      easing = value[ 1 ];
6511      value = props[ index ] = value[ 0 ];
6512    }
6513
6514    if ( index !== name ) {
6515      props[ name ] = value;
6516      delete props[ index ];
6517    }
6518
6519    hooks = jQuery.cssHooks[ name ];
6520    if ( hooks && "expand" in hooks ) {
6521      value = hooks.expand( value );
6522      delete props[ name ];
6523
6524      // Not quite $.extend, this won't overwrite existing keys.
6525      // Reusing 'index' because we have the correct "name"
6526      for ( index in value ) {
6527        if ( !( index in props ) ) {
6528          props[ index ] = value[ index ];
6529          specialEasing[ index ] = easing;
6530        }
6531      }
6532    } else {
6533      specialEasing[ name ] = easing;
6534    }
6535  }
6536}
6537
6538function Animation( elem, properties, options ) {
6539  var result,
6540    stopped,
6541    index = 0,
6542    length = animationPrefilters.length,
6543    deferred = jQuery.Deferred().always( function() {
6544      // Don't match elem in the :animated selector
6545      delete tick.elem;
6546    }),
6547    tick = function() {
6548      if ( stopped ) {
6549        return false;
6550      }
6551      var currentTime = fxNow || createFxNow(),
6552        remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
6553        // Support: Android 2.3
6554        // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
6555        temp = remaining / animation.duration || 0,
6556        percent = 1 - temp,
6557        index = 0,
6558        length = animation.tweens.length;
6559
6560      for ( ; index < length ; index++ ) {
6561        animation.tweens[ index ].run( percent );
6562      }
6563
6564      deferred.notifyWith( elem, [ animation, percent, remaining ]);
6565
6566      if ( percent < 1 && length ) {
6567        return remaining;
6568      } else {
6569        deferred.resolveWith( elem, [ animation ] );
6570        return false;
6571      }
6572    },
6573    animation = deferred.promise({
6574      elem: elem,
6575      props: jQuery.extend( {}, properties ),
6576      opts: jQuery.extend( true, { specialEasing: {} }, options ),
6577      originalProperties: properties,
6578      originalOptions: options,
6579      startTime: fxNow || createFxNow(),
6580      duration: options.duration,
6581      tweens: [],
6582      createTween: function( prop, end ) {
6583        var tween = jQuery.Tween( elem, animation.opts, prop, end,
6584            animation.opts.specialEasing[ prop ] || animation.opts.easing );
6585        animation.tweens.push( tween );
6586        return tween;
6587      },
6588      stop: function( gotoEnd ) {
6589        var index = 0,
6590          // If we are going to the end, we want to run all the tweens
6591          // otherwise we skip this part
6592          length = gotoEnd ? animation.tweens.length : 0;
6593        if ( stopped ) {
6594          return this;
6595        }
6596        stopped = true;
6597        for ( ; index < length ; index++ ) {
6598          animation.tweens[ index ].run( 1 );
6599        }
6600
6601        // Resolve when we played the last frame; otherwise, reject
6602        if ( gotoEnd ) {
6603          deferred.resolveWith( elem, [ animation, gotoEnd ] );
6604        } else {
6605          deferred.rejectWith( elem, [ animation, gotoEnd ] );
6606        }
6607        return this;
6608      }
6609    }),
6610    props = animation.props;
6611
6612  propFilter( props, animation.opts.specialEasing );
6613
6614  for ( ; index < length ; index++ ) {
6615    result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
6616    if ( result ) {
6617      return result;
6618    }
6619  }
6620
6621  jQuery.map( props, createTween, animation );
6622
6623  if ( jQuery.isFunction( animation.opts.start ) ) {
6624    animation.opts.start.call( elem, animation );
6625  }
6626
6627  jQuery.fx.timer(
6628    jQuery.extend( tick, {
6629      elem: elem,
6630      anim: animation,
6631      queue: animation.opts.queue
6632    })
6633  );
6634
6635  // attach callbacks from options
6636  return animation.progress( animation.opts.progress )
6637    .done( animation.opts.done, animation.opts.complete )
6638    .fail( animation.opts.fail )
6639    .always( animation.opts.always );
6640}
6641
6642jQuery.Animation = jQuery.extend( Animation, {
6643
6644  tweener: function( props, callback ) {
6645    if ( jQuery.isFunction( props ) ) {
6646      callback = props;
6647      props = [ "*" ];
6648    } else {
6649      props = props.split(" ");
6650    }
6651
6652    var prop,
6653      index = 0,
6654      length = props.length;
6655
6656    for ( ; index < length ; index++ ) {
6657      prop = props[ index ];
6658      tweeners[ prop ] = tweeners[ prop ] || [];
6659      tweeners[ prop ].unshift( callback );
6660    }
6661  },
6662
6663  prefilter: function( callback, prepend ) {
6664    if ( prepend ) {
6665      animationPrefilters.unshift( callback );
6666    } else {
6667      animationPrefilters.push( callback );
6668    }
6669  }
6670});
6671
6672jQuery.speed = function( speed, easing, fn ) {
6673  var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
6674    complete: fn || !fn && easing ||
6675      jQuery.isFunction( speed ) && speed,
6676    duration: speed,
6677    easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
6678  };
6679
6680  opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
6681    opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
6682
6683  // Normalize opt.queue - true/undefined/null -> "fx"
6684  if ( opt.queue == null || opt.queue === true ) {
6685    opt.queue = "fx";
6686  }
6687
6688  // Queueing
6689  opt.old = opt.complete;
6690
6691  opt.complete = function() {
6692    if ( jQuery.isFunction( opt.old ) ) {
6693      opt.old.call( this );
6694    }
6695
6696    if ( opt.queue ) {
6697      jQuery.dequeue( this, opt.queue );
6698    }
6699  };
6700
6701  return opt;
6702};
6703
6704jQuery.fn.extend({
6705  fadeTo: function( speed, to, easing, callback ) {
6706
6707    // Show any hidden elements after setting opacity to 0
6708    return this.filter( isHidden ).css( "opacity", 0 ).show()
6709
6710      // Animate to the value specified
6711      .end().animate({ opacity: to }, speed, easing, callback );
6712  },
6713  animate: function( prop, speed, easing, callback ) {
6714    var empty = jQuery.isEmptyObject( prop ),
6715      optall = jQuery.speed( speed, easing, callback ),
6716      doAnimation = function() {
6717        // Operate on a copy of prop so per-property easing won't be lost
6718        var anim = Animation( this, jQuery.extend( {}, prop ), optall );
6719
6720        // Empty animations, or finishing resolves immediately
6721        if ( empty || data_priv.get( this, "finish" ) ) {
6722          anim.stop( true );
6723        }
6724      };
6725      doAnimation.finish = doAnimation;
6726
6727    return empty || optall.queue === false ?
6728      this.each( doAnimation ) :
6729      this.queue( optall.queue, doAnimation );
6730  },
6731  stop: function( type, clearQueue, gotoEnd ) {
6732    var stopQueue = function( hooks ) {
6733      var stop = hooks.stop;
6734      delete hooks.stop;
6735      stop( gotoEnd );
6736    };
6737
6738    if ( typeof type !== "string" ) {
6739      gotoEnd = clearQueue;
6740      clearQueue = type;
6741      type = undefined;
6742    }
6743    if ( clearQueue && type !== false ) {
6744      this.queue( type || "fx", [] );
6745    }
6746
6747    return this.each(function() {
6748      var dequeue = true,
6749        index = type != null && type + "queueHooks",
6750        timers = jQuery.timers,
6751        data = data_priv.get( this );
6752
6753      if ( index ) {
6754        if ( data[ index ] && data[ index ].stop ) {
6755          stopQueue( data[ index ] );
6756        }
6757      } else {
6758        for ( index in data ) {
6759          if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
6760            stopQueue( data[ index ] );
6761          }
6762        }
6763      }
6764
6765      for ( index = timers.length; index--; ) {
6766        if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
6767          timers[ index ].anim.stop( gotoEnd );
6768          dequeue = false;
vendor: 3,243 bytes, lines 6769-6900
6769          timers.splice( index, 1 );
6770        }
6771      }
6772
6773      // Start the next in the queue if the last step wasn't forced.
6774      // Timers currently will call their complete callbacks, which
6775      // will dequeue but only if they were gotoEnd.
6776      if ( dequeue || !gotoEnd ) {
6777        jQuery.dequeue( this, type );
6778      }
6779    });
6780  },
6781  finish: function( type ) {
6782    if ( type !== false ) {
6783      type = type || "fx";
6784    }
6785    return this.each(function() {
6786      var index,
6787        data = data_priv.get( this ),
6788        queue = data[ type + "queue" ],
6789        hooks = data[ type + "queueHooks" ],
6790        timers = jQuery.timers,
6791        length = queue ? queue.length : 0;
6792
6793      // Enable finishing flag on private data
6794      data.finish = true;
6795
6796      // Empty the queue first
6797      jQuery.queue( this, type, [] );
6798
6799      if ( hooks && hooks.stop ) {
6800        hooks.stop.call( this, true );
6801      }
6802
6803      // Look for any active animations, and finish them
6804      for ( index = timers.length; index--; ) {
6805        if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
6806          timers[ index ].anim.stop( true );
6807          timers.splice( index, 1 );
6808        }
6809      }
6810
6811      // Look for any animations in the old queue and finish them
6812      for ( index = 0; index < length; index++ ) {
6813        if ( queue[ index ] && queue[ index ].finish ) {
6814          queue[ index ].finish.call( this );
6815        }
6816      }
6817
6818      // Turn off finishing flag
6819      delete data.finish;
6820    });
6821  }
6822});
6823
6824jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
6825  var cssFn = jQuery.fn[ name ];
6826  jQuery.fn[ name ] = function( speed, easing, callback ) {
6827    return speed == null || typeof speed === "boolean" ?
6828      cssFn.apply( this, arguments ) :
6829      this.animate( genFx( name, true ), speed, easing, callback );
6830  };
6831});
6832
6833// Generate shortcuts for custom animations
6834jQuery.each({
6835  slideDown: genFx("show"),
6836  slideUp: genFx("hide"),
6837  slideToggle: genFx("toggle"),
6838  fadeIn: { opacity: "show" },
6839  fadeOut: { opacity: "hide" },
6840  fadeToggle: { opacity: "toggle" }
6841}, function( name, props ) {
6842  jQuery.fn[ name ] = function( speed, easing, callback ) {
6843    return this.animate( props, speed, easing, callback );
6844  };
6845});
6846
6847jQuery.timers = [];
6848jQuery.fx.tick = function() {
6849  var timer,
6850    i = 0,
6851    timers = jQuery.timers;
6852
6853  fxNow = jQuery.now();
6854
6855  for ( ; i < timers.length; i++ ) {
6856    timer = timers[ i ];
6857    // Checks the timer has not already been removed
6858    if ( !timer() && timers[ i ] === timer ) {
6859      timers.splice( i--, 1 );
6860    }
6861  }
6862
6863  if ( !timers.length ) {
6864    jQuery.fx.stop();
6865  }
6866  fxNow = undefined;
6867};
6868
6869jQuery.fx.timer = function( timer ) {
6870  jQuery.timers.push( timer );
6871  if ( timer() ) {
6872    jQuery.fx.start();
6873  } else {
6874    jQuery.timers.pop();
6875  }
6876};
6877
6878jQuery.fx.interval = 13;
6879
6880jQuery.fx.start = function() {
6881  if ( !timerId ) {
6882    timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
6883  }
6884};
6885
6886jQuery.fx.stop = function() {
6887  clearInterval( timerId );
6888  timerId = null;
6889};
6890
6891jQuery.fx.speeds = {
6892  slow: 600,
6893  fast: 200,
6894  // Default speed
6895  _default: 400
6896};
6897
6898
6899// Based off of the plugin by Clint Helfers, with permission.
6900// http://blindsignals.com/index.php/2009/07/jquery-delay/
6901jQuery.fn.delay = function( time, type ) {
6902  time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
6903  type = type || "fx";
6904
6905  return this.queue( type, function( next, hooks ) {
6906    var timeout = setTimeout( next, time );
6907    hooks.stop = function() {
6908      clearTimeout( timeout );
6909    };
6910  });
6911};
6912
6913
6914(function() {
6915  var input = document.createElement( "input" ),
6916    select = document.createElement( "select" ),
6917    opt = select.appendChild( document.createElement( "option" ) );
6918
6919  input.type = "checkbox";
6920
6921  // Support: iOS<=5.1, Android<=4.2+
6922  // Default value for a checkbox should be "on"
6923  support.checkOn = input.value !== "";
6924
6925  // Support: IE<=11+
6926  // Must access selectedIndex to make default options select
6927  support.optSelected = opt.selected;
6928
6929  // Support: Android<=2.3
6930  // Options inside disabled selects are incorrectly marked as disabled
6931  select.disabled = true;
6932  support.optDisabled = !opt.disabled;
6933
6934  // Support: IE<=11+
6935  // An input loses its value after becoming a radio
6936  input = document.createElement( "input" );
6937  input.value = "t";
6938  input.type = "radio";
6939  support.radioValue = input.value === "t";
6940})();
6941
6942
6943var nodeHook, boolHook,
6944  attrHandle = jQuery.expr.attrHandle;
6945
6946jQuery.fn.extend({
6947  attr: function( name, value ) {
6948    return access( this, jQuery.attr, name, value, arguments.length > 1 );
6949  },
6950
6951  removeAttr: function( name ) {
6952    return this.each(function() {
6953      jQuery.removeAttr( this, name );
6954    });
6955  }
6956});
6957
6958jQuery.extend({
6959  attr: function( elem, name, value ) {
6960    var hooks, ret,
6961      nType = elem.nodeType;
6962
6963    // don't get/set attributes on text, comment and attribute nodes
6964    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
6965      return;
6966    }
6967
6968    // Fallback to prop when attributes are not supported
6969    if ( typeof elem.getAttribute === strundefined ) {
6970      return jQuery.prop( elem, name, value );
6971    }
6972
6973    // All attributes are lowercase
6974    // Grab necessary hook if one is defined
6975    if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
6976      name = name.toLowerCase();
6977      hooks = jQuery.attrHooks[ name ] ||
6978        ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
6979    }
6980
6981    if ( value !== undefined ) {
6982
6983      if ( value === null ) {
6984        jQuery.removeAttr( elem, name );
6985
6986      } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
6987        return ret;
6988
6989      } else {
6990        elem.setAttribute( name, value + "" );
6991        return value;
6992      }
6993
6994    } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
6995      return ret;
6996
6997    } else {
6998      ret = jQuery.find.attr( elem, name );
6999
7000      // Non-existent attributes return null, we normalize to undefined
7001      return ret == null ?
7002        undefined :
7003        ret;
7004    }
7005  },
7006
7007  removeAttr: function( elem, value ) {
7008    var name, propName,
7009      i = 0,
7010      attrNames = value && value.match( rnotwhite );
7011
7012    if ( attrNames && elem.nodeType === 1 ) {
7013      while ( (name = attrNames[i++]) ) {
7014        propName = jQuery.propFix[ name ] || name;
7015
7016        // Boolean attributes get special treatment (#10870)
7017        if ( jQuery.expr.match.bool.test( name ) ) {
7018          // Set corresponding property to false
7019          elem[ propName ] = false;
7020        }
7021
7022        elem.removeAttribute( name );
7023      }
7024    }
7025  },
7026
7027  attrHooks: {
7028    type: {
7029      set: function( elem, value ) {
7030        if ( !support.radioValue && value === "radio" &&
7031          jQuery.nodeName( elem, "input" ) ) {
7032          var val = elem.value;
7033          elem.setAttribute( "type", value );
7034          if ( val ) {
7035            elem.value = val;
7036          }
7037          return value;
7038        }
7039      }
7040    }
7041  }
7042});
7043
7044// Hooks for boolean attributes
7045boolHook = {
7046  set: function( elem, value, name ) {
7047    if ( value === false ) {
7048      // Remove boolean attributes when set to false
7049      jQuery.removeAttr( elem, name );
7050    } else {
7051      elem.setAttribute( name, name );
7052    }
7053    return name;
7054  }
7055};
7056jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
7057  var getter = attrHandle[ name ] || jQuery.find.attr;
7058
7059  attrHandle[ name ] = function( elem, name, isXML ) {
7060    var ret, handle;
7061    if ( !isXML ) {
7062      // Avoid an infinite loop by temporarily removing this function from the getter
7063      handle = attrHandle[ name ];
7064      attrHandle[ name ] = ret;
7065      ret = getter( elem, name, isXML ) != null ?
7066        name.toLowerCase() :
7067        null;
7068      attrHandle[ name ] = handle;
7069    }
7070    return ret;
7071  };
7072});
7073
7074
7075
7076
7077var rfocusable = /^(?:input|select|textarea|button)$/i;
7078
7079jQuery.fn.extend({
7080  prop: function( name, value ) {
7081    return access( this, jQuery.prop, name, value, arguments.length > 1 );
7082  },
7083
7084  removeProp: function( name ) {
7085    return this.each(function() {
7086      delete this[ jQuery.propFix[ name ] || name ];
7087    });
7088  }
7089});
7090
7091jQuery.extend({
7092  propFix: {
7093    "for": "htmlFor",
7094    "class": "className"
7095  },
7096
7097  prop: function( elem, name, value ) {
7098    var ret, hooks, notxml,
7099      nType = elem.nodeType;
7100
7101    // Don't get/set properties on text, comment and attribute nodes
7102    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
7103      return;
7104    }
7105
7106    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
7107
7108    if ( notxml ) {
7109      // Fix name and attach hooks
7110      name = jQuery.propFix[ name ] || name;
7111      hooks = jQuery.propHooks[ name ];
7112    }
7113
7114    if ( value !== undefined ) {
7115      return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
7116        ret :
7117        ( elem[ name ] = value );
7118
7119    } else {
7120      return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
7121        ret :
7122        elem[ name ];
7123    }
7124  },
7125
7126  propHooks: {
7127    tabIndex: {
7128      get: function( elem ) {
7129        return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
7130          elem.tabIndex :
7131          -1;
7132      }
7133    }
7134  }
7135});
7136
7137if ( !support.optSelected ) {
7138  jQuery.propHooks.selected = {
7139    get: function( elem ) {
7140      var parent = elem.parentNode;
7141      if ( parent && parent.parentNode ) {
7142        parent.parentNode.selectedIndex;
7143      }
7144      return null;
7145    }
7146  };
7147}
7148
7149jQuery.each([
7150  "tabIndex",
7151  "readOnly",
7152  "maxLength",
7153  "cellSpacing",
7154  "cellPadding",
7155  "rowSpan",
7156  "colSpan",
7157  "useMap",
7158  "frameBorder",
7159  "contentEditable"
7160], function() {
7161  jQuery.propFix[ this.toLowerCase() ] = this;
7162});
7163
7164
7165
7166
7167var rclass = /[\t\r\n\f]/g;
7168
7169jQuery.fn.extend({
7170  addClass: function( value ) {
7171    var classes, elem, cur, clazz, j, finalValue,
7172      proceed = typeof value === "string" && value,
7173      i = 0,
7174      len = this.length;
7175
7176    if ( jQuery.isFunction( value ) ) {
7177      return this.each(function( j ) {
7178        jQuery( this ).addClass( value.call( this, j, this.className ) );
7179      });
7180    }
7181
7182    if ( proceed ) {
7183      // The disjunction here is for better compressibility (see removeClass)
7184      classes = ( value || "" ).match( rnotwhite ) || [];
7185
7186      for ( ; i < len; i++ ) {
7187        elem = this[ i ];
7188        cur = elem.nodeType === 1 && ( elem.className ?
7189          ( " " + elem.className + " " ).replace( rclass, " " ) :
7190          " "
7191        );
7192
7193        if ( cur ) {
7194          j = 0;
7195          while ( (clazz = classes[j++]) ) {
7196            if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
7197              cur += clazz + " ";
7198            }
7199          }
7200
7201          // only assign if different to avoid unneeded rendering.
7202          finalValue = jQuery.trim( cur );
7203          if ( elem.className !== finalValue ) {
7204            elem.className = finalValue;
7205          }
7206        }
7207      }
7208    }
7209
7210    return this;
7211  },
7212
7213  removeClass: function( value ) {
7214    var classes, elem, cur, clazz, j, finalValue,
7215      proceed = arguments.length === 0 || typeof value === "string" && value,
7216      i = 0,
7217      len = this.length;
7218
7219    if ( jQuery.isFunction( value ) ) {
7220      return this.each(function( j ) {
7221        jQuery( this ).removeClass( value.call( this, j, this.className ) );
7222      });
7223    }
7224    if ( proceed ) {
7225      classes = ( value || "" ).match( rnotwhite ) || [];
7226
7227      for ( ; i < len; i++ ) {
7228        elem = this[ i ];
7229        // This expression is here for better compressibility (see addClass)
7230        cur = elem.nodeType === 1 && ( elem.className ?
7231          ( " " + elem.className + " " ).replace( rclass, " " ) :
7232          ""
7233        );
7234
7235        if ( cur ) {
7236          j = 0;
7237          while ( (clazz = classes[j++]) ) {
7238            // Remove *all* instances
7239            while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
7240              cur = cur.replace( " " + clazz + " ", " " );
7241            }
7242          }
7243
7244          // Only assign if different to avoid unneeded rendering.
7245          finalValue = value ? jQuery.trim( cur ) : "";
7246          if ( elem.className !== finalValue ) {
7247            elem.className = finalValue;
7248          }
7249        }
7250      }
7251    }
7252
7253    return this;
7254  },
7255
7256  toggleClass: function( value, stateVal ) {
7257    var type = typeof value;
7258
7259    if ( typeof stateVal === "boolean" && type === "string" ) {
7260      return stateVal ? this.addClass( value ) : this.removeClass( value );
7261    }
7262
7263    if ( jQuery.isFunction( value ) ) {
7264      return this.each(function( i ) {
7265        jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
7266      });
7267    }
7268
7269    return this.each(function() {
7270      if ( type === "string" ) {
7271        // Toggle individual class names
7272        var className,
7273          i = 0,
7274          self = jQuery( this ),
7275          classNames = value.match( rnotwhite ) || [];
7276
7277        while ( (className = classNames[ i++ ]) ) {
7278          // Check each className given, space separated list
7279          if ( self.hasClass( className ) ) {
7280            self.removeClass( className );
7281          } else {
7282            self.addClass( className );
7283          }
7284        }
7285
7286      // Toggle whole class name
7287      } else if ( type === strundefined || type === "boolean" ) {
7288        if ( this.className ) {
7289          // store className if set
7290          data_priv.set( this, "__className__", this.className );
7291        }
7292
7293        // If the element has a class name or if we're passed `false`,
7294        // then remove the whole classname (if there was one, the above saved it).
7295        // Otherwise bring back whatever was previously saved (if anything),
7296        // falling back to the empty string if nothing was stored.
7297        this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
7298      }
7299    });
7300  },
7301
7302  hasClass: function( selector ) {
7303    var className = " " + selector + " ",
7304      i = 0,
7305      l = this.length;
7306    for ( ; i < l; i++ ) {
7307      if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
7308        return true;
7309      }
7310    }
7311
7312    return false;
7313  }
7314});
7315
7316
7317
7318
7319var rreturn = /\r/g;
7320
7321jQuery.fn.extend({
7322  val: function( value ) {
7323    var hooks, ret, isFunction,
7324      elem = this[0];
7325
7326    if ( !arguments.length ) {
7327      if ( elem ) {
7328        hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7329
7330        if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
7331          return ret;
7332        }
7333
7334        ret = elem.value;
7335
7336        return typeof ret === "string" ?
7337          // Handle most common string cases
7338          ret.replace(rreturn, "") :
7339          // Handle cases where value is null/undef or number
7340          ret == null ? "" : ret;
7341      }
7342
7343      return;
7344    }
7345
7346    isFunction = jQuery.isFunction( value );
7347
7348    return this.each(function( i ) {
7349      var val;
7350
7351      if ( this.nodeType !== 1 ) {
7352        return;
7353      }
7354
7355      if ( isFunction ) {
7356        val = value.call( this, i, jQuery( this ).val() );
7357      } else {
7358        val = value;
7359      }
7360
7361      // Treat null/undefined as ""; convert numbers to string
7362      if ( val == null ) {
7363        val = "";
7364
7365      } else if ( typeof val === "number" ) {
7366        val += "";
7367
7368      } else if ( jQuery.isArray( val ) ) {
7369        val = jQuery.map( val, function( value ) {
7370          return value == null ? "" : value + "";
7371        });
7372      }
7373
7374      hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7375
7376      // If set returns undefined, fall back to normal setting
7377      if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
7378        this.value = val;
7379      }
7380    });
7381  }
7382});
7383
7384jQuery.extend({
7385  valHooks: {
7386    option: {
7387      get: function( elem ) {
7388        var val = jQuery.find.attr( elem, "value" );
7389        return val != null ?
7390          val :
7391          // Support: IE10-11+
7392          // option.text throws exceptions (#14686, #14858)
7393          jQuery.trim( jQuery.text( elem ) );
7394      }
7395    },
7396    select: {
7397      get: function( elem ) {
7398        var value, option,
7399          options = elem.options,
7400          index = elem.selectedIndex,
7401          one = elem.type === "select-one" || index < 0,
7402          values = one ? null : [],
7403          max = one ? index + 1 : options.length,
7404          i = index < 0 ?
7405            max :
7406            one ? index : 0;
7407
7408        // Loop through all the selected options
7409        for ( ; i < max; i++ ) {
7410          option = options[ i ];
7411
7412          // IE6-9 doesn't update selected after form reset (#2551)
7413          if ( ( option.selected || i === index ) &&
7414              // Don't return options that are disabled or in a disabled optgroup
7415              ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
7416              ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7417
7418            // Get the specific value for the option
7419            value = jQuery( option ).val();
7420
7421            // We don't need an array for one selects
7422            if ( one ) {
7423              return value;
7424            }
7425
7426            // Multi-Selects return an array
7427            values.push( value );
7428          }
7429        }
7430
7431        return values;
7432      },
7433
7434      set: function( elem, value ) {
7435        var optionSet, option,
7436          options = elem.options,
7437          values = jQuery.makeArray( value ),
7438          i = options.length;
7439
7440        while ( i-- ) {
7441          option = options[ i ];
7442          if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
7443            optionSet = true;
7444          }
7445        }
7446
7447        // Force browsers to behave consistently when non-matching value is set
7448        if ( !optionSet ) {
7449          elem.selectedIndex = -1;
7450        }
7451        return values;
7452      }
7453    }
7454  }
7455});
7456
7457// Radios and checkboxes getter/setter
7458jQuery.each([ "radio", "checkbox" ], function() {
7459  jQuery.valHooks[ this ] = {
7460    set: function( elem, value ) {
7461      if ( jQuery.isArray( value ) ) {
7462        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
7463      }
7464    }
7465  };
7466  if ( !support.checkOn ) {
7467    jQuery.valHooks[ this ].get = function( elem ) {
7468      return elem.getAttribute("value") === null ? "on" : elem.value;
7469    };
7470  }
7471});
7472
7473
7474
7475
7476// Return jQuery for attributes-only inclusion
7477
7478
7479jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7480  "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7481  "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7482
7483  // Handle event binding
7484  jQuery.fn[ name ] = function( data, fn ) {
7485    return arguments.length > 0 ?
7486      this.on( name, null, data, fn ) :
7487      this.trigger( name );
7488  };
7489});
7490
7491jQuery.fn.extend({
7492  hover: function( fnOver, fnOut ) {
7493    return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7494  },
7495
7496  bind: function( types, data, fn ) {
7497    return this.on( types, null, data, fn );
7498  },
7499  unbind: function( types, fn ) {
7500    return this.off( types, null, fn );
7501  },
7502
7503  delegate: function( selector, types, data, fn ) {
7504    return this.on( types, selector, data, fn );
7505  },
7506  undelegate: function( selector, types, fn ) {
7507    // ( namespace ) or ( selector, types [, fn] )
7508    return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
7509  }
7510});
7511
7512
7513var nonce = jQuery.now();
7514
7515var rquery = (/\?/);
7516
7517
7518
7519// Support: Android 2.3
7520// Workaround failure to string-cast null input
7521jQuery.parseJSON = function( data ) {
7522  return JSON.parse( data + "" );
7523};
7524
7525
7526// Cross-browser xml parsing
7527jQuery.parseXML = function( data ) {
7528  var xml, tmp;
7529  if ( !data || typeof data !== "string" ) {
7530    return null;
7531  }
7532
7533  // Support: IE9
7534  try {
7535    tmp = new DOMParser();
7536    xml = tmp.parseFromString( data, "text/xml" );
7537  } catch ( e ) {
7538    xml = undefined;
7539  }
7540
7541  if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
7542    jQuery.error( "Invalid XML: " + data );
7543  }
7544  return xml;
7545};
7546
7547
7548var
7549  rhash = /#.*$/,
7550  rts = /([?&])_=[^&]*/,
7551  rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
vendor: 4,472 bytes, lines 7552-7692
7552  // #7653, #8125, #8152: local protocol detection
7553  rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7554  rnoContent = /^(?:GET|HEAD)$/,
7555  rprotocol = /^\/\//,
7556  rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
7557
7558  /* Prefilters
7559   * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7560   * 2) These are called:
7561   *    - BEFORE asking for a transport
7562   *    - AFTER param serialization (s.data is a string if s.processData is true)
7563   * 3) key is the dataType
7564   * 4) the catchall symbol "*" can be used
7565   * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7566   */
7567  prefilters = {},
7568
7569  /* Transports bindings
7570   * 1) key is the dataType
7571   * 2) the catchall symbol "*" can be used
7572   * 3) selection will start with transport dataType and THEN go to "*" if needed
7573   */
7574  transports = {},
7575
7576  // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7577  allTypes = "*/".concat( "*" ),
7578
7579  // Document location
7580  ajaxLocation = window.location.href,
7581
7582  // Segment location into parts
7583  ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7584
7585// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7586function addToPrefiltersOrTransports( structure ) {
7587
7588  // dataTypeExpression is optional and defaults to "*"
7589  return function( dataTypeExpression, func ) {
7590
7591    if ( typeof dataTypeExpression !== "string" ) {
7592      func = dataTypeExpression;
7593      dataTypeExpression = "*";
7594    }
7595
7596    var dataType,
7597      i = 0,
7598      dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
7599
7600    if ( jQuery.isFunction( func ) ) {
7601      // For each dataType in the dataTypeExpression
7602      while ( (dataType = dataTypes[i++]) ) {
7603        // Prepend if requested
7604        if ( dataType[0] === "+" ) {
7605          dataType = dataType.slice( 1 ) || "*";
7606          (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7607
7608        // Otherwise append
7609        } else {
7610          (structure[ dataType ] = structure[ dataType ] || []).push( func );
7611        }
7612      }
7613    }
7614  };
7615}
7616
7617// Base inspection function for prefilters and transports
7618function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7619
7620  var inspected = {},
7621    seekingTransport = ( structure === transports );
7622
7623  function inspect( dataType ) {
7624    var selected;
7625    inspected[ dataType ] = true;
7626    jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7627      var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7628      if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7629        options.dataTypes.unshift( dataTypeOrTransport );
7630        inspect( dataTypeOrTransport );
7631        return false;
7632      } else if ( seekingTransport ) {
7633        return !( selected = dataTypeOrTransport );
7634      }
7635    });
7636    return selected;
7637  }
7638
7639  return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7640}
7641
7642// A special extend for ajax options
7643// that takes "flat" options (not to be deep extended)
7644// Fixes #9887
7645function ajaxExtend( target, src ) {
7646  var key, deep,
7647    flatOptions = jQuery.ajaxSettings.flatOptions || {};
7648
7649  for ( key in src ) {
7650    if ( src[ key ] !== undefined ) {
7651      ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7652    }
7653  }
7654  if ( deep ) {
7655    jQuery.extend( true, target, deep );
7656  }
7657
7658  return target;
7659}
7660
7661/* Handles responses to an ajax request:
7662 * - finds the right dataType (mediates between content-type and expected dataType)
7663 * - returns the corresponding response
7664 */
7665function ajaxHandleResponses( s, jqXHR, responses ) {
7666
7667  var ct, type, finalDataType, firstDataType,
7668    contents = s.contents,
7669    dataTypes = s.dataTypes;
7670
7671  // Remove auto dataType and get content-type in the process
7672  while ( dataTypes[ 0 ] === "*" ) {
7673    dataTypes.shift();
7674    if ( ct === undefined ) {
7675      ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
7676    }
7677  }
7678
7679  // Check if we're dealing with a known content-type
7680  if ( ct ) {
7681    for ( type in contents ) {
7682      if ( contents[ type ] && contents[ type ].test( ct ) ) {
7683        dataTypes.unshift( type );
7684        break;
7685      }
7686    }
7687  }
7688
7689  // Check to see if we have a response for the expected dataType
7690  if ( dataTypes[ 0 ] in responses ) {
7691    finalDataType = dataTypes[ 0 ];
7692  } else {
7693    // Try convertible dataTypes
7694    for ( type in responses ) {
7695      if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
7696        finalDataType = type;
7697        break;
7698      }
7699      if ( !firstDataType ) {
7700        firstDataType = type;
7701      }
7702    }
7703    // Or just use first one
7704    finalDataType = finalDataType || firstDataType;
7705  }
7706
7707  // If we found a dataType
7708  // We add the dataType to the list if needed
7709  // and return the corresponding response
7710  if ( finalDataType ) {
7711    if ( finalDataType !== dataTypes[ 0 ] ) {
7712      dataTypes.unshift( finalDataType );
7713    }
7714    return responses[ finalDataType ];
7715  }
7716}
7717
7718/* Chain conversions given the request and the original response
7719 * Also sets the responseXXX fields on the jqXHR instance
7720 */
7721function ajaxConvert( s, response, jqXHR, isSuccess ) {
7722  var conv2, current, conv, tmp, prev,
7723    converters = {},
7724    // Work with a copy of dataTypes in case we need to modify it for conversion
7725    dataTypes = s.dataTypes.slice();
7726
7727  // Create converters map with lowercased keys
7728  if ( dataTypes[ 1 ] ) {
7729    for ( conv in s.converters ) {
7730      converters[ conv.toLowerCase() ] = s.converters[ conv ];
7731    }
7732  }
7733
7734  current = dataTypes.shift();
7735
7736  // Convert to each sequential dataType
7737  while ( current ) {
7738
7739    if ( s.responseFields[ current ] ) {
7740      jqXHR[ s.responseFields[ current ] ] = response;
7741    }
7742
7743    // Apply the dataFilter if provided
7744    if ( !prev && isSuccess && s.dataFilter ) {
7745      response = s.dataFilter( response, s.dataType );
7746    }
7747
7748    prev = current;
7749    current = dataTypes.shift();
7750
7751    if ( current ) {
7752
7753    // There's only work to do if current dataType is non-auto
7754      if ( current === "*" ) {
7755
7756        current = prev;
7757
7758      // Convert response if prev dataType is non-auto and differs from current
7759      } else if ( prev !== "*" && prev !== current ) {
7760
7761        // Seek a direct converter
7762        conv = converters[ prev + " " + current ] || converters[ "* " + current ];
7763
7764        // If none found, seek a pair
7765        if ( !conv ) {
7766          for ( conv2 in converters ) {
7767
7768            // If conv2 outputs current
7769            tmp = conv2.split( " " );
7770            if ( tmp[ 1 ] === current ) {
7771
7772              // If prev can be converted to accepted input
7773              conv = converters[ prev + " " + tmp[ 0 ] ] ||
7774                converters[ "* " + tmp[ 0 ] ];
7775              if ( conv ) {
7776                // Condense equivalence converters
7777                if ( conv === true ) {
7778                  conv = converters[ conv2 ];
7779
7780                // Otherwise, insert the intermediate dataType
7781                } else if ( converters[ conv2 ] !== true ) {
7782                  current = tmp[ 0 ];
7783                  dataTypes.unshift( tmp[ 1 ] );
7784                }
7785                break;
7786              }
7787            }
7788          }
7789        }
7790
7791        // Apply converter (if not an equivalence)
7792        if ( conv !== true ) {
7793
7794          // Unless errors are allowed to bubble, catch and return them
7795          if ( conv && s[ "throws" ] ) {
7796            response = conv( response );
7797          } else {
7798            try {
7799              response = conv( response );
7800            } catch ( e ) {
7801              return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
7802            }
7803          }
7804        }
7805      }
7806    }
7807  }
7808
7809  return { state: "success", data: response };
7810}
7811
7812jQuery.extend({
7813
7814  // Counter for holding the number of active queries
7815  active: 0,
7816
7817  // Last-Modified header cache for next request
7818  lastModified: {},
7819  etag: {},
7820
7821  ajaxSettings: {
7822    url: ajaxLocation,
7823    type: "GET",
7824    isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7825    global: true,
7826    processData: true,
7827    async: true,
7828    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7829    /*
7830    timeout: 0,
7831    data: null,
7832    dataType: null,
7833    username: null,
7834    password: null,
7835    cache: null,
7836    throws: false,
7837    traditional: false,
7838    headers: {},
7839    */
7840
7841    accepts: {
7842      "*": allTypes,
7843      text: "text/plain",
7844      html: "text/html",
7845      xml: "application/xml, text/xml",
7846      json: "application/json, text/javascript"
7847    },
7848
7849    contents: {
7850      xml: /xml/,
7851      html: /html/,
7852      json: /json/
7853    },
7854
7855    responseFields: {
7856      xml: "responseXML",
7857      text: "responseText",
7858      json: "responseJSON"
7859    },
7860
7861    // Data converters
7862    // Keys separate source (or catchall "*") and destination types with a single space
7863    converters: {
7864
7865      // Convert anything to text
7866      "* text": String,
7867
7868      // Text to html (true = no transformation)
7869      "text html": true,
7870
7871      // Evaluate text as a json expression
7872      "text json": jQuery.parseJSON,
7873
7874      // Parse text as xml
7875      "text xml": jQuery.parseXML
7876    },
7877
7878    // For options that shouldn't be deep extended:
7879    // you can add your own custom options here if
7880    // and when you create one that shouldn't be
7881    // deep extended (see ajaxExtend)
7882    flatOptions: {
7883      url: true,
7884      context: true
7885    }
7886  },
7887
7888  // Creates a full fledged settings object into target
7889  // with both ajaxSettings and settings fields.
7890  // If target is omitted, writes into ajaxSettings.
7891  ajaxSetup: function( target, settings ) {
7892    return settings ?
7893
7894      // Building a settings object
7895      ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7896
7897      // Extending ajaxSettings
7898      ajaxExtend( jQuery.ajaxSettings, target );
7899  },
7900
7901  ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7902  ajaxTransport: addToPrefiltersOrTransports( transports ),
7903
7904  // Main method
7905  ajax: function( url, options ) {
7906
7907    // If url is an object, simulate pre-1.5 signature
7908    if ( typeof url === "object" ) {
7909      options = url;
7910      url = undefined;
7911    }
7912
7913    // Force options to be an object
7914    options = options || {};
7915
7916    var transport,
7917      // URL without anti-cache param
7918      cacheURL,
7919      // Response headers
7920      responseHeadersString,
7921      responseHeaders,
7922      // timeout handle
7923      timeoutTimer,
7924      // Cross-domain detection vars
7925      parts,
7926      // To know if global events are to be dispatched
7927      fireGlobals,
7928      // Loop variable
7929      i,
7930      // Create the final options object
7931      s = jQuery.ajaxSetup( {}, options ),
7932      // Callbacks context
7933      callbackContext = s.context || s,
7934      // Context for global events is callbackContext if it is a DOM node or jQuery collection
7935      globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7936        jQuery( callbackContext ) :
7937        jQuery.event,
7938      // Deferreds
7939      deferred = jQuery.Deferred(),
7940      completeDeferred = jQuery.Callbacks("once memory"),
7941      // Status-dependent callbacks
7942      statusCode = s.statusCode || {},
7943      // Headers (they are sent all at once)
7944      requestHeaders = {},
7945      requestHeadersNames = {},
7946      // The jqXHR state
7947      state = 0,
7948      // Default abort message
7949      strAbort = "canceled",
7950      // Fake xhr
7951      jqXHR = {
7952        readyState: 0,
7953
7954        // Builds headers hashtable if needed
7955        getResponseHeader: function( key ) {
7956          var match;
7957          if ( state === 2 ) {
7958            if ( !responseHeaders ) {
7959              responseHeaders = {};
7960              while ( (match = rheaders.exec( responseHeadersString )) ) {
7961                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7962              }
7963            }
7964            match = responseHeaders[ key.toLowerCase() ];
7965          }
7966          return match == null ? null : match;
7967        },
7968
7969        // Raw string
7970        getAllResponseHeaders: function() {
7971          return state === 2 ? responseHeadersString : null;
7972        },
7973
7974        // Caches the header
7975        setRequestHeader: function( name, value ) {
7976          var lname = name.toLowerCase();
7977          if ( !state ) {
7978            name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7979            requestHeaders[ name ] = value;
7980          }
7981          return this;
7982        },
7983
7984        // Overrides response content-type header
7985        overrideMimeType: function( type ) {
7986          if ( !state ) {
7987            s.mimeType = type;
7988          }
7989          return this;
7990        },
7991
7992        // Status-dependent callbacks
7993        statusCode: function( map ) {
7994          var code;
7995          if ( map ) {
7996            if ( state < 2 ) {
7997              for ( code in map ) {
7998                // Lazy-add the new callback in a way that preserves old ones
7999                statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
8000              }
8001            } else {
8002              // Execute the appropriate callbacks
8003              jqXHR.always( map[ jqXHR.status ] );
8004            }
8005          }
8006          return this;
8007        },
8008
8009        // Cancel the request
8010        abort: function( statusText ) {
8011          var finalText = statusText || strAbort;
8012          if ( transport ) {
8013            transport.abort( finalText );
8014          }
8015          done( 0, finalText );
8016          return this;
8017        }
8018      };
8019
8020    // Attach deferreds
8021    deferred.promise( jqXHR ).complete = completeDeferred.add;
8022    jqXHR.success = jqXHR.done;
8023    jqXHR.error = jqXHR.fail;
8024
8025    // Remove hash character (#7531: and string promotion)
8026    // Add protocol if not provided (prefilters might expect it)
8027    // Handle falsy url in the settings object (#10093: consistency with old signature)
8028    // We also use the url parameter if available
8029    s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
8030      .replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
8031
8032    // Alias method option to type as per ticket #12004
8033    s.type = options.method || options.type || s.method || s.type;
8034
8035    // Extract dataTypes list
8036    s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
8037
8038    // A cross-domain request is in order when we have a protocol:host:port mismatch
8039    if ( s.crossDomain == null ) {
8040      parts = rurl.exec( s.url.toLowerCase() );
8041      s.crossDomain = !!( parts &&
8042        ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
8043          ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
8044            ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
8045      );
8046    }
8047
8048    // Convert data if not already a string
8049    if ( s.data && s.processData && typeof s.data !== "string" ) {
8050      s.data = jQuery.param( s.data, s.traditional );
8051    }
8052
8053    // Apply prefilters
8054    inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8055
8056    // If request was aborted inside a prefilter, stop there
8057    if ( state === 2 ) {
8058      return jqXHR;
8059    }
8060
8061    // We can fire global events as of now if asked to
8062    // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
8063    fireGlobals = jQuery.event && s.global;
8064
8065    // Watch for a new set of requests
8066    if ( fireGlobals && jQuery.active++ === 0 ) {
8067      jQuery.event.trigger("ajaxStart");
8068    }
8069
8070    // Uppercase the type
8071    s.type = s.type.toUpperCase();
8072
8073    // Determine if request has content
8074    s.hasContent = !rnoContent.test( s.type );
8075
8076    // Save the URL in case we're toying with the If-Modified-Since
8077    // and/or If-None-Match header later on
8078    cacheURL = s.url;
8079
8080    // More options handling for requests with no content
8081    if ( !s.hasContent ) {
8082
8083      // If data is available, append data to url
8084      if ( s.data ) {
8085        cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
8086        // #9682: remove data so that it's not used in an eventual retry
8087        delete s.data;
8088      }
8089
8090      // Add anti-cache in url if needed
8091      if ( s.cache === false ) {
8092        s.url = rts.test( cacheURL ) ?
8093
8094          // If there is already a '_' parameter, set its value
8095          cacheURL.replace( rts, "$1_=" + nonce++ ) :
8096
8097          // Otherwise add one to the end
8098          cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
8099      }
8100    }
8101
8102    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8103    if ( s.ifModified ) {
8104      if ( jQuery.lastModified[ cacheURL ] ) {
8105        jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
8106      }
8107      if ( jQuery.etag[ cacheURL ] ) {
8108        jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
8109      }
8110    }
8111
8112    // Set the correct header, if data is being sent
8113    if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8114      jqXHR.setRequestHeader( "Content-Type", s.contentType );
8115    }
8116
8117    // Set the Accepts header for the server, depending on the dataType
8118    jqXHR.setRequestHeader(
8119      "Accept",
8120      s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8121        s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8122        s.accepts[ "*" ]
8123    );
8124
8125    // Check for headers option
8126    for ( i in s.headers ) {
8127      jqXHR.setRequestHeader( i, s.headers[ i ] );
8128    }
8129
8130    // Allow custom headers/mimetypes and early abort
8131    if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8132      // Abort if not done already and return
8133      return jqXHR.abort();
8134    }
8135
8136    // Aborting is no longer a cancellation
8137    strAbort = "abort";
8138
8139    // Install callbacks on deferreds
8140    for ( i in { success: 1, error: 1, complete: 1 } ) {
8141      jqXHR[ i ]( s[ i ] );
8142    }
8143
8144    // Get transport
8145    transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8146
8147    // If no transport, we auto-abort
8148    if ( !transport ) {
8149      done( -1, "No Transport" );
8150    } else {
8151      jqXHR.readyState = 1;
8152
8153      // Send global event
8154      if ( fireGlobals ) {
8155        globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8156      }
8157      // Timeout
8158      if ( s.async && s.timeout > 0 ) {
8159        timeoutTimer = setTimeout(function() {
8160          jqXHR.abort("timeout");
8161        }, s.timeout );
8162      }
8163
8164      try {
8165        state = 1;
8166        transport.send( requestHeaders, done );
8167      } catch ( e ) {
8168        // Propagate exception as error if not done
8169        if ( state < 2 ) {
8170          done( -1, e );
8171        // Simply rethrow otherwise
8172        } else {
8173          throw e;
8174        }
8175      }
8176    }
8177
8178    // Callback for when everything is done
8179    function done( status, nativeStatusText, responses, headers ) {
8180      var isSuccess, success, error, response, modified,
8181        statusText = nativeStatusText;
8182
8183      // Called once
8184      if ( state === 2 ) {
8185        return;
8186      }
8187
8188      // State is "done" now
8189      state = 2;
8190
8191      // Clear timeout if it exists
8192      if ( timeoutTimer ) {
8193        clearTimeout( timeoutTimer );
8194      }
8195
8196      // Dereference transport for early garbage collection
8197      // (no matter how long the jqXHR object will be used)
8198      transport = undefined;
8199
8200      // Cache response headers
8201      responseHeadersString = headers || "";
8202
8203      // Set readyState
8204      jqXHR.readyState = status > 0 ? 4 : 0;
8205
8206      // Determine if successful
8207      isSuccess = status >= 200 && status < 300 || status === 304;
8208
8209      // Get response data
8210      if ( responses ) {
8211        response = ajaxHandleResponses( s, jqXHR, responses );
8212      }
8213
8214      // Convert no matter what (that way responseXXX fields are always set)
8215      response = ajaxConvert( s, response, jqXHR, isSuccess );
8216
8217      // If successful, handle type chaining
8218      if ( isSuccess ) {
8219
8220        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8221        if ( s.ifModified ) {
8222          modified = jqXHR.getResponseHeader("Last-Modified");
8223          if ( modified ) {
8224            jQuery.lastModified[ cacheURL ] = modified;
8225          }
8226          modified = jqXHR.getResponseHeader("etag");
8227          if ( modified ) {
8228            jQuery.etag[ cacheURL ] = modified;
8229          }
8230        }
8231
8232        // if no content
8233        if ( status === 204 || s.type === "HEAD" ) {
8234          statusText = "nocontent";
8235
8236        // if not modified
8237        } else if ( status === 304 ) {
8238          statusText = "notmodified";
8239
8240        // If we have data, let's convert it
8241        } else {
8242          statusText = response.state;
8243          success = response.data;
8244          error = response.error;
8245          isSuccess = !error;
8246        }
8247      } else {
8248        // Extract error from statusText and normalize for non-aborts
8249        error = statusText;
8250        if ( status || !statusText ) {
8251          statusText = "error";
8252          if ( status < 0 ) {
8253            status = 0;
8254          }
8255        }
8256      }
8257
8258      // Set data for the fake xhr object
8259      jqXHR.status = status;
8260      jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8261
8262      // Success/Error
8263      if ( isSuccess ) {
8264        deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8265      } else {
8266        deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8267      }
8268
8269      // Status-dependent callbacks
8270      jqXHR.statusCode( statusCode );
8271      statusCode = undefined;
8272
8273      if ( fireGlobals ) {
8274        globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8275          [ jqXHR, s, isSuccess ? success : error ] );
8276      }
8277
8278      // Complete
8279      completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8280
8281      if ( fireGlobals ) {
8282        globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8283        // Handle the global AJAX counter
8284        if ( !( --jQuery.active ) ) {
8285          jQuery.event.trigger("ajaxStop");
8286        }
8287      }
8288    }
8289
8290    return jqXHR;
8291  },
8292
8293  getJSON: function( url, data, callback ) {
8294    return jQuery.get( url, data, callback, "json" );
8295  },
8296
8297  getScript: function( url, callback ) {
8298    return jQuery.get( url, undefined, callback, "script" );
8299  }
8300});
8301
8302jQuery.each( [ "get", "post" ], function( i, method ) {
8303  jQuery[ method ] = function( url, data, callback, type ) {
8304    // Shift arguments if data argument was omitted
8305    if ( jQuery.isFunction( data ) ) {
8306      type = type || callback;
8307      callback = data;
8308      data = undefined;
8309    }
8310
8311    return jQuery.ajax({
8312      url: url,
8313      type: method,
8314      dataType: type,
8315      data: data,
8316      success: callback
8317    });
8318  };
8319});
8320
8321
8322jQuery._evalUrl = function( url ) {
8323  return jQuery.ajax({
8324    url: url,
8325    type: "GET",
8326    dataType: "script",
8327    async: false,
8328    global: false,
8329    "throws": true
8330  });
8331};
8332
8333
8334jQuery.fn.extend({
8335  wrapAll: function( html ) {
8336    var wrap;
8337
8338    if ( jQuery.isFunction( html ) ) {
8339      return this.each(function( i ) {
8340        jQuery( this ).wrapAll( html.call(this, i) );
8341      });
8342    }
8343
8344    if ( this[ 0 ] ) {
8345
8346      // The elements to wrap the target around
8347      wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
8348
8349      if ( this[ 0 ].parentNode ) {
8350        wrap.insertBefore( this[ 0 ] );
8351      }
8352
8353      wrap.map(function() {
8354        var elem = this;
8355
8356        while ( elem.firstElementChild ) {
8357          elem = elem.firstElementChild;
8358        }
8359
8360        return elem;
8361      }).append( this );
8362    }
8363
8364    return this;
8365  },
8366
8367  wrapInner: function( html ) {
8368    if ( jQuery.isFunction( html ) ) {
8369      return this.each(function( i ) {
8370        jQuery( this ).wrapInner( html.call(this, i) );
8371      });
8372    }
8373
8374    return this.each(function() {
8375      var self = jQuery( this ),
8376        contents = self.contents();
8377
8378      if ( contents.length ) {
8379        contents.wrapAll( html );
8380
8381      } else {
8382        self.append( html );
8383      }
8384    });
8385  },
8386
8387  wrap: function( html ) {
8388    var isFunction = jQuery.isFunction( html );
8389
8390    return this.each(function( i ) {
8391      jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
8392    });
8393  },
8394
8395  unwrap: function() {
8396    return this.parent().each(function() {
8397      if ( !jQuery.nodeName( this, "body" ) ) {
8398        jQuery( this ).replaceWith( this.childNodes );
8399      }
8400    }).end();
8401  }
8402});
8403
8404
8405jQuery.expr.filters.hidden = function( elem ) {
8406  // Support: Opera <= 12.12
8407  // Opera reports offsetWidths and offsetHeights less than zero on some elements
8408  return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
8409};
8410jQuery.expr.filters.visible = function( elem ) {
8411  return !jQuery.expr.filters.hidden( elem );
8412};
8413
8414
8415
8416
8417var r20 = /%20/g,
8418  rbracket = /\[\]$/,
8419  rCRLF = /\r?\n/g,
8420  rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8421  rsubmittable = /^(?:input|select|textarea|keygen)/i;
8422
8423function buildParams( prefix, obj, traditional, add ) {
8424  var name;
8425
8426  if ( jQuery.isArray( obj ) ) {
8427    // Serialize array item.
8428    jQuery.each( obj, function( i, v ) {
8429      if ( traditional || rbracket.test( prefix ) ) {
8430        // Treat each array item as a scalar.
8431        add( prefix, v );
8432
8433      } else {
8434        // Item is non-scalar (array or object), encode its numeric index.
8435        buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
8436      }
8437    });
8438
8439  } else if ( !traditional && jQuery.type( obj ) === "object" ) {
8440    // Serialize object item.
8441    for ( name in obj ) {
8442      buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8443    }
8444
8445  } else {
8446    // Serialize scalar item.
8447    add( prefix, obj );
8448  }
8449}
8450
8451// Serialize an array of form elements or a set of
8452// key/values into a query string
8453jQuery.param = function( a, traditional ) {
8454  var prefix,
8455    s = [],
8456    add = function( key, value ) {
8457      // If value is a function, invoke it and return its value
8458      value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
8459      s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
8460    };
8461
8462  // Set traditional to true for jQuery <= 1.3.2 behavior.
8463  if ( traditional === undefined ) {
8464    traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
8465  }
8466
8467  // If an array was passed in, assume that it is an array of form elements.
8468  if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8469    // Serialize the form elements
8470    jQuery.each( a, function() {
8471      add( this.name, this.value );
8472    });
8473
8474  } else {
8475    // If traditional, encode the "old" way (the way 1.3.2 or older
8476    // did it), otherwise encode params recursively.
8477    for ( prefix in a ) {
8478      buildParams( prefix, a[ prefix ], traditional, add );
8479    }
8480  }
8481
8482  // Return the resulting serialization
8483  return s.join( "&" ).replace( r20, "+" );
8484};
8485
8486jQuery.fn.extend({
8487  serialize: function() {
8488    return jQuery.param( this.serializeArray() );
8489  },
8490  serializeArray: function() {
8491    return this.map(function() {
8492      // Can add propHook for "elements" to filter or add form elements
8493      var elements = jQuery.prop( this, "elements" );
8494      return elements ? jQuery.makeArray( elements ) : this;
8495    })
8496    .filter(function() {
8497      var type = this.type;
8498
8499      // Use .is( ":disabled" ) so that fieldset[disabled] works
8500      return this.name && !jQuery( this ).is( ":disabled" ) &&
8501        rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8502        ( this.checked || !rcheckableType.test( type ) );
8503    })
8504    .map(function( i, elem ) {
8505      var val = jQuery( this ).val();
8506
8507      return val == null ?
8508        null :
8509        jQuery.isArray( val ) ?
8510          jQuery.map( val, function( val ) {
8511            return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8512          }) :
8513          { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8514    }).get();
8515  }
8516});
8517
8518
8519jQuery.ajaxSettings.xhr = function() {
8520  try {
8521    return new XMLHttpRequest();
8522  } catch( e ) {}
8523};
8524
8525var xhrId = 0,
8526  xhrCallbacks = {},
8527  xhrSuccessStatus = {
8528    // file protocol always yields status code 0, assume 200
8529    0: 200,
8530    // Support: IE9
8531    // #1450: sometimes IE returns 1223 when it should be 204
8532    1223: 204
8533  },
8534  xhrSupported = jQuery.ajaxSettings.xhr();
8535
8536// Support: IE9
8537// Open requests must be manually aborted on unload (#5280)
8538// See https://support.microsoft.com/kb/2856746 for more info
8539if ( window.attachEvent ) {
8540  window.attachEvent( "onunload", function() {
8541    for ( var key in xhrCallbacks ) {
8542      xhrCallbacks[ key ]();
8543    }
8544  });
8545}
8546
8547support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8548support.ajax = xhrSupported = !!xhrSupported;
8549
8550jQuery.ajaxTransport(function( options ) {
8551  var callback;
8552
8553  // Cross domain only allowed if supported through XMLHttpRequest
8554  if ( support.cors || xhrSupported && !options.crossDomain ) {
8555    return {
8556      send: function( headers, complete ) {
8557        var i,
8558          xhr = options.xhr(),
8559          id = ++xhrId;
8560
8561        xhr.open( options.type, options.url, options.async, options.username, options.password );
8562
8563        // Apply custom fields if provided
8564        if ( options.xhrFields ) {
8565          for ( i in options.xhrFields ) {
8566            xhr[ i ] = options.xhrFields[ i ];
8567          }
8568        }
8569
8570        // Override mime type if needed
8571        if ( options.mimeType && xhr.overrideMimeType ) {
8572          xhr.overrideMimeType( options.mimeType );
8573        }
8574
8575        // X-Requested-With header
8576        // For cross-domain requests, seeing as conditions for a preflight are
8577        // akin to a jigsaw puzzle, we simply never set it to be sure.
8578        // (it can always be set on a per-request basis or even using ajaxSetup)
8579        // For same-domain requests, won't change header if already provided.
8580        if ( !options.crossDomain && !headers["X-Requested-With"] ) {
8581          headers["X-Requested-With"] = "XMLHttpRequest";
8582        }
8583
8584        // Set headers
8585        for ( i in headers ) {
8586          xhr.setRequestHeader( i, headers[ i ] );
8587        }
8588
8589        // Callback
8590        callback = function( type ) {
8591          return function() {
8592            if ( callback ) {
8593              delete xhrCallbacks[ id ];
8594              callback = xhr.onload = xhr.onerror = null;
8595
8596              if ( type === "abort" ) {
8597                xhr.abort();
8598              } else if ( type === "error" ) {
8599                complete(
8600                  // file: protocol always yields status 0; see #8605, #14207
8601                  xhr.status,
8602                  xhr.statusText
8603                );
8604              } else {
8605                complete(
8606                  xhrSuccessStatus[ xhr.status ] || xhr.status,
8607                  xhr.statusText,
8608                  // Support: IE9
8609                  // Accessing binary-data responseText throws an exception
8610                  // (#11426)
8611                  typeof xhr.responseText === "string" ? {
8612                    text: xhr.responseText
8613                  } : undefined,
8614                  xhr.getAllResponseHeaders()
8615                );
8616              }
8617            }
8618          };
8619        };
8620
8621        // Listen to events
8622        xhr.onload = callback();
8623        xhr.onerror = callback("error");
8624
8625        // Create the abort callback
8626        callback = xhrCallbacks[ id ] = callback("abort");
8627
8628        try {
8629          // Do send the request (this may raise an exception)
8630          xhr.send( options.hasContent && options.data || null );
8631        } catch ( e ) {
8632          // #14683: Only rethrow if this hasn't been notified as an error yet
8633          if ( callback ) {
8634            throw e;
8635          }
8636        }
8637      },
8638
8639      abort: function() {
8640        if ( callback ) {
8641          callback();
8642        }
8643      }
8644    };
8645  }
8646});
8647
8648
8649
8650
8651// Install script dataType
8652jQuery.ajaxSetup({
8653  accepts: {
8654    script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8655  },
8656  contents: {
8657    script: /(?:java|ecma)script/
8658  },
8659  converters: {
8660    "text script": function( text ) {
8661      jQuery.globalEval( text );
8662      return text;
8663    }
8664  }
8665});
8666
8667// Handle cache's special case and crossDomain
8668jQuery.ajaxPrefilter( "script", function( s ) {
8669  if ( s.cache === undefined ) {
8670    s.cache = false;
8671  }
8672  if ( s.crossDomain ) {
8673    s.type = "GET";
8674  }
8675});
8676
8677// Bind script tag hack transport
8678jQuery.ajaxTransport( "script", function( s ) {
8679  // This transport only deals with cross domain requests
8680  if ( s.crossDomain ) {
8681    var script, callback;
8682    return {
8683      send: function( _, complete ) {
8684        script = jQuery("<script>").prop({
8685          async: true,
8686          charset: s.scriptCharset,
8687          src: s.url
8688        }).on(
8689          "load error",
8690          callback = function( evt ) {
8691            script.remove();
8692            callback = null;
8693            if ( evt ) {
8694              complete( evt.type === "error" ? 404 : 200, evt.type );
8695            }
8696          }
8697        );
8698        document.head.appendChild( script[ 0 ] );
8699      },
8700      abort: function() {
8701        if ( callback ) {
8702          callback();
8703        }
8704      }
8705    };
8706  }
8707});
8708
8709
8710
8711
8712var oldCallbacks = [],
8713  rjsonp = /(=)\?(?=&|$)|\?\?/;
8714
8715// Default jsonp settings
8716jQuery.ajaxSetup({
8717  jsonp: "callback",
8718  jsonpCallback: function() {
8719    var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
8720    this[ callback ] = true;
8721    return callback;
8722  }
8723});
8724
8725// Detect, normalize options and install callbacks for jsonp requests
8726jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8727
8728  var callbackName, overwritten, responseContainer,
8729    jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8730      "url" :
8731      typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8732    );
8733
8734  // Handle iff the expected data type is "jsonp" or we have a parameter to set
8735  if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8736
8737    // Get callback name, remembering preexisting value associated with it
8738    callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8739      s.jsonpCallback() :
8740      s.jsonpCallback;
8741
8742    // Insert callback into url or form data
8743    if ( jsonProp ) {
8744      s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8745    } else if ( s.jsonp !== false ) {
8746      s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8747    }
8748
8749    // Use data converter to retrieve json after script execution
8750    s.converters["script json"] = function() {
8751      if ( !responseContainer ) {
8752        jQuery.error( callbackName + " was not called" );
8753      }
8754      return responseContainer[ 0 ];
8755    };
8756
8757    // force json dataType
8758    s.dataTypes[ 0 ] = "json";
8759
8760    // Install callback
8761    overwritten = window[ callbackName ];
8762    window[ callbackName ] = function() {
8763      responseContainer = arguments;
8764    };
8765
8766    // Clean-up function (fires after converters)
8767    jqXHR.always(function() {
8768      // Restore preexisting value
8769      window[ callbackName ] = overwritten;
8770
8771      // Save back as free
8772      if ( s[ callbackName ] ) {
8773        // make sure that re-using the options doesn't screw things around
8774        s.jsonpCallback = originalSettings.jsonpCallback;
8775
8776        // save the callback name for future use
8777        oldCallbacks.push( callbackName );
8778      }
8779
8780      // Call if it was a function and we have a response
8781      if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8782        overwritten( responseContainer[ 0 ] );
8783      }
8784
8785      responseContainer = overwritten = undefined;
8786    });
8787
8788    // Delegate to script
8789    return "script";
8790  }
8791});
8792
8793
8794
8795
8796// data: string of html
8797// context (optional): If specified, the fragment will be created in this context, defaults to document
8798// keepScripts (optional): If true, will include scripts passed in the html string
8799jQuery.parseHTML = function( data, context, keepScripts ) {
8800  if ( !data || typeof data !== "string" ) {
8801    return null;
8802  }
8803  if ( typeof context === "boolean" ) {
8804    keepScripts = context;
8805    context = false;
8806  }
8807  context = context || document;
8808
8809  var parsed = rsingleTag.exec( data ),
8810    scripts = !keepScripts && [];
8811
8812  // Single tag
8813  if ( parsed ) {
8814    return [ context.createElement( parsed[1] ) ];
8815  }
8816
8817  parsed = jQuery.buildFragment( [ data ], context, scripts );
8818
8819  if ( scripts && scripts.length ) {
8820    jQuery( scripts ).remove();
8821  }
8822
8823  return jQuery.merge( [], parsed.childNodes );
8824};
8825
8826
8827// Keep a copy of the old load method
8828var _load = jQuery.fn.load;
8829
8830/**
8831 * Load a url into a page
8832 */
8833jQuery.fn.load = function( url, params, callback ) {
8834  if ( typeof url !== "string" && _load ) {
8835    return _load.apply( this, arguments );
8836  }
8837
8838  var selector, type, response,
8839    self = this,
8840    off = url.indexOf(" ");
8841
8842  if ( off >= 0 ) {
8843    selector = jQuery.trim( url.slice( off ) );
8844    url = url.slice( 0, off );
8845  }
8846
8847  // If it's a function
8848  if ( jQuery.isFunction( params ) ) {
8849
8850    // We assume that it's the callback
8851    callback = params;
8852    params = undefined;
8853
8854  // Otherwise, build a param string
8855  } else if ( params && typeof params === "object" ) {
8856    type = "POST";
8857  }
8858
8859  // If we have elements to modify, make the request
8860  if ( self.length > 0 ) {
8861    jQuery.ajax({
8862      url: url,
8863
8864      // if "type" variable is undefined, then "GET" method will be used
8865      type: type,
8866      dataType: "html",
8867      data: params
8868    }).done(function( responseText ) {
8869
8870      // Save response for use in complete callback
8871      response = arguments;
8872
8873      self.html( selector ?
8874
8875        // If a selector was specified, locate the right elements in a dummy div
8876        // Exclude scripts to avoid IE 'Permission Denied' errors
8877        jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
8878
8879        // Otherwise use the full result
8880        responseText );
8881
8882    }).complete( callback && function( jqXHR, status ) {
8883      self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
8884    });
8885  }
8886
8887  return this;
8888};
8889
8890
8891
8892
8893// Attach a bunch of functions for handling common AJAX events
8894jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
8895  jQuery.fn[ type ] = function( fn ) {
8896    return this.on( type, fn );
8897  };
8898});
8899
8900
8901
8902
8903jQuery.expr.filters.animated = function( elem ) {
8904  return jQuery.grep(jQuery.timers, function( fn ) {
8905    return elem === fn.elem;
8906  }).length;
8907};
8908
8909
8910
8911
8912var docElem = window.document.documentElement;
8913
8914/**
8915 * Gets a window from an element
8916 */
8917function getWindow( elem ) {
8918  return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
8919}
8920
8921jQuery.offset = {
8922  setOffset: function( elem, options, i ) {
8923    var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
8924      position = jQuery.css( elem, "position" ),
8925      curElem = jQuery( elem ),
8926      props = {};
8927
8928    // Set position first, in-case top/left are set even on static elem
8929    if ( position === "static" ) {
8930      elem.style.position = "relative";
8931    }
8932
8933    curOffset = curElem.offset();
8934    curCSSTop = jQuery.css( elem, "top" );
8935    curCSSLeft = jQuery.css( elem, "left" );
8936    calculatePosition = ( position === "absolute" || position === "fixed" ) &&
8937      ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
8938
8939    // Need to be able to calculate position if either
8940    // top or left is auto and position is either absolute or fixed
8941    if ( calculatePosition ) {
8942      curPosition = curElem.position();
8943      curTop = curPosition.top;
8944      curLeft = curPosition.left;
8945
8946    } else {
8947      curTop = parseFloat( curCSSTop ) || 0;
8948      curLeft = parseFloat( curCSSLeft ) || 0;
8949    }
8950
8951    if ( jQuery.isFunction( options ) ) {
8952      options = options.call( elem, i, curOffset );
8953    }
8954
8955    if ( options.top != null ) {
8956      props.top = ( options.top - curOffset.top ) + curTop;
8957    }
8958    if ( options.left != null ) {
8959      props.left = ( options.left - curOffset.left ) + curLeft;
8960    }
8961
8962    if ( "using" in options ) {
8963      options.using.call( elem, props );
8964
8965    } else {
8966      curElem.css( props );
8967    }
8968  }
8969};
8970
8971jQuery.fn.extend({
8972  offset: function( options ) {
8973    if ( arguments.length ) {
8974      return options === undefined ?
8975        this :
8976        this.each(function( i ) {
8977          jQuery.offset.setOffset( this, options, i );
8978        });
8979    }
8980
8981    var docElem, win,
8982      elem = this[ 0 ],
8983      box = { top: 0, left: 0 },
8984      doc = elem && elem.ownerDocument;
8985
8986    if ( !doc ) {
8987      return;
8988    }
8989
8990    docElem = doc.documentElement;
8991
8992    // Make sure it's not a disconnected DOM node
8993    if ( !jQuery.contains( docElem, elem ) ) {
8994      return box;
8995    }
8996
8997    // Support: BlackBerry 5, iOS 3 (original iPhone)
8998    // If we don't have gBCR, just use 0,0 rather than error
8999    if ( typeof elem.getBoundingClientRect !== strundefined ) {
9000      box = elem.getBoundingClientRect();
9001    }
9002    win = getWindow( doc );
9003    return {
9004      top: box.top + win.pageYOffset - docElem.clientTop,
9005      left: box.left + win.pageXOffset - docElem.clientLeft
9006    };
9007  },
9008
9009  position: function() {
9010    if ( !this[ 0 ] ) {
9011      return;
9012    }
9013
9014    var offsetParent, offset,
9015      elem = this[ 0 ],
9016      parentOffset = { top: 0, left: 0 };
9017
9018    // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
9019    if ( jQuery.css( elem, "position" ) === "fixed" ) {
9020      // Assume getBoundingClientRect is there when computed position is fixed
9021      offset = elem.getBoundingClientRect();
9022
9023    } else {
9024      // Get *real* offsetParent
9025      offsetParent = this.offsetParent();
9026
9027      // Get correct offsets
9028      offset = this.offset();
9029      if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9030        parentOffset = offsetParent.offset();
9031      }
9032
9033      // Add offsetParent borders
9034      parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9035      parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9036    }
9037
9038    // Subtract parent offsets and element margins
9039    return {
9040      top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9041      left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
9042    };
9043  },
9044
9045  offsetParent: function() {
9046    return this.map(function() {
9047      var offsetParent = this.offsetParent || docElem;
9048
9049      while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
9050        offsetParent = offsetParent.offsetParent;
9051      }
9052
9053      return offsetParent || docElem;
9054    });
9055  }
9056});
9057
9058// Create scrollLeft and scrollTop methods
9059jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
9060  var top = "pageYOffset" === prop;
9061
9062  jQuery.fn[ method ] = function( val ) {
9063    return access( this, function( elem, method, val ) {
9064      var win = getWindow( elem );
9065
9066      if ( val === undefined ) {
9067        return win ? win[ prop ] : elem[ method ];
9068      }
9069
9070      if ( win ) {
9071        win.scrollTo(
9072          !top ? val : window.pageXOffset,
9073          top ? val : window.pageYOffset
9074        );
9075
9076      } else {
9077        elem[ method ] = val;
9078      }
9079    }, method, val, arguments.length, null );
9080  };
9081});
9082
9083// Support: Safari<7+, Chrome<37+
9084// Add the top/left cssHooks using jQuery.fn.position
9085// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
9086// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
9087// getComputedStyle returns percent when specified for top/left/bottom/right;
9088// rather than make the css module depend on the offset module, just check for it here
9089jQuery.each( [ "top", "left" ], function( i, prop ) {
9090  jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
9091    function( elem, computed ) {
9092      if ( computed ) {
9093        computed = curCSS( elem, prop );
9094        // If curCSS returns percentage, fallback to offset
9095        return rnumnonpx.test( computed ) ?
9096          jQuery( elem ).position()[ prop ] + "px" :
9097          computed;
9098      }
9099    }
9100  );
9101});
9102
9103
9104// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9105jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9106  jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9107    // Margin is only for outerHeight, outerWidth
9108    jQuery.fn[ funcName ] = function( margin, value ) {
9109      var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9110        extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9111
9112      return access( this, function( elem, type, value ) {
9113        var doc;
9114
9115        if ( jQuery.isWindow( elem ) ) {
9116          // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9117          // isn't a whole lot we can do. See pull request at this URL for discussion:
9118          // https://github.com/jquery/jquery/pull/764
9119          return elem.document.documentElement[ "client" + name ];
9120        }
9121
9122        // Get document width or height
9123        if ( elem.nodeType === 9 ) {
9124          doc = elem.documentElement;
9125
9126          // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
9127          // whichever is greatest
9128          return Math.max(
9129            elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9130            elem.body[ "offset" + name ], doc[ "offset" + name ],
9131            doc[ "client" + name ]
9132          );
9133        }
9134
9135        return value === undefined ?
9136          // Get width or height on the element, requesting but not forcing parseFloat
9137          jQuery.css( elem, type, extra ) :
9138
9139          // Set width or height on the element
9140          jQuery.style( elem, type, value, extra );
9141      }, type, chainable ? margin : undefined, chainable, null );
9142    };
9143  });
9144});
9145
9146
9147// The number of elements contained in the matched element set
9148jQuery.fn.size = function() {
9149  return this.length;
9150};
9151
9152jQuery.fn.andSelf = jQuery.fn.addBack;
9153
9154
9155
9156
9157// Register as a named AMD module, since jQuery can be concatenated with other
9158// files that may use define, but not via a proper concatenation script that
9159// understands anonymous AMD modules. A named AMD is safest and most robust
9160// way to register. Lowercase jquery is used because AMD module names are
9161// derived from file names, and jQuery is normally delivered in a lowercase
9162// file name. Do this after creating the global so that if an AMD module wants
9163// to call noConflict to hide this version of jQuery, it will work.
9164
9165// Note that for maximum portability, libraries that are not jQuery should
9166// declare themselves as anonymous modules, and avoid setting a global if an
9167// AMD loader is present. jQuery is a special case. For more information, see
9168// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
9169
9170if ( typeof define === "function" && define.amd ) {
9171  define( "jquery", [], function() {
9172    return jQuery;
9173  });
9174}
9175
9176
9177
9178
9179var
9180  // Map over jQuery in case of overwrite
9181  _jQuery = window.jQuery,
9182
9183  // Map over the $ in case of overwrite
9184  _$ = window.$;
9185
9186jQuery.noConflict = function( deep ) {
9187  if ( window.$ === jQuery ) {
9188    window.$ = _$;
9189  }
9190
9191  if ( deep && window.jQuery === jQuery ) {
9192    window.jQuery = _jQuery;
9193  }
9194
9195  return jQuery;
9196};
9197
9198// Expose jQuery and $ identifiers, even in AMD
9199// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
9200// and CommonJS for browser emulators (#13566)
9201if ( typeof noGlobal === strundefined ) {
9202  window.jQuery = window.$ = jQuery;
9203}
9204
9205
9206
9207
9208return jQuery;
9209
9210}));
9211/* jshint node: true */
9212
9213/**
9214 * Unobtrusive scripting adapter for jQuery
9215 * https://github.com/rails/jquery-ujs
9216 *
9217 * Requires jQuery 1.8.0 or later.
9218 *
9219 * Released under the MIT license
9220 *
9221 */
9222
9223(function() {
9224  'use strict';
9225
9226  var jqueryUjsInit = function($, undefined) {
9227
9228  // Cut down on the number of issues from people inadvertently including jquery_ujs twice
9229  // by detecting and raising an error when it happens.
9230  if ( $.rails !== undefined ) {
9231    $.error('jquery-ujs has already been loaded!');
9232  }
9233
9234  // Shorthand to make it a little easier to call public rails functions from within rails.js
9235  var rails;
9236  var $document = $(document);
9237
9238  $.rails = rails = {
9239    // Link elements bound by jquery-ujs
9240    linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]',
9241
9242    // Button elements bound by jquery-ujs
9243    buttonClickSelector: 'button[data-remote]:not([form]):not(form button), button[data-confirm]:not([form]):not(form button)',
9244
9245    // Select elements bound by jquery-ujs
9246    inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
9247
9248    // Form elements bound by jquery-ujs
9249    formSubmitSelector: 'form:not([data-turbo=true])',
9250
9251    // Form input elements bound by jquery-ujs
9252    formInputClickSelector: 'form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
9253
9254    // Form input elements disabled during form submission
9255    disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
9256
9257    // Form input elements re-enabled after form submission
9258    enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled',
9259
9260    // Form required input elements
9261    requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])',
9262
9263    // Form file input elements
9264    fileInputSelector: 'input[name][type=file]:not([disabled])',
9265
9266    // Link onClick disable selector with possible reenable after remote submission
9267    linkDisableSelector: 'a[data-disable-with], a[data-disable]',
9268
9269    // Button onClick disable selector with possible reenable after remote submission
9270    buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',
9271
9272    // Up-to-date Cross-Site Request Forgery token
9273    csrfToken: function() {
9274     return $('meta[name=csrf-token]').attr('content');
9275    },
9276
9277    // URL param that must contain the CSRF token
9278    csrfParam: function() {
9279     return $('meta[name=csrf-param]').attr('content');
9280    },
9281
9282    // Make sure that every Ajax request sends the CSRF token
9283    CSRFProtection: function(xhr) {
9284      var token = rails.csrfToken();
9285      if (token) xhr.setRequestHeader('X-CSRF-Token', token);
9286    },
9287
9288    // Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)
9289    refreshCSRFTokens: function(){
9290      $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken());
9291    },
9292
9293    // Triggers an event on an element and returns false if the event result is false
9294    fire: function(obj, name, data) {
9295      var event = $.Event(name);
9296      obj.trigger(event, data);
9297      return event.result !== false;
9298    },
9299
9300    // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
9301    confirm: function(message) {
9302      return confirm(message);
9303    },
9304
9305    // Default ajax function, may be overridden with custom function in $.rails.ajax
9306    ajax: function(options) {
9307      return $.ajax(options);
9308    },
9309
9310    // Default way to get an element's href. May be overridden at $.rails.href.
9311    href: function(element) {
9312      return element[0].href;
9313    },
9314
9315    // Checks "data-remote" if true to handle the request through a XHR request.
9316    isRemote: function(element) {
9317      return element.data('remote') !== undefined && element.data('remote') !== false;
9318    },
9319
9320    // Submits "remote" forms and links with ajax
9321    handleRemote: function(element) {
9322      var method, url, data, withCredentials, dataType, options;
9323
9324      if (rails.fire(element, 'ajax:before')) {
9325        withCredentials = element.data('with-credentials') || null;
9326        dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
9327
9328        if (element.is('form')) {
9329          method = element.data('ujs:submit-button-formmethod') || element.attr('method');
9330          url = element.data('ujs:submit-button-formaction') || element.attr('action');
9331          data = $(element[0]).serializeArray();
9332          // memoized value from clicked submit button
9333          var button = element.data('ujs:submit-button');
9334          if (button) {
9335            data.push(button);
9336            element.data('ujs:submit-button', null);
9337          }
9338          element.data('ujs:submit-button-formmethod', null);
9339          element.data('ujs:submit-button-formaction', null);
9340        } else if (element.is(rails.inputChangeSelector)) {
9341          method = element.data('method');
9342          url = element.data('url');
9343          data = element.serialize();
9344          if (element.data('params')) data = data + '&' + element.data('params');
9345        } else if (element.is(rails.buttonClickSelector)) {
9346          method = element.data('method') || 'get';
9347          url = element.data('url');
9348          data = element.serialize();
9349          if (element.data('params')) data = data + '&' + element.data('params');
9350        } else {
9351          method = element.data('method');
9352          url = rails.href(element);
9353          data = element.data('params') || null;
9354        }
9355
9356        options = {
9357          type: method || 'GET', data: data, dataType: dataType,
9358          // stopping the "ajax:beforeSend" event will cancel the ajax request
9359          beforeSend: function(xhr, settings) {
9360            if (settings.dataType === undefined) {
9361              xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
9362            }
9363            if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
9364              element.trigger('ajax:send', xhr);
9365            } else {
9366              return false;
9367            }
9368          },
9369          success: function(data, status, xhr) {
9370            element.trigger('ajax:success', [data, status, xhr]);
9371          },
9372          complete: function(xhr, status) {
9373            element.trigger('ajax:complete', [xhr, status]);
9374          },
9375          error: function(xhr, status, error) {
9376            element.trigger('ajax:error', [xhr, status, error]);
9377          },
9378          crossDomain: rails.isCrossDomain(url)
9379        };
9380
9381        // There is no withCredentials for IE6-8 when
9382        // "Enable native XMLHTTP support" is disabled
9383        if (withCredentials) {
9384          options.xhrFields = {
9385            withCredentials: withCredentials
9386          };
9387        }
9388
9389        // Only pass url to `ajax` options if not blank
9390        if (url) { options.url = url; }
9391
9392        return rails.ajax(options);
9393      } else {
9394        return false;
9395      }
9396    },
9397
9398    // Determines if the request is a cross domain request.
9399    isCrossDomain: function(url) {
9400      var originAnchor = document.createElement('a');
9401      originAnchor.href = location.href;
9402      var urlAnchor = document.createElement('a');
9403
9404      try {
9405        urlAnchor.href = url;
9406        // This is a workaround to a IE bug.
9407        urlAnchor.href = urlAnchor.href;
9408
9409        // If URL protocol is false or is a string containing a single colon
9410        // *and* host are false, assume it is not a cross-domain request
9411        // (should only be the case for IE7 and IE compatibility mode).
9412        // Otherwise, evaluate protocol and host of the URL against the origin
9413        // protocol and host.
9414        return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) ||
9415          (originAnchor.protocol + '//' + originAnchor.host ===
9416            urlAnchor.protocol + '//' + urlAnchor.host));
9417      } catch (e) {
9418        // If there is an error parsing the URL, assume it is crossDomain.
9419        return true;
9420      }
9421    },
9422
9423    // Handles "data-method" on links such as:
9424    // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
9425    handleMethod: function(link) {
9426      var href = rails.href(link),
9427        method = link.data('method'),
9428        target = link.attr('target'),
9429        csrfToken = rails.csrfToken(),
9430        csrfParam = rails.csrfParam(),
9431        form = $('<form method="post" action="' + href + '"></form>'),
9432        metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';
9433
9434      if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
9435        metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
9436      }
9437
9438      if (target) { form.attr('target', target); }
9439
9440      form.hide().append(metadataInput).appendTo('body');
9441      form.submit();
9442    },
9443
9444    // Helper function that returns form elements that match the specified CSS selector
9445    // If form is actually a "form" element this will return associated elements outside the from that have
9446    // the html form attribute set
9447    formElements: function(form, selector) {
9448      return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
9449    },
9450
9451    /* Disables form elements:
9452      - Caches element value in 'ujs:enable-with' data store
9453      - Replaces element text with value of 'data-disable-with' attribute
9454      - Sets disabled property to true
9455    */
9456    disableFormElements: function(form) {
9457      rails.formElements(form, rails.disableSelector).each(function() {
9458        rails.disableFormElement($(this));
9459      });
9460    },
9461
9462    disableFormElement: function(element) {
9463      var method, replacement;
9464
9465      method = element.is('button') ? 'html' : 'val';
9466      replacement = element.data('disable-with');
9467
9468      if (replacement !== undefined) {
9469        element.data('ujs:enable-with', element[method]());
9470        element[method](replacement);
9471      }
9472
9473      element.prop('disabled', true);
9474      element.data('ujs:disabled', true);
9475    },
9476
9477    /* Re-enables disabled form elements:
9478      - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
9479      - Sets disabled property to false
9480    */
9481    enableFormElements: function(form) {
9482      rails.formElements(form, rails.enableSelector).each(function() {
9483        rails.enableFormElement($(this));
9484      });
9485    },
9486
9487    enableFormElement: function(element) {
9488      var method = element.is('button') ? 'html' : 'val';
9489      if (element.data('ujs:enable-with') !== undefined) {
9490        element[method](element.data('ujs:enable-with'));
9491        element.removeData('ujs:enable-with'); // clean up cache
9492      }
9493      element.prop('disabled', false);
9494      element.removeData('ujs:disabled');
9495    },
9496
9497   /* For 'data-confirm' attribute:
9498      - Fires `confirm` event
9499      - Shows the confirmation dialog
9500      - Fires the `confirm:complete` event
9501
9502      Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
9503      Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
9504      Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
9505      return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
9506   */
9507    allowAction: function(element) {
9508      var message = element.data('confirm'),
9509          answer = false, callback;
9510      if (!message) { return true; }
9511
9512      if (rails.fire(element, 'confirm')) {
9513        try {
9514          answer = rails.confirm(message);
9515        } catch (e) {
9516          (console.error || console.log).call(console, e.stack || e);
9517        }
9518        callback = rails.fire(element, 'confirm:complete', [answer]);
9519      }
9520      return answer && callback;
9521    },
9522
9523    // Helper function which checks for blank inputs in a form that match the specified CSS selector
9524    blankInputs: function(form, specifiedSelector, nonBlank) {
9525      var foundInputs = $(),
9526        input,
9527        valueToCheck,
9528        radiosForNameWithNoneSelected,
9529        radioName,
9530        selector = specifiedSelector || 'input,textarea',
9531        requiredInputs = form.find(selector),
9532        checkedRadioButtonNames = {};
9533
9534      requiredInputs.each(function() {
9535        input = $(this);
9536        if (input.is('input[type=radio]')) {
9537
9538          // Don't count unchecked required radio as blank if other radio with same name is checked,
9539          // regardless of whether same-name radio input has required attribute or not. The spec
9540          // states https://www.w3.org/TR/html5/forms.html#the-required-attribute
9541          radioName = input.attr('name');
9542
9543          // Skip if we've already seen the radio with this name.
9544          if (!checkedRadioButtonNames[radioName]) {
9545
9546            // If none checked
9547            if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) {
9548              radiosForNameWithNoneSelected = form.find(
9549                'input[type=radio][name="' + radioName + '"]');
9550              foundInputs = foundInputs.add(radiosForNameWithNoneSelected);
9551            }
9552
9553            // We only need to check each name once.
9554            checkedRadioButtonNames[radioName] = radioName;
9555          }
9556        } else {
9557          valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val();
9558          if (valueToCheck === nonBlank) {
9559            foundInputs = foundInputs.add(input);
9560          }
9561        }
9562      });
9563      return foundInputs.length ? foundInputs : false;
9564    },
9565
9566    // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
9567    nonBlankInputs: function(form, specifiedSelector) {
9568      return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
9569    },
9570
9571    // Helper function, needed to provide consistent behavior in IE
9572    stopEverything: function(e) {
9573      $(e.target).trigger('ujs:everythingStopped');
9574      e.stopImmediatePropagation();
9575      return false;
9576    },
9577
9578    //  Replace element's html with the 'data-disable-with' after storing original html
9579    //  and prevent clicking on it
9580    disableElement: function(element) {
9581      var replacement = element.data('disable-with');
9582
9583      if (replacement !== undefined) {
9584        element.data('ujs:enable-with', element.html()); // store enabled state
9585        element.html(replacement);
9586      }
9587
9588      element.on('click.railsDisable', function(e) { // prevent further clicking
9589        return rails.stopEverything(e);
9590      });
9591      element.data('ujs:disabled', true);
9592    },
9593
9594    // Restore element to its original state which was disabled by 'disableElement' above
9595    enableElement: function(element) {
9596      if (element.data('ujs:enable-with') !== undefined) {
9597        element.html(element.data('ujs:enable-with')); // set to old enabled state
9598        element.removeData('ujs:enable-with'); // clean up cache
9599      }
9600      element.off('click.railsDisable'); // enable element
9601      element.removeData('ujs:disabled');
9602    }
9603  };
9604
9605  if (rails.fire($document, 'rails:attachBindings')) {
9606
9607    $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
9608
9609    // This event works the same as the load event, except that it fires every
9610    // time the page is loaded.
9611    //
9612    // See https://github.com/rails/jquery-ujs/issues/357
9613    // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
9614    $(window).on('pageshow.rails', function () {
9615      $($.rails.enableSelector).each(function () {
9616        var element = $(this);
9617
9618        if (element.data('ujs:disabled')) {
9619          $.rails.enableFormElement(element);
9620        }
9621      });
9622
9623      $($.rails.linkDisableSelector).each(function () {
9624        var element = $(this);
9625
9626        if (element.data('ujs:disabled')) {
9627          $.rails.enableElement(element);
9628        }
9629      });
9630    });
9631
9632    $document.on('ajax:complete', rails.linkDisableSelector, function() {
9633        rails.enableElement($(this));
9634    });
9635
9636    $document.on('ajax:complete', rails.buttonDisableSelector, function() {
9637        rails.enableFormElement($(this));
9638    });
9639
9640    $document.on('click.rails', rails.linkClickSelector, function(e) {
9641      var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
9642      if (!rails.allowAction(link)) return rails.stopEverything(e);
9643
9644      if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);
9645
9646      if (rails.isRemote(link)) {
9647        if (metaClick && (!method || method === 'GET') && !data) { return true; }
9648
9649        var handleRemote = rails.handleRemote(link);
9650        // Response from rails.handleRemote() will either be false or a deferred object promise.
9651        if (handleRemote === false) {
9652          rails.enableElement(link);
9653        } else {
9654          handleRemote.fail( function() { rails.enableElement(link); } );
9655        }
9656        return false;
9657
9658      } else if (method) {
9659        rails.handleMethod(link);
9660        return false;
9661      }
9662    });
9663
9664    $document.on('click.rails', rails.buttonClickSelector, function(e) {
9665      var button = $(this);
9666
9667      if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e);
9668
9669      if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
9670
9671      var handleRemote = rails.handleRemote(button);
9672      // Response from rails.handleRemote() will either be false or a deferred object promise.
9673      if (handleRemote === false) {
9674        rails.enableFormElement(button);
9675      } else {
9676        handleRemote.fail( function() { rails.enableFormElement(button); } );
9677      }
9678      return false;
9679    });
9680
9681    $document.on('change.rails', rails.inputChangeSelector, function(e) {
9682      var link = $(this);
9683      if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e);
9684
9685      rails.handleRemote(link);
9686      return false;
9687    });
9688
9689    $document.on('submit.rails', rails.formSubmitSelector, function(e) {
9690      var form = $(this),
9691        remote = rails.isRemote(form),
9692        blankRequiredInputs,
9693        nonBlankFileInputs;
9694
9695      if (!rails.allowAction(form)) return rails.stopEverything(e);
9696
9697      // Skip other logic when required values are missing or file upload is present
9698      if (form.attr('novalidate') === undefined) {
9699        if (form.data('ujs:formnovalidate-button') === undefined) {
9700          blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false);
9701          if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
9702            return rails.stopEverything(e);
9703          }
9704        } else {
9705          // Clear the formnovalidate in case the next button click is not on a formnovalidate button
9706          // Not strictly necessary to do here, since it is also reset on each button click, but just to be certain
9707          form.data('ujs:formnovalidate-button', undefined);
9708        }
9709      }
9710
9711      if (remote) {
9712        nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
9713        if (nonBlankFileInputs) {
9714          // Slight timeout so that the submit button gets properly serialized
9715          // (make it easy for event handler to serialize form without disabled values)
9716          setTimeout(function(){ rails.disableFormElements(form); }, 13);
9717          var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
9718
9719          // Re-enable form elements if event bindings return false (canceling normal form submission)
9720          if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
9721
9722          return aborted;
9723        }
9724
9725        rails.handleRemote(form);
9726        return false;
9727
9728      } else {
9729        // Slight timeout so that the submit button gets properly serialized
9730        setTimeout(function(){ rails.disableFormElements(form); }, 13);
9731      }
9732    });
9733
9734    $document.on('click.rails', rails.formInputClickSelector, function(event) {
9735      var button = $(this);
9736
9737      if (!rails.allowAction(button)) return rails.stopEverything(event);
9738
9739      // Register the pressed submit button
9740      var name = button.attr('name'),
9741        data = name ? {name:name, value:button.val()} : null;
9742
9743      var form = button.closest('form');
9744      if (form.length === 0) {
9745        form = $('#' + button.attr('form'));
9746      }
9747      form.data('ujs:submit-button', data);
9748
9749      // Save attributes from button
9750      form.data('ujs:formnovalidate-button', button.attr('formnovalidate'));
9751      form.data('ujs:submit-button-formaction', button.attr('formaction'));
9752      form.data('ujs:submit-button-formmethod', button.attr('formmethod'));
9753    });
9754
9755    $document.on('ajax:send.rails', rails.formSubmitSelector, function(event) {
9756      if (this === event.target) rails.disableFormElements($(this));
9757    });
9758
9759    $document.on('ajax:complete.rails', rails.formSubmitSelector, function(event) {
9760      if (this === event.target) rails.enableFormElements($(this));
9761    });
9762
9763    $(function(){
9764      rails.refreshCSRFTokens();
9765    });
9766  }
9767
9768  };
9769
9770  if (window.jQuery) {
9771    jqueryUjsInit(jQuery);
9772  } else if (typeof exports === 'object' && typeof module === 'object') {
9773    module.exports = jqueryUjsInit;
9774  }
9775})();
9776/*! modulejs v2.2.0 - https://larsjung.de/modulejs/ */
9777!function(n,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exp
9777orts.modulejs=r():n.modulejs=r()}(this,function(){return function(n){function r(t){if(e[t])return e[t].exports;var i=e[t]={exports:{},id:t,loaded:!1};return n[t].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}var e={};return r.m=n,r.c=e,r.p="",r(0)}([function(n,r,e){"use strict";var t=e(1),i=t.assert,o=t.forOwn,u=t.has,f=t.resolve,s=function n(){var r={},e={},t=function(n,e,t){if(void 0===t){var o=[[],e];e=o[0],t=o[1]}i("string"==typeof n,"id must be string: "+n),i(!u(r,n),"id already defined: "+n),i(Array.isArray(e),"deps must be array: "+n),r[n]={id:n,deps:e,fn:"function"==typeof t?t:function(){return t}}},s=function(n,t){return i("string"==typeof n,"id must be string: "+n),f(r,t||e,n)},c=function(){var n={};return o(r,function(t,i){n[i]={deps:t.deps.slice(),reqs:f(r,null,i),init:u(e,i)}}),o(r,function(e,t){var i=[];o(r,function(r,e){n[e].reqs.indexOf(t)>=0&&i.push(e)}),n[t].reqd=i}),n},a=function(n){var r="\n";return o(c(),function(e,t){var i=n?e.reqd:e.reqs;r+=(e.init?"*":" ")+" "+t+" -> [ "+i.join(", ")+" ]\n"}),r};return{create:n,define:t,log:a,require:s,state:c,_d:r,_i:e}};n.exports=s()},function(n,r){"use strict";var e=function(n,r){if(!n)throw new Error("[modulejs] "+r)},t=function(n,r){Object.keys(n).forEach(function(e){return r(n[e],e)})},i=function(n,r){return(n||{}).hasOwnProperty(r)},o=function(n){var r={};return n.filter(function(n){var e=!r[n];return r[n]=1,e})},u=function n(r,t,u,f){var s=!t;if(!s&&i(t,u))return t[u];var c=r[u];e(c,"id not defined: "+u),f=(f||[]).slice(),f.push(u);var a=[];if(c.deps.forEach(function(i){e(f.indexOf(i)<0,"circular dependencies: "+i+" in "+f);var o=n(r,t,i,f);s?(a=a.concat(o),a.push(i)):a.push(o)}),s)return o(a);var d=c.fn.apply(void 0,a);return t[u]=d,d};n.exports={assert:e,forOwn:t,has:i,resolve:u,uniq:o}}])});
9778/*!
9779 * JavaScript Cookie v2.0.3
9780 * https://github.com/js-cookie/js-cookie
9781 *
9782 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
9783 * Released under the MIT license
9784 */
9785(function (factory) {
9786	if (typeof define === 'function' && define.amd) {
9787		define(factory);
9788	} else if (typeof exports === 'object') {
9789		module.exports = factory();
9790	} else {
9791		var _OldCookies = window.Cookies;
9792		var api = window.Cookies = factory();
9793		api.noConflict = function () {
9794			window.Cookies = _OldCookies;
9795			return api;
9796		};
9797	}
9798}(function () {
9799	function extend () {
9800		var i = 0;
9801		var result = {};
9802		for (; i < arguments.length; i++) {
9803			var attributes = arguments[ i ];
9804			for (var key in attributes) {
9805				result[key] = attributes[key];
9806			}
9807		}
9808		return result;
9809	}
9810
9811	function init (converter) {
9812		function api (key, value, attributes) {
9813			var result;
9814
9815			// Write
9816
9817			if (arguments.length > 1) {
9818				attributes = extend({
9819					path: '/'
9820				}, api.defaults, attributes);
9821
9822				if (typeof attributes.expires === 'number') {
9823					var expires = new Date();
9824					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
9825					attributes.expires = expires;
9826				}
9827
9828				try {
9829					result = JSON.stringify(value);
9830					if (/^[\{\[]/.test(result)) {
9831						value = result;
9832					}
9833				} catch (e) {}
9834
9835				value = encodeURIComponent(String(value));
9836				value = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
9837
9838				key = encodeURIComponent(String(key));
9839				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
9840				key = key.replace(/[\(\)]/g, escape);
9841
9842				return (document.cookie = [
9843					key, '=', value,
9844					attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
9845					attributes.path    && '; path=' + attributes.path,
9846					attributes.domain  && '; domain=' + attributes.domain,
9847					attributes.secure ? '; secure' : ''
9848				].join(''));
9849			}
9850
9851			// Read
9852
9853			if (!key) {
9854				result = {};
9855			}
9856
9857			// To prevent the for loop in the first place assign an empty array
9858			// in case there are no cookies at all. Also prevents odd result when
9859			// calling "get()"
9860			var cookies = document.cookie ? document.cookie.split('; ') : [];
9861			var rdecode = /(%[0-9A-Z]{2})+/g;
9862			var i = 0;
9863
9864			for (; i < cookies.length; i++) {
9865				var parts = cookies[i].split('=');
9866				var name = parts[0].replace(rdecode, decodeURIComponent);
9867				var cookie = parts.slice(1).join('=');
9868
9869				if (cookie.charAt(0) === '"') {
9870					cookie = cookie.slice(1, -1);
9871				}
9872
9873				try {
9874					cookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent);
9875
9876					if (this.json) {
9877						try {
9878							cookie = JSON.parse(cookie);
9879						} catch (e) {}
9880					}
9881
9882					if (key === name) {
9883						result = cookie;
9884						break;
9885					}
9886
9887					if (!key) {
9888						result[name] = cookie;
9889					}
9890				} catch (e) {}
9891			}
9892
9893			return result;
9894		}
9895
9896		api.get = api.set = api;
9897		api.getJSON = function () {
9898			return api.apply({
9899				json: true
9900			}, [].slice.call(arguments));
9901		};
9902		api.defaults = {};
9903
9904		api.remove = function (key, attributes) {
9905			api(key, '', extend(attributes, {
9906				expires: -1
9907			}));
9908		};
9909
9910		api.withConverter = init;
9911
9912		return api;
9913	}
9914
9915	return init();
9916}));
9917/*
9918 * jQuery appear plugin
9919 *
9920 * Copyright (c) 2012 Andrey Sidorov
9921 * licensed under MIT license.
9922 *
9923 * https://github.com/morr/jquery.appear/
9924 *
9925 * Version: 0.3.6
9926 */
9927(function($) {
9928  var selectors = [];
9929
9930  var check_binded = false;
9931  var check_lock = false;
9932  var defaults = {
9933    interval: 250,
9934    force_process: false
9935  };
9936  var $window = $(window);
9937
9938  var $prior_appeared = [];
9939
9940  function process() {
9941    check_lock = false;
9942    for (var index = 0, selectorsLength = selectors.length; index < selectorsLength; index++) {
9943      var $appeared = $(selectors[index]).filter(function() {
9944        return $(this).is(':appeared');
9945      });
9946
9947      $appeared.trigger('appear', [$appeared]);
9948
9949      if ($prior_appeared[index]) {
9950        var $disappeared = $prior_appeared[index].not($appeared);
9951        $disappeared.trigger('disappear', [$disappeared]);
9952      }
9953      $prior_appeared[index] = $appeared;
9954    }
9955  };
9956
9957  function add_selector(selector) {
9958    selectors.push(selector);
9959    $prior_appeared.push();
9960  }
9961
9962  // "appeared" custom filter
9963  $.expr[':']['appeared'] = function(element) {
9964    var $element = $(element);
9965    if (!$element.is(':visible')) {
9966      return false;
9967    }
9968
9969    var window_left = $window.scrollLeft();
9970    var window_top = $window.scrollTop();
9971    var offset = $element.offset();
9972    var left = offset.left;
9973    var top = offset.top;
9974
9975    if (top + $element.height() >= window_top &&
9976        top - ($element.data('appear-top-offset') || 0) <= window_top + $window.height() &&
9977        left + $element.width() >= window_left &&
9978        left - ($element.data('appear-left-offset') || 0) <= window_left + $window.width()) {
9979      return true;
9980    } else {
9981      return false;
9982    }
9983  };
9984
9985  $.fn.extend({
9986    // watching for element's appearance in browser viewport
9987    appear: function(options) {
9988      var opts = $.extend({}, defaults, options || {});
9989      var selector = this.selector || this;
9990      if (!check_binded) {
9991        var on_check = function() {
9992          if (check_lock) {
9993            return;
9994          }
9995          check_lock = true;
9996
9997          setTimeout(process, opts.interval);
9998        };
9999
10000        $(window).scroll(on_check).resize(on_check);
10001        check_binded = true;
10002      }
10003
10004      if (opts.force_process) {
10005        setTimeout(process, opts.interval);
10006      }
10007      add_selector(selector);
10008      return $(selector);
10009    }
10010  });
10011
10012  $.extend({
10013    // force elements's appearance check
10014    force_appear: function() {
10015      if (check_binded) {
10016        process();
10017        return true;
10018      }
10019      return false;
10020    }
10021  });
10022})(function() {
10023  if (typeof module !== 'undefined') {
10024    // Node
10025    return require('jquery');
10026  } else {
10027    return jQuery;
10028  }
10029}());
10030/*!
10031	Autosize 3.0.5
10032	license: MIT
10033	http://www.jacklmoore.com/autosize
10034*/
10035(function (global, factory) {
10036	if (typeof define === 'function' && define.amd) {
10037		define(['exports', 'module'], factory);
10038	} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
10039		factory(exports, module);
10040	} else {
10041		var mod = {
10042			exports: {}
10043		};
10044		factory(mod.exports, mod);
10045		global.autosize = mod.exports;
10046	}
10047})(this, function (exports, module) {
10048	'use strict';
10049
10050	function assign(ta) {
10051		var _ref = arguments[1] === undefined ? {} : arguments[1];
10052
10053		var _ref$setOverflowX = _ref.setOverflowX;
10054		var setOverflowX = _ref$setOverflowX === undefined ? true : _ref$setOverflowX;
10055		var _ref$setOverflowY = _ref.setOverflowY;
10056		var setOverflowY = _ref$setOverflowY === undefined ? true : _ref$setOverflowY;
10057
10058		if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || ta.hasAttribute('data-autosize-on')) return;
10059
10060		var heightOffset = null;
10061		var overflowY = 'hidden';
10062
10063		function init() {
10064			var style = window.getComputedStyle(ta, null);
10065
10066			if (style.resize === 'vertical') {
10067				ta.style.resize = 'none';
10068			} else if (style.resize === 'both') {
10069				ta.style.resize = 'horizontal';
10070			}
10071
10072			if (style.boxSizing === 'content-box') {
10073				heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
10074			} else {
10075				heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
10076			}
10077
10078			update();
10079		}
10080
10081		function changeOverflow(value) {
10082			{
10083				// Chrome/Safari-specific fix:
10084				// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
10085				// made available by removing the scrollbar. The following forces the necessary text reflow.
10086				var width = ta.style.width;
10087				ta.style.width = '0px';
10088				// Force reflow:
10089				/* jshint ignore:start */
10090				ta.offsetWidth;
10091				/* jshint ignore:end */
10092				ta.style.width = width;
10093			}
10094
10095			overflowY = value;
10096
10097			if (setOverflowY) {
10098				ta.style.overflowY = value;
10099			}
10100
10101			update();
10102		}
10103
10104		function update() {
10105			var startHeight = ta.style.height;
10106			var htmlTop = document.documentElement.scrollTop;
10107			var bodyTop = document.body.scrollTop;
10108			var originalHeight = ta.style.height;
10109
10110			ta.style.height = 'auto';
10111
10112			var endHeight = ta.scrollHeight + heightOffset;
10113
10114			if (ta.scrollHeight === 0) {
10115				// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
10116				ta.style.height = originalHeight;
10117				return;
10118			}
10119
10120			ta.style.height = endHeight + 'px';
10121
10122			// prevents scroll-position jumping
10123			document.documentElement.scrollTop = htmlTop;
10124			document.body.scrollTop = bodyTop;
10125
10126			var style = window.getComputedStyle(ta, null);
10127
10128			if (style.height !== ta.style.height) {
10129				if (overflowY !== 'visible') {
10130					changeOverflow('visible');
10131					return;
10132				}
10133			} else {
10134				if (overflowY !== 'hidden') {
10135					changeOverflow('hidden');
10136					return;
10137				}
10138			}
10139
10140			if (startHeight !== ta.style.height) {
10141				var evt = document.createEvent('Event');
10142				evt.initEvent('autosize:resized', true, false);
10143				ta.dispatchEvent(evt);
10144			}
10145		}
10146
10147		var destroy = (function (style) {
10148			window.removeEventListener('resize', update);
10149			ta.removeEventListener('input', update);
10150			ta.removeEventListener('keyup', update);
10151			ta.removeAttribute('data-autosize-on');
10152			ta.removeEventListener('autosize:destroy', destroy);
10153
10154			Object.keys(style).forEach(function (key) {
10155				ta.style[key] = style[key];
10156			});
10157		}).bind(ta, {
10158			height: ta.style.height,
10159			resize: ta.style.resize,
10160			overflowY: ta.style.overflowY,
10161			overflowX: ta.style.overflowX,
10162			wordWrap: ta.style.wordWrap });
10163
10164		ta.addEventListener('autosize:destroy', destroy);
10165
10166		// IE9 does not fire onpropertychange or oninput for deletions,
10167		// so binding to onkeyup to catch most of those events.
10168		// There is no way that I know of to detect something like 'cut' in IE9.
10169		if ('onpropertychange' in ta && 'oninput' in ta) {
10170			ta.addEventListener('keyup', update);
10171		}
10172
10173		window.addEventListener('resize', update);
10174		ta.addEventListener('input', update);
10175		ta.addEventListener('autosize:update', update);
10176		ta.setAttribute('data-autosize-on', true);
10177
10178		if (setOverflowY) {
10179			ta.style.overflowY = 'hidden';
10180		}
10181		if (setOverflowX) {
10182			ta.style.overflowX = 'hidden';
10183			ta.style.wordWrap = 'break-word';
10184		}
10185
10186		init();
10187	}
10188
10189	function destroy(ta) {
10190		if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
10191		var evt = document.createEvent('Event');
10192		evt.initEvent('autosize:destroy', true, false);
10193		ta.dispatchEvent(evt);
10194	}
10195
10196	function update(ta) {
10197		if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
10198		var evt = document.createEvent('Event');
10199		evt.initEvent('autosize:update', true, false);
10200		ta.dispatchEvent(evt);
10201	}
10202
10203	var autosize = null;
10204
10205	// Do nothing in Node.js environment and IE8 (or lower)
10206	if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
10207		autosize = function (el) {
10208			return el;
10209		};
10210		autosize.destroy = function (el) {
10211			return el;
10212		};
10213		autosize.update = function (el) {
10214			return el;
10215		};
10216	} else {
10217		autosize = function (el, options) {
10218			if (el) {
10219				Array.prototype.forEach.call(el.length ? el : [el], function (x) {
10220					return assign(x, options);
10221				});
10222			}
10223			return el;
10224		};
10225		autosize.destroy = function (el) {
10226			if (el) {
10227				Array.prototype.forEach.call(el.length ? el : [el], destroy);
10228			}
10229			return el;
10230		};
10231		autosize.update = function (el) {
10232			if (el) {
10233				Array.prototype.forEach.call(el.length ? el : [el], update);
10234			}
10235			return el;
10236		};
10237	}
10238
10239	module.exports = autosize;
10240});
10241// Generated by CoffeeScript 1.4.0
10242(function() {
10243  var $;
10244
10245  $ = window.jQuery || window.Zepto || window.$;
10246
10247  $.fn.fancySelect = function(opts) {
10248    var isiOS, settings;
10249    if (opts == null) {
10250      opts = {};
10251    }
10252    settings = $.extend({
10253      forceiOS: false,
10254      includeBlank: false,
10255      optionTemplate: function(optionEl) {
10256        return optionEl.text();
10257      },
10258      triggerTemplate: function(optionEl) {
10259        return optionEl.text();
10260      }
10261    }, opts);
10262    isiOS = !!navigator.userAgent.match(/iP(hone|od|ad)/i);
10263    return this.each(function() {
10264      var copyOptionsToList, disabled, options, sel, trigger, updateTriggerText, wrapper;
10265      sel = $(this);
10266      if (sel.hasClass('fancified') || sel[0].tagName !== 'SELECT') {
10267        return;
10268      }
10269      sel.addClass('fancified');
10270      sel.css({
10271        width: 1,
10272        height: 1,
10273        display: 'block',
10274        position: 'absolute',
10275        top: 0,
10276        left: 0,
10277        opacity: 0
10278      });
10279      sel.wrap('<div class="fancy-select">');
10280      wrapper = sel.parent();
10281      if (sel.data('class')) {
10282        wrapper.addClass(sel.data('class'));
10283      }
10284      wrapper.append('<div class="trigger">');
10285      if (!(isiOS && !settings.forceiOS)) {
10286        wrapper.append('<ul class="options">');
10287      }
10288      trigger = wrapper.find('.trigger');
10289      options = wrapper.find('.options');
10290      disabled = sel.prop('disabled');
10291      if (disabled) {
10292        wrapper.addClass('disabled');
10293      }
10294      updateTriggerText = function() {
10295        var triggerHtml;
10296        triggerHtml = settings.triggerTemplate(sel.find(':selected'));
10297        return trigger.html(triggerHtml);
10298      };
10299      sel.on('blur.fs', function() {
10300        if (trigger.hasClass('open')) {
10301          return setTimeout(function() {
10302            return trigger.trigger('close.fs');
10303          }, 120);
10304        }
10305      });
10306      trigger.on('close.fs', function() {
10307        trigger.removeClass('open');
10308        return options.removeClass('open');
10309      });
10310      trigger.on('click.fs', function() {
10311        var offParent, parent;
10312        if (!disabled) {
10313          trigger.toggleClass('open');
10314          if (isiOS && !settings.forceiOS) {
10315            if (trigger.hasClass('open')) {
10316              return sel.focus();
10317            }
10318          } else {
10319            if (trigger.hasClass('open')) {
10320              parent = trigger.parent();
10321              offParent = parent.offsetParent();
10322              if ((parent.offset().top + parent.outerHeight() + options.outerHeight() + 20) > $(window).height() + $(window).scrollTop()) {
10323                options.addClass('overflowing');
10324              } else {
10325                options.removeClass('overflowing');
10326              }
10327            }
10328            options.toggleClass('open');
10329            if (!isiOS) {
10330              return sel.focus();
10331            }
10332          }
10333        }
10334      });
10335      sel.on('enable', function() {
10336        sel.prop('disabled', false);
10337        wrapper.removeClass('disabled');
10338        disabled = false;
10339        return copyOptionsToList();
10340      });
10341      sel.on('disable', function() {
10342        sel.prop('disabled', true);
10343        wrapper.addClass('disabled');
10344        return disabled = true;
10345      });
10346      sel.on('change.fs', function(e) {
10347        if (e.originalEvent && e.originalEvent.isTrusted) {
10348          return e.stopPropagation();
10349        } else {
10350          return updateTriggerText();
10351        }
10352      });
10353      sel.on('keydown', function(e) {
10354        var hovered, newHovered, w;
10355        w = e.which;
10356        hovered = options.find('.hover');
10357        hovered.removeClass('hover');
10358        if (!options.hasClass('open')) {
10359          if (w === 13 || w === 32 || w === 38 || w === 40) {
10360            e.preventDefault();
10361            return trigger.trigger('click.fs');
10362          }
10363        } else {
10364          if (w === 38) {
10365            e.preventDefault();
10366            if (hovered.length && hovered.index() > 0) {
10367              hovered.prev().addClass('hover');
10368            } else {
10369              options.find('li:last-child').addClass('hover');
10370            }
10371          } else if (w === 40) {
10372            e.preventDefault();
10373            if (hovered.length && hovered.index() < options.find('li').length - 1) {
10374              hovered.next().addClass('hover');
10375            } else {
10376              options.find('li:first-child').addClass('hover');
10377            }
10378          } else if (w === 27) {
10379            e.preventDefault();
10380            trigger.trigger('click.fs');
10381          } else if (w === 13 || w === 32) {
10382            e.preventDefault();
10383            hovered.trigger('click.fs');
10384          } else if (w === 9) {
10385            if (trigger.hasClass('open')) {
10386              trigger.trigger('close.fs');
10387            }
10388          }
10389          newHovered = options.find('.hover');
10390          if (newHovered.length) {
10391            options.scrollTop(0);
10392            return options.scrollTop(newHovered.position().top - 12);
10393          }
10394        }
10395      });
10396      options.on('click.fs', 'li', function(e) {
10397        var clicked;
10398        clicked = $(this);
10399        sel.val(clicked.data('raw-value'));
10400        if (!isiOS) {
10401          sel.trigger('blur.fs').trigger('focus.fs');
10402        }
10403        options.find('.selected').removeClass('selected');
10404        clicked.addClass('selected');
10405        trigger.addClass('selected');
10406        return sel.val(clicked.data('raw-value')).trigger('change.fs').trigger('blur.fs').trigger('focus.fs');
10407      });
10408      options.on('mouseenter.fs', 'li', function() {
10409        var hovered, nowHovered;
10410        nowHovered = $(this);
10411        hovered = options.find('.hover');
10412        hovered.removeClass('hover');
10413        return nowHovered.addClass('hover');
10414      });
10415      options.on('mouseleave.fs', 'li', function() {
10416        return options.find('.hover').removeClass('hover');
10417      });
10418      copyOptionsToList = function() {
10419        var selOpts;
10420        updateTriggerText();
10421        if (isiOS && !settings.forceiOS) {
10422          return;
10423        }
10424        selOpts = sel.find('option');
10425        return sel.find('option').each(function(i, opt) {
10426          var optHtml;
10427          opt = $(opt);
10428          if (!opt.prop('disabled') && (opt.val() || settings.includeBlank)) {
10429            optHtml = settings.optionTemplate(opt);
10430            if (opt.prop('selected')) {
10431              return options.append("<li data-raw-value=\"" + (opt.val()) + "\" class=\"selected\">" + optHtml + "</li>");
10432            } else {
10433              return options.append("<li data-raw-value=\"" + (opt.val()) + "\">" + optHtml + "</li>");
10434            }
10435          }
10436        });
10437      };
10438      sel.on('update.fs', function() {
10439        wrapper.find('.options').empty();
10440        return copyOptionsToList();
10441      });
10442      return copyOptionsToList();
10443    });
10444  };
10445
10446}).call(this);
10447/*!
10448 * Flickity PACKAGED v2.3.0
10449 * Touch, responsive, flickable carousels
10450 *
10451 * Licensed GPLv3 for open source use
10452 * or Flickity Commercial License for commercial use
10453 *
10454 * https://flickity.metafizzy.co
10455 * Copyright 2015-2021 Metafizzy
10456 */
10457(function(e,i){if(typeof define=="function"&&define.amd){define("jquery-bridget/jquery-bridget",["jquery"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("jquery"))}else{e.jQueryBridget=i(e,e.jQuery)}})(window,function t(e,r){"use strict";var o=Array.prototype.slice;var i=e.console;var u=typeof i=="undefined"?function(){}:function(t){i.error(t)};function n(h,s,c){c=c||r||e.jQuery;if(!c){return}if(!s.prototype.option){s.prototype.option=function(t){if(!c.isPlainObject(t)){return}this.options=c.extend(true,this.options,t)}}c.fn[h]=function(t){if(typeof t=="string"){var e=o.call(arguments,1);return i(this,t,e)}n(this,t);return this};function i(t,r,o){var a;var l="$()."+h+'("'+r+'")';t.each(function(t,e){var i=c.data(e,h);if(!i){u(h+" not initialized. Cannot call methods, i.e. "+l);return}var n=i[r];if(!n||r.charAt(0)=="_"){u(l+" is not a valid method");return}var s=n.apply(i,o);a=a===undefined?s:a});return a!==undefined?a:t}function n(t,n){t.each(function(t,e){var i=c.data(e,h);if(i){i.option(n);i._init()}else{i=new s(e,n);c.data(e,h,i)}})}a(c)}function a(t){if(!t||t&&t.bridget){return}t.bridget=n}a(r||e.jQuery);return n});(function(t,e){if(typeof define=="function"&&define.amd){define("ev-emitter/ev-emitter",e)}else if(typeof module=="object"&&module.exports){module.exports=e()}else{t.EvEmitter=e()}})(typeof window!="undefined"?window:this,function(){function t(){}var e=t.prototype;e.on=function(t,e){if(!t||!e){return}var i=this._events=this._events||{};var n=i[t]=i[t]||[];if(n.indexOf(e)==-1){n.push(e)}return this};e.once=function(t,e){if(!t||!e){return}this.on(t,e);var i=this._onceEvents=this._onceEvents||{};var n=i[t]=i[t]||{};n[e]=true;return this};e.off=function(t,e){var i=this._events&&this._events[t];if(!i||!i.length){return}var n=i.indexOf(e);if(n!=-1){i.splice(n,1)}return this};e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(!i||!i.length){return}i=i.slice(0);e=e||[];var n=this._onceEvents&&this._onceEvents[t];for(var s=0;s<i.length;s++){var r=i[s];var o=n&&n[r];if(o){this.off(t,r);delete n[r]}r.apply(this,e)}return this};e.allOff=function(){delete this._events;delete this._onceEvents};return t});
10458/*!
10459 * getSize v2.0.3
10460 * measure size of elements
10461 * MIT license
10462 */
10463(function(t,e){if(typeof define=="function"&&define.amd){define("get-size/get-size",e)}else if(typeof module=="object"&&module.exports){module.exports=e()}else{t.getSize=e()}})(window,function t(){"use strict";function m(t){var e=parseFloat(t);var i=t.indexOf("%")==-1&&!isNaN(e);return i&&e}function e(){}var i=typeof console=="undefined"?e:function(t){console.error(t)};var y=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];var b=y.length;function E(){var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0};for(var e=0;e<b;e++){var i=y[e];t[i]=0}return t}function S(t){var e=getComputedStyle(t);if(!e){i("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? "+"See https://bit.ly/getsizebug1")}return e}var n=false;var C;function x(){if(n){return}n=true;var t=document.createElement("div");t.style.width="200px";t.style.padding="1px 2px 3px 4px";t.style.borderStyle="solid";t.style.borderWidth="1px 2px 3px 4px";t.style.boxSizing="border-box";var e=document.body||document.documentElement;e.appendChild(t);var i=S(t);C=Math.round(m(i.width))==200;s.isBoxSizeOuter=C;e.removeChild(t)}function s(t){x();if(typeof t=="string"){t=document.querySelector(t)}if(!t||typeof t!="object"||!t.nodeType){return}var e=S(t);if(e.display=="none"){return E()}var i={};i.width=t.offsetWidth;i.height=t.offsetHeight;var n=i.isBorderBox=e.boxSizing=="border-box";for(var s=0;s<b;s++){var r=y[s];var o=e[r];var a=parseFloat(o);i[r]=!isNaN(a)?a:0}var l=i.paddingLeft+i.paddingRight;var h=i.paddingTop+i.paddingBottom;var c=i.marginLeft+i.marginRight;var u=i.marginTop+i.marginBottom;var d=i.borderLeftWidth+i.borderRightWidth;var f=i.borderTopWidth+i.borderBottomWidth;var p=n&&C;var v=m(e.width);if(v!==false){i.width=v+(p?0:l+d)}var g=m(e.height);if(g!==false){i.height=g+(p?0:h+f)}i.innerWidth=i.width-(l+d);i.innerHeight=i.height-(h+f);i.outerWidth=i.width+c;i.outerHeight=i.height+u;return i}return s});(function(t,e){"use strict";if(typeof define=="function"&&define.amd){define("desandro-matches-selector/matches-selector",e)}else if(typeof module=="object"&&module.exports){module.exports=e()}else{t.matchesSelector=e()}})(window,function t(){"use strict";var n=function(){var t=window.Element.prototype;if(t.matches){return"matches"}if(t.matchesSelector){return"matchesSelector"}var e=["webkit","moz","ms","o"];for(var i=0;i<e.length;i++){var n=e[i];var s=n+"MatchesSelector";if(t[s]){return s}}}();return function t(e,i){return e[n](i)}});(function(e,i){if(typeof define=="function"&&define.amd){define("fizzy-ui-utils/utils",["de
10463sandro-matches-selector/matches-selector"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("desandro-matches-selector"))}else{e.fizzyUIUtils=i(e,e.matchesSelector)}})(window,function t(h,r){var c={};c.extend=function(t,e){for(var i in e){t[i]=e[i]}return t};c.modulo=function(t,e){return(t%e+e)%e};var i=Array.prototype.slice;c.makeArray=function(t){if(Array.isArray(t)){return t}if(t===null||t===undefined){return[]}var e=typeof t=="object"&&typeof t.length=="number";if(e){return i.call(t)}return[t]};c.removeFrom=function(t,e){var i=t.indexOf(e);if(i!=-1){t.splice(i,1)}};c.getParent=function(t,e){while(t.parentNode&&t!=document.body){t=t.parentNode;if(r(t,e)){return t}}};c.getQueryElement=function(t){if(typeof t=="string"){return document.querySelector(t)}return t};c.handleEvent=function(t){var e="on"+t.type;if(this[e]){this[e](t)}};c.filterFindElements=function(t,n){t=c.makeArray(t);var s=[];t.forEach(function(t){if(!(t instanceof HTMLElement)){return}if(!n){s.push(t);return}if(r(t,n)){s.push(t)}var e=t.querySelectorAll(n);for(var i=0;i<e.length;i++){s.push(e[i])}});return s};c.debounceMethod=function(t,e,n){n=n||100;var s=t.prototype[e];var r=e+"Timeout";t.prototype[e]=function(){var t=this[r];clearTimeout(t);var e=arguments;var i=this;this[r]=setTimeout(function(){s.apply(i,e);delete i[r]},n)}};c.docReady=function(t){var e=document.readyState;if(e=="complete"||e=="interactive"){setTimeout(t)}else{document.addEventListener("DOMContentLoaded",t)}};c.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()};var u=h.console;c.htmlInit=function(a,l){c.docReady(function(){var t=c.toDashed(l);var s="data-"+t;var e=document.querySelectorAll("["+s+"]");var i=document.querySelectorAll(".js-"+t);var n=c.makeArray(e).concat(c.makeArray(i));var r=s+"-options";var o=h.jQuery;n.forEach(function(e){var t=e.getAttribute(s)||e.getAttribute(r);var i;try{i=t&&JSON.parse(t)}catch(t){if(u){u.error("Error parsing "+s+" on "+e.className+": "+t)}return}var n=new a(e,i);if(o){o.data(e,l,n)}})})};return c});(function(e,i){if(typeof define=="function"&&define.amd){define("flickity/js/cell",["get-size/get-size"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("get-size"))}else{e.Flickity=e.Flickity||{};e.Flickity.Cell=i(e,e.getSize)}})(window,function t(e,i){function n(t,e){this.element=t;this.parent=e;this.create()}var s=n.prototype;s.create=function(){this.element.style.position="absolute";this.element.setAttribute("aria-hidden","true");this.x=0;this.shift=0;this.element.style[this.parent.originSide]=0};s.destroy=function(){this.unselect();this.element.style.position="";var t=this.parent.originSide;this.element.style[t]="";this.element.style.transform="";this.element.removeAttribute("aria-hidden")};s.getSize=function(){this.size=i(this.element)};s.setPosition=function(t){this.x=t;this.updateTarget();this.renderPosition(t)};s.updateTarget=s.setDefaultTarget=function(){var t=this.parent.originSide=="left"?"marginLeft":"marginRight";this.target=this.x+this.size[t]+this.size.width*this.parent.cellAlign};s.renderPosition=function(t){var e=this.parent.originSide==="left"?1:-1;var i=this.parent.options.percentPosition?t*e*(this.parent.size.innerWidth/this.size.width):t*e;this.element.style.transform="translateX("+this.parent.getPositionValue(i)+")"};s.select=function(){this.element.classList.add("is-selected");this.element.removeAttribute("aria-hidden")};s.unselect=function(){this.element.classList.remove("is-selected");this.element.setAttribute("aria-hidden","true")};s.wrapShift=function(t){this.shift=t;this.renderPosition(this.x+this.parent.slideableWidth*t)};s.remove=function(){this.element.parentNode.removeChild(this.element)};return n});(function(t,e){if(typeof define=="function"&&define.amd){define("flickity/js/slide",e)}else if(typeof module=="object"&&module.exports){module.exports=e()}else{t.Flickity=t.Flickity||{};t.Flickity.Slide=e()}})(window,function t(){"use strict";function e(t){this.parent=t;this.isOriginLeft=t.originSide=="left";this.cells=[];this.outerWidth=0;this.height=0}var i=e.prototype;i.addCell=function(t){this.cells.push(t);this.outerWidth+=t.size.outerWidth;this.height=Math.max(t.size.outerHeight,this.height);if(this.cells.length==1){this.x=t.x;var e=this.isOriginLeft?"marginLeft":"marginRight";this.firstMargin=t.size[e]}};i.updateTarget=function(){var t=this.isOriginLeft?"marginRight":"marginLeft";var e=this.getLastCell();var i=e?e.size[t]:0;var n=this.outerWidth-(this.firstMargin+i);this.target=this.x+this.firstMargin+n*this.parent.cellAlign};i.getLastCell=function(){return this.cells[this.cells.length-1]};
10463i.select=function(){this.cells.forEach(function(t){t.select()})};i.unselect=function(){this.cells.forEach(function(t){t.unselect()})};i.getCellElements=function(){return this.cells.map(function(t){return t.element})};return e});(function(e,i){if(typeof define=="function"&&define.amd){define("flickity/js/animate",["fizzy-ui-utils/utils"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("fizzy-ui-utils"))}else{e.Flickity=e.Flickity||{};e.Flickity.animatePrototype=i(e,e.fizzyUIUtils)}})(window,function t(e,i){var n={};n.startAnimation=function(){if(this.isAnimating){return}this.isAnimating=true;this.restingFrames=0;this.animate()};n.animate=function(){this.applyDragForce();this.applySelectedAttraction();var t=this.x;this.integratePhysics();this.positionSlider();this.settle(t);if(this.isAnimating){var e=this;requestAnimationFrame(function t(){e.animate()})}};n.positionSlider=function(){var t=this.x;if(this.options.wrapAround&&this.cells.length>1){t=i.modulo(t,this.slideableWidth);t-=this.slideableWidth;this.shiftWrapCells(t)}this.setTranslateX(t,this.isAnimating);this.dispatchScrollEvent()};n.setTranslateX=function(t,e){t+=this.cursorPosition;t=this.options.rightToLeft?-t:t;var i=this.getPositionValue(t);this.slider.style.transform=e?"translate3d("+i+",0,0)":"translateX("+i+")"};n.dispatchScrollEvent=function(){var t=this.slides[0];if(!t){return}var e=-this.x-t.target;var i=e/this.slidesWidth;this.dispatchEvent("scroll",null,[i,e])};n.positionSliderAtSelected=function(){if(!this.cells.length){return}this.x=-this.selectedSlide.target;this.velocity=0;this.positionSlider()};n.getPositionValue=function(t){if(this.options.percentPosition){return Math.round(t/this.size.innerWidth*1e4)*.01+"%"}else{return Math.round(t)+"px"}};n.settle=function(t){var e=!this.isPointerDown&&Math.round(this.x*100)==Math.round(t*100);if(e){this.restingFrames++}if(this.restingFrames>2){this.isAnimating=false;delete this.isFreeScrolling;this.positionSlider();this.dispatchEvent("settle",null,[this.selectedIndex])}};n.shiftWrapCells=function(t){var e=this.cursorPosition+t;this._shiftCells(this.beforeShiftCells,e,-1);var i=this.size.innerWidth-(t+this.slideableWidth+this.cursorPosition);this._shiftCells(this.afterShiftCells,i,1)};n._shiftCells=function(t,e,i){for(var n=0;n<t.length;n++){var s=t[n];var r=e>0?i:0;s.wrapShift(r);e-=s.size.outerWidth}};n._unshiftCells=function(t){if(!t||!t.length){return}for(var e=0;e<t.length;e++){t[e].wrapShift(0)}};n.integratePhysics=function(){this.x+=this.velocity;this.velocity*=this.getFrictionFactor()};n.applyForce=function(t){this.velocity+=t};n.getFrictionFactor=function(){return 1-this.options[this.isFreeScrolling?"freeScrollFriction":"friction"]};n.getRestingPosition=function(){return this.x+this.velocity/(1-this.getFrictionFactor())};n.applyDragForce=function(){if(!this.isDraggable||!this.isPointerDown){return}var t=this.dragX-this.x;var e=t-this.velocity;this.applyForce(e)};n.applySelectedAttraction=function(){var t=this.isDraggable&&this.isPointerDown;if(t||this.isFreeScrolling||!this.slides.length){return}var e=this.selectedSlide.target*-1-this.x;var i=e*this.options.selectedAttraction;this.applyForce(i)};return n});(function(o,a){if(typeof define=="function"&&define.amd){define("flickity/js/flickity",["ev-emitter/ev-emitter","get-size/get-size","fizzy-ui-utils/utils","./cell","./slide","./animate"],function(t,e,i,n,s,r){return a(o,t,e,i,n,s,r)})}else if(typeof module=="object"&&module.exports){module.exports=a(o,require("ev-emitter"),require("get-size"),require("fizzy-ui-utils"),require("./cell"),require("./sli
10463de"),require("./animate"))}else{var t=o.Flickity;o.Flickity=a(o,o.EvEmitter,o.getSize,o.fizzyUIUtils,t.Cell,t.Slide,t.animatePrototype)}})(window,function t(n,e,i,a,s,o,r){var l=n.jQuery;var h=n.getComputedStyle;var c=n.console;function u(t,e){t=a.makeArray(t);while(t.length){e.appendChild(t.shift())}}var d=0;var f={};function p(t,e){var i=a.getQueryElement(t);if(!i){if(c){c.error("Bad element for Flickity: "+(i||t))}return}this.element=i;if(this.element.flickityGUID){var n=f[this.element.flickityGUID];if(n)n.option(e);return n}if(l){this.$element=l(this.element)}this.options=a.extend({},this.constructor.defaults);this.option(e);this._create()}p.defaults={accessibility:true,cellAlign:"center",freeScrollFriction:.075,friction:.28,namespaceJQueryEvents:true,percentPosition:true,resize:true,selectedAttraction:.025,setGallerySize:true};p.createMethods=[];var v=p.prototype;a.extend(v,e.prototype);v._create=function(){var t=this.guid=++d;this.element.flickityGUID=t;f[t]=this;this.selectedIndex=0;this.restingFrames=0;this.x=0;this.velocity=0;this.originSide=this.options.rightToLeft?"right":"left";this.viewport=document.createElement("div");this.viewport.className="flickity-viewport";this._createSlider();if(this.options.resize||this.options.watchCSS){n.addEventListener("resize",this)}for(var e in this.options.on){var i=this.options.on[e];this.on(e,i)}p.createMethods.forEach(function(t){this[t]()},this);if(this.options.watchCSS){this.watchCSS()}else{this.activate()}};v.option=function(t){a.extend(this.options,t)};v.activate=function(){if(this.isActive){return}this.isActive=true;this.element.classList.add("flickity-enabled");if(this.options.rightToLeft){this.element.classList.add("flickity-rtl")}this.getSize();var t=this._filterFindCellElements(this.element.children);u(t,this.slider);this.viewport.appendChild(this.slider);this.element.appendChild(this.viewport);this.reloadCells();if(this.options.accessibility){this.element.tabIndex=0;this.element.addEventListener("keydown",this)}this.emitEvent("activate");this.selectInitialIndex();this.isInitActivated=true;this.dispatchEvent("ready")};v._createSlider=function(){var t=document.createElement("div");t.className="flickity-slider";t.style[this.originSide]=0;this.slider=t};v._filterFindCellElements=function(t){return a.filterFindElements(t,this.options.cellSelector)};v.reloadCells=function(){this.cells=this._makeCells(this.slider.children);this.positionCells();this._getWrapShiftCells();this.setGallerySize()};v._makeCells=function(t){var e=this._filterFindCellElements(t);var i=e.map(function(t){return new s(t,this)},this);return i};v.getLastCell=function(){return this.cells[this.cells.length-1]};v.getLastSlide=function(){return this.slides[this.slides.length-1]};v.positionCells=function(){this._sizeCells(this.cells);this._positionCells(0)};v._positionCells=function(t){t=t||0;this.maxCellHeight=t?this.maxCellHeight||0:0;var e=0;if(t>0){var i=this.cells[t-1];e=i.x+i.size.outerWidth}var n=this.cells.length;for(var s=t;s<n;s++){var r=this.cells[s];r.setPosition(e);e+=r.size.outerWidth;this.maxCellHeight=Math.max(r.size.outerHeight,this.maxCellHeight)}this.slideableWidth=e;this.updateSlides();this._containSlides();this.slidesWidth=n?this.getLastSlide().target-this.slides[0].target:0};v._sizeCells=function(t){t.forEach(function(t){t.getSize()})};v.updateSlides=function(){this.slides=[];if(!this.cells.length){return}var n=new o(this);this.slides.push(n);var t=this.originSide=="left";var s=t?"marginRight":"marginLeft";var r=this._getCanCellFit();this.cells.forEach(function(t,e){if(!n.cells.length){n.addCell(t);return}var i=n.outerWidth-n.firstMargin+(t.size.outerWidth-t.size[s]);if(r.call(this,e,i)){n.addCell(t)}else{n.updateTarget();n=new o(this);this.slides.push(n);n.addCell(t)}},this);n.updateTarget();this.updateSelectedSlide()};v._getCanCellFit=function(){var t=this.options.groupCells;if(!t){return function(){return false}}else if(typeof t=="number"){var e=parseInt(t,10);return function(t){return t%e!==0}}var i=typeof t=="string"&&t.match(/^(\d+)%$/);var n=i?parseInt(i[1],10)/100:1;return function(t,e){return e<=(this.size.innerWidth+1)*n}};v._init=v.reposition=function(){this.positionCells();this.positionSliderAtSelected()};v.getSize=function(){this.size=i(this.element);this.setCellAlign();this.cursorPosition=this.size.innerWidth*this.cellAlign};var g={center:{left:.5,right:.5},left:{left:0,right:1},right:{right:0,left:1}};v.setCellAlign=function(){var t=g[this.options.cellAlign];this.cellAlign=t?t[this.originSide]:this.options.cellAlign};v.setGallerySize=function(){if(this.options.setGallerySize){var t=this.options.adaptiveHeight&&this.selectedSlide?this.selectedSlide.height:this.maxCellHeight;this.viewport.style.height=t+"px"}};v._getWrapShiftCells=function(){if(!this.options.wrapAround){return}this._unshiftCells(this.beforeShiftCells);this._unshiftCells(this.afterShiftCells);var t=this.cursorPosition;var e=this.cells.length-1;this.beforeShiftCells=this._getGapCells(t,e,-1);
10463t=this.size.innerWidth-this.cursorPosition;this.afterShiftCells=this._getGapCells(t,0,1)};v._getGapCells=function(t,e,i){var n=[];while(t>0){var s=this.cells[e];if(!s){break}n.push(s);e+=i;t-=s.size.outerWidth}return n};v._containSlides=function(){if(!this.options.contain||this.options.wrapAround||!this.cells.length){return}var t=this.options.rightToLeft;var e=t?"marginRight":"marginLeft";var i=t?"marginLeft":"marginRight";var n=this.slideableWidth-this.getLastCell().size[i];var s=n<this.size.innerWidth;var r=this.cursorPosition+this.cells[0].size[e];var o=n-this.size.innerWidth*(1-this.cellAlign);this.slides.forEach(function(t){if(s){t.target=n*this.cellAlign}else{t.target=Math.max(t.target,r);t.target=Math.min(t.target,o)}},this)};v.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i;this.emitEvent(t,n);if(l&&this.$element){t+=this.options.namespaceJQueryEvents?".flickity":"";var s=t;if(e){var r=new l.Event(e);r.type=t;s=r}this.$element.trigger(s,i)}};v.select=function(t,e,i){if(!this.isActive){return}t=parseInt(t,10);this._wrapSelect(t);if(this.options.wrapAround||e){t=a.modulo(t,this.slides.length)}if(!this.slides[t]){return}var n=this.selectedIndex;this.selectedIndex=t;this.updateSelectedSlide();if(i){this.positionSliderAtSelected()}else{this.startAnimation()}if(this.options.adaptiveHeight){this.setGallerySize()}this.dispatchEvent("select",null,[t]);if(t!=n){this.dispatchEvent("change",null,[t])}this.dispatchEvent("cellSelect")};v._wrapSelect=function(t){var e=this.slides.length;var i=this.options.wrapAround&&e>1;if(!i){return t}var n=a.modulo(t,e);var s=Math.abs(n-this.selectedIndex);var r=Math.abs(n+e-this.selectedIndex);var o=Math.abs(n-e-this.selectedIndex);if(!this.isDragSelect&&r<s){t+=e}else if(!this.isDragSelect&&o<s){t-=e}if(t<0){this.x-=this.slideableWidth}else if(t>=e){this.x+=this.slideableWidth}};v.previous=function(t,e){this.select(this.selectedIndex-1,t,e)};v.next=function(t,e){this.select(this.selectedIndex+1,t,e)};v.updateSelectedSlide=function(){var t=this.slides[this.selectedIndex];if(!t){return}this.unselectSelectedSlide();this.selectedSlide=t;t.select();this.selectedCells=t.cells;this.selectedElements=t.getCellElements();this.selectedCell=t.cells[0];this.selectedElement=this.selectedElements[0]};v.unselectSelectedSlide=function(){if(this.selectedSlide){this.selectedSlide.unselect()}};v.selectInitialIndex=function(){var t=this.options.initialIndex;if(this.isInitActivated){this.select(this.selectedIndex,false,true);return}if(t&&typeof t=="string"){var e=this.queryCell(t);if(e){this.selectCell(t,false,true);return}}var i=0;if(t&&this.slides[t]){i=t}this.select(i,false,true)};v.selectCell=function(t,e,i){var n=this.queryCell(t);if(!n){return}var s=this.getCellSlideIndex(n);this.select(s,e,i)};v.getCellSlideIndex=function(t){for(var e=0;e<this.slides.length;e++){var i=this.slides[e];var n=i.cells.indexOf(t);if(n!=-1){return e}}};v.getCell=function(t){for(var e=0;e<this.cells.length;e++){var i=this.cells[e];if(i.element==t){return i}}};v.getCells=function(t){t=a.makeArray(t);var i=[];t.forEach(function(t){var e=this.getCell(t);if(e){i.push(e)}},this);return i};v.getCellElements=function(){return this.cells.map(function(t){return t.element})};v.getParentCell=function(t){var e=this.getCell(t);if(e){return e}t=a.getParent(t,".flickity-slider > *");return this.getCell(t)};v.getAdjacentCellElements=function(t,e){if(!t){return this.selectedSlide.getCellElements()}e=e===undefined?this.selectedIndex:e;var i=this.slides.length;if(1+t*2>=i){return this.getCellElements()}var n=[];for(var s=e-t;s<=e+t;s++){var r=this.options.wrapAround?a.modulo(s,i):s;var o=this.slides[r];if(o){n=n.concat(o.getCellElements())}}return n};v.queryCell=function(t){if(typeof t=="number"){return this.cells[t]}if(typeof t=="string"){if(t.match(/^[#.]?[\d/]/)){return}t=this.element.querySelector(t)}return this.getCell(t)};v.uiChange=function(){this.emitEvent("uiChange")};v.childUIPointerDown=function(t){if(t.type!="touchstart"){t.preventDefault()}this.focus()};v.onresize=function(){this.watchCSS();this.resize()};a.debounceMethod(p,"onresize",150);v.resize=function(){if(!this.isActive||this.isAnimating||this.isDragging){return}this.getSize();if(this.options.wrapAround){this.x=a.modulo(this.x,this.slideableWidth)}this.positionCells();this._getWrapShiftCells();this.setGallerySize();this.emitEvent("resize");var t=this.selectedElements&&this.selectedElements[0];this.selectCell(t,false,true)};v.watchCSS=function(){var t=this.options.watchCSS;if(!t){return}var e=h(this.element,":after").content;if(e.indexOf("flickity")!=-1){this.activate()}else{this.deactivate()}};v.onkeydown=function(t){var e=document.activeElement&&document.activeElement!=this.element;if(!this.options.accessibility||e){return}var i=p.keyboardHandlers[t.keyCode];if(i){i.call(this)}};p.keyboardHandlers={37:function(){var t=this.options.rightToLeft?"next":"previous";this.uiChange();this[t]()},39:function(){var t=this.options.rightToLeft?"previous":"next";this.uiChange();this[t]()}};v.focus=function(){var t=n.pageYOffset;this.element.focus({preventScroll:true});if(n.pageYOffset!=t){n.scrollTo(n.pageXOffset,t)}};v.deactivate=function(){if(!this.isActive){return}this.element.classList.remove("flickity-enabled");this.element.classList.remove("flickity-rtl");this.unselectSelectedSlide();
10463this.cells.forEach(function(t){t.destroy()});this.element.removeChild(this.viewport);u(this.slider.children,this.element);if(this.options.accessibility){this.element.removeAttribute("tabIndex");this.element.removeEventListener("keydown",this)}this.isActive=false;this.emitEvent("deactivate")};v.destroy=function(){this.deactivate();n.removeEventListener("resize",this);this.allOff();this.emitEvent("destroy");if(l&&this.$element){l.removeData(this.element,"flickity")}delete this.element.flickityGUID;delete f[this.guid]};a.extend(v,r);p.data=function(t){t=a.getQueryElement(t);var e=t&&t.flickityGUID;return e&&f[e]};a.htmlInit(p,"flickity");if(l&&l.bridget){l.bridget("flickity",p)}p.setJQuery=function(t){l=t};p.Cell=s;p.Slide=o;return p});
10464/*!
10465 * Unipointer v2.4.0
10466 * base class for doing one thing with pointer event
10467 * MIT license
10468 */
10469(function(e,i){if(typeof define=="function"&&define.amd){define("unipointer/unipointer",["ev-emitter/ev-emitter"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("ev-emitter"))}else{e.Unipointer=i(e,e.EvEmitter)}})(window,function t(s,e){function i(){}function n(){}var r=n.prototype=Object.create(e.prototype);r.bindStartEvent=function(t){this._bindStartEvent(t,true)};r.unbindStartEvent=function(t){this._bindStartEvent(t,false)};r._bindStartEvent=function(t,e){e=e===undefined?true:e;var i=e?"addEventListener":"removeEventListener";var n="mousedown";if("ontouchstart"in s){n="touchstart"}else if(s.PointerEvent){n="pointerdown"}t[i](n,this)};r.handleEvent=function(t){var e="on"+t.type;if(this[e]){this[e](t)}};r.getTouch=function(t){for(var e=0;e<t.length;e++){var i=t[e];if(i.identifier==this.pointerIdentifier){return i}}};r.onmousedown=function(t){var e=t.button;if(e&&(e!==0&&e!==1)){return}this._pointerDown(t,t)};r.ontouchstart=function(t){this._pointerDown(t,t.changedTouches[0])};r.onpointerdown=function(t){this._pointerDown(t,t)};r._pointerDown=function(t,e){if(t.button||this.isPointerDown){return}this.isPointerDown=true;this.pointerIdentifier=e.pointerId!==undefined?e.pointerId:e.identifier;this.pointerDown(t,e)};r.pointerDown=function(t,e){this._bindPostStartEvents(t);this.emitEvent("pointerDown",[t,e])};var o={mousedown:["mousemove","mouseup"],touchstart:["touchmove","touchend","touchcancel"],pointerdown:["pointermove","pointerup","pointercancel"]};r._bindPostStartEvents=function(t){if(!t){return}var e=o[t.type];e.forEach(function(t){s.addEventListener(t,this)},this);this._boundPointerEvents=e};r._unbindPostStartEvents=function(){if(!this._boundPointerEvents){return}this._boundPointerEvents.forEach(function(t){s.removeEventListener(t,this)},this);delete this._boundPointerEvents};r.onmousemove=function(t){this._pointerMove(t,t)};r.onpointermove=function(t){if(t.pointerId==this.pointerIdentifier){this._pointerMove(t,t)}};r.ontouchmove=function(t){var e=this.getTouch(t.changedTouches);if(e){this._pointerMove(t,e)}};r._pointerMove=function(t,e){this.pointerMove(t,e)};r.pointerMove=function(t,e){this.emitEvent("pointerMove",[t,e])};r.onmouseup=function(t){this._pointerUp(t,t)};r.onpointerup=function(t){if(t.pointerId==this.pointerIdentifier){this._pointerUp(t,t)}};r.ontouchend=function(t){var e=this.getTouch(t.changedTouches);if(e){this._pointerUp(t,e)}};r._pointerUp=function(t,e){this._pointerDone();this.pointerUp(t,e)};r.pointerUp=function(t,e){this.emitEvent("pointerUp",[t,e])};r._pointerDone=function(){this._pointerReset();this._unbindPostStartEvents();this.pointerDone()};r._pointerReset=function(){this.isPointerDown=false;delete this.pointerIdentifier};r.pointerDone=i;r.onpointercancel=function(t){if(t.pointerId==this.pointerIdentifier){this._pointerCancel(t,t)}};r.ontouchcancel=function(t){var e=this.getTouch(t.changedTouches);if(e){this._pointerCancel(t,e)}};r._pointerCancel=function(t,e){this._pointerDone();this.pointerCancel(t,e)};r.pointerCancel=function(t,e){this.emitEvent("pointerCancel",[t,e])};n.getPointerPoint=function(t){return{x:t.pageX,y:t.pageY}};return n});
10470/*!
10471 * Unidragger v2.4.0
10472 * Draggable base class
10473 * MIT license
10474 */
10475(function(e,i){if(typeof define=="function"&&define.amd){define("unidragger/unidragger",["unipointer/unipointer"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("unipointer"))}else{e.Unidragger=i(e,e.Unipointer)}})(window,function t(r,e){function i(){}var n=i.prototype=Object.create(e.prototype);n.bindHandles=function(){this._bindHandles(true)};n.unbindHandles=function(){this._bindHandles(false)};n._bindHandles=function(t){t=t===undefined?true:t;var e=t?"addEventListener":"removeEventListener";var i=t?this._touchActionValue:"";for(var n=0;n<this.handles.length;n++){var s=this.handles[n];this._bindStartEvent(s,t);s[e]("click",this);if(r.PointerEvent){s.style.touchAction=i}}};n._touchActionValue="none";n.pointerDown=function(t,e){var i=this.okayPointerDown(t);if(!i){return}this.pointerDownPointer={pageX:e.pageX,pageY:e.pageY};t.preventDefault();this.pointerDownBlur();this._bindPostStartEvents(t);this.emitEvent("pointerDown",[t,e])};var s={TEXTAREA:true,INPUT:true,SELECT:true,OPTION:true};var o={radio:true,checkbox:true,button:true,submit:true,image:true,file:true};n.okayPointerDown=function(t){var e=s[t.target.nodeName];var i=o[t.target.type];var n=!e||i;
10475if(!n){this._pointerReset()}return n};n.pointerDownBlur=function(){var t=document.activeElement;var e=t&&t.blur&&t!=document.body;if(e){t.blur()}};n.pointerMove=function(t,e){var i=this._dragPointerMove(t,e);this.emitEvent("pointerMove",[t,e,i]);this._dragMove(t,e,i)};n._dragPointerMove=function(t,e){var i={x:e.pageX-this.pointerDownPointer.pageX,y:e.pageY-this.pointerDownPointer.pageY};if(!this.isDragging&&this.hasDragStarted(i)){this._dragStart(t,e)}return i};n.hasDragStarted=function(t){return Math.abs(t.x)>3||Math.abs(t.y)>3};n.pointerUp=function(t,e){this.emitEvent("pointerUp",[t,e]);this._dragPointerUp(t,e)};n._dragPointerUp=function(t,e){if(this.isDragging){this._dragEnd(t,e)}else{this._staticClick(t,e)}};n._dragStart=function(t,e){this.isDragging=true;this.isPreventingClicks=true;this.dragStart(t,e)};n.dragStart=function(t,e){this.emitEvent("dragStart",[t,e])};n._dragMove=function(t,e,i){if(!this.isDragging){return}this.dragMove(t,e,i)};n.dragMove=function(t,e,i){t.preventDefault();this.emitEvent("dragMove",[t,e,i])};n._dragEnd=function(t,e){this.isDragging=false;
10475setTimeout(function(){delete this.isPreventingClicks}.bind(this));this.dragEnd(t,e)};n.dragEnd=function(t,e){this.emitEvent("dragEnd",[t,e])};n.onclick=function(t){if(this.isPreventingClicks){t.preventDefault()}};n._staticClick=function(t,e){if(this.isIgnoringMouseUp&&t.type=="mouseup"){return}this.staticClick(t,e);if(t.type!="mouseup"){this.isIgnoringMouseUp=true;setTimeout(function(){delete this.isIgnoringMouseUp}.bind(this),400)}};n.staticClick=function(t,e){this.emitEvent("staticClick",[t,e])};i.getPointerPoint=e.getPointerPoint;return i});(function(n,s){if(typeof define=="function"&&define.amd){define("flickity/js/drag",["./flickity","unidragger/unidragger","fizzy-ui-utils/utils"],function(t,e,i){return s(n,t,e,i)})}else if(typeof module=="object"&&module.exports){module.exports=s(n,require("./flickity"),require("unidragger"),require("fizzy-ui-utils"))}else{n.Flickity=s(n,n.Flickity,n.Unidragger,n.fizzyUIUtils)}})(window,function t(n,e,i,a){a.extend(e.defaults,{draggable:">1",dragThreshold:3});e.createMethods.push("_createDrag");var s=e.prototype;a.extend(s,i.prototype);s._touchActionValue="pan-y";s._createDrag=function(){this.on("activate",this.onActivateDrag);this.on("uiChange",this._uiChangeDrag);this.on("deactivate",this.onDeactivateDrag);this.on("cellChange",this.updateDraggable)};s.onActivateDrag=function(){this.handles=[this.viewport];this.bindHandles();this.updateDraggable()};s.onDeactivateDrag=function(){this.unbindHandles();this.element.classList.remove("is-draggable")};s.updateDraggable=function(){if(this.options.draggable==">1"){this.isDraggable=this.slides.length>1}else{this.isDraggable=this.options.draggable}if(this.isDraggable){this.element.classList.add("is-draggable")}else{this.element.classList.remove("is-draggable")}};s.bindDrag=function(){this.options.draggable=true;this.updateDraggable()};s.unbindDrag=function(){this.options.draggable=false;this.updateDraggable()};s._uiChangeDrag=function(){delete this.isFreeScrolling};s.pointerDown=function(t,e){if(!this.isDraggable){this._pointerDownDefault(t,e);return}var i=this.okayPointerDown(t);if(!i){return}this._pointerDownPreventDefault(t);this.pointerDownFocus(t);if(document.activeElement!=this.element){this.pointerDownBlur()}this.dragX=this.x;this.viewport.classList.add("is-pointer-down");this.pointerDownScroll=o();n.addEventListener("scroll",this);this._pointerDownDefault(t,e)};s._pointerDownDefault=function(t,e){this.pointerDownPointer={pageX:e.pageX,pageY:e.pageY};this._bindPostStartEvents(t);this.dispatchEvent("pointerDown",t,[e])};var r={INPUT:true,TEXTAREA:true,SELECT:true};s.pointerDownFocus=function(t){var e=r[t.target.nodeName];if(!e){this.focus()}};s._pointerDownPreventDefault=function(t){var e=t.type=="touchstart";var i=t.pointerType=="touch";var n=r[t.target.nodeName];if(!e&&!i&&!n){t.preventDefault()}};s.hasDragStarted=function(t){return Math.abs(t.x)>this.options.dragThreshold};s.pointerUp=function(t,e){delete this.isTouchScrolling;this.viewport.classList.remove("is-pointer-down");this.dispatchEvent("pointerUp",t,[e]);this._dragPointerUp(t,e)};s.pointerDone=function(){n.removeEventListener("scroll",this);delete this.pointerDownScroll};s.dragStart=function(t,e){if(!this.isDraggable){return}this.dragStartPosition=this.x;this.startAnimation();n.removeEventListener("scroll",this);this.dispatchEvent("dragStart",t,[e])};s.pointerMove=function(t,e){var i=this._dragPointerMove(t,e);this.dispatchEvent("pointerMove",t,[e,i]);this._dragMove(t,e,i)};s.dragMove=function(t,e,i){if(!this.isDraggable){return}t.preventDefault();this.previousDragX=this.dragX;var n=this.options.rightToLeft?-1:1;if(this.options.wrapAround){i.x%=this.slideableWidth}var s=this.dragStartPosition+i.x*n;if(!this.options.wrapAround&&this.slides.length){var r=Math.max(-this.slides[0].target,this.dragStartPosition);s=s>r?(s+r)*.5:s;var o=Math.min(-this.getLastSlide().target,this.dragStartPosition);s=s<o?(s+o)*.5:s}this.dragX=s;this.dragMoveTime=new Date;this.dispatchEvent("dragMove",t,[e,i])};s.dragEnd=function(t,e){if(!this.isDraggable){return}if(this.options.freeScroll){this.isFreeScrolling=true}var i=this.dragEndRestingSelect();if(this.options.freeScroll&&!this.options.wrapAround){var n=this.getRestingPosition();this.isFreeScrolling=-n>this.slides[0].target&&-n<this.getLastSlide().target}else if(!this.options.freeScroll&&i==this.selectedIndex){i+=this.dragEndBoostSelect()}delete this.previousDragX;this.isDragSelect=this.options.wrapAround;this.select(i);delete this.isDragSelect;this.dispatchEvent("dragEnd",t,[e])};s.dragEndRestingSelect=function(){var t=this.getRestingPosition();var e=Math.abs(this.getSlideDistance(-t,this.selectedIndex));var i=this._getClosestResting(t,e,1);var n=this._getClosestResting(t,e,-1);var s=i.distance<n.distance?i.index:n.index;return s};
10475s._getClosestResting=function(t,e,i){var n=this.selectedIndex;var s=Infinity;var r=this.options.contain&&!this.options.wrapAround?function(t,e){return t<=e}:function(t,e){return t<e};while(r(e,s)){n+=i;s=e;e=this.getSlideDistance(-t,n);if(e===null){break}e=Math.abs(e)}return{distance:s,index:n-i}};s.getSlideDistance=function(t,e){var i=this.slides.length;var n=this.options.wrapAround&&i>1;var s=n?a.modulo(e,i):e;var r=this.slides[s];if(!r){return null}var o=n?this.slideableWidth*Math.floor(e/i):0;return t-(r.target+o)};s.dragEndBoostSelect=function(){if(this.previousDragX===undefined||!this.dragMoveTime||new Date-this.dragMoveTime>100){return 0}var t=this.getSlideDistance(-this.dragX,this.selectedIndex);var e=this.previousDragX-this.dragX;if(t>0&&e>0){return 1}else if(t<0&&e<0){return-1}return 0};s.staticClick=function(t,e){var i=this.getParentCell(t.target);var n=i&&i.element;var s=i&&this.cells.indexOf(i);this.dispatchEvent("staticClick",t,[e,n,s])};s.onscroll=function(){var t=o();var e=this.pointerDownScroll.x-t.x;var i=this.pointerDownScroll.y-t.y;if(Math.abs(e)>3||Math.abs(i)>3){this._pointerDone()}};function o(){return{x:n.pageXOffset,y:n.pageYOffset}}return e});(function(n,s){if(typeof define=="function"&&define.amd){define("flickity/js/prev-next-button",["./flickity","unipointer/unipointer","fizzy-ui-utils/utils"],function(t,e,i){return s(n,t,e,i)})}else if(typeof module=="object"&&module.exports){module.exports=s(n,require("./flickity"),require("unipointer"),require("fizzy-ui-utils"))}else{s(n,n.Flickity,n.Unipointer,n.fizzyUIUtils)}})(window,function t(e,i,n,s){"use strict";var r="http://www.w3.org/2000/svg";function o(t,e){this.direction=t;this.parent=e;this._create()}o.prototype=Object.create(n.prototype);o.prototype._create=function(){this.isEnabled=true;this.isPrevious=this.direction==-1;var t=this.parent.options.rightToLeft?1:-1;this.isLeft=this.direction==t;var e=this.element=document.createElement("button");e.className="flickity-button flickity-prev-next-button";e.className+=this.isPrevious?" previous":" next";e.setAttribute("type","button");this.disable();e.setAttribute("aria-label",this.isPrevious?"Previous":"Next");var i=this.createSVG();e.appendChild(i);this.parent.on("select",this.update.bind(this));this.on("pointerDown",this.parent.childUIPointerDown.bind(this.parent))};o.prototype.activate=function(){this.bindStartEvent(this.element);this.element.addEventListener("click",this);this.parent.element.appendChild(this.element)};o.prototype.deactivate=function(){this.parent.element.removeChild(this.element);this.unbindStartEvent(this.element);this.element.removeEventListener("click",this)};o.prototype.createSVG=function(){var t=document.createElementNS(r,"svg");t.setAttribute("class","flickity-button-icon");t.setAttribute("viewBox","0 0 100 100");var e=document.createElementNS(r,"path");var i=a(this.parent.options.arrowShape);e.setAttribute("d",i);e.setAttribute("class","arrow");if(!this.isLeft){e.setAttribute("transform","translate(100, 100) rotate(180) ")}t.appendChild(e);return t};function a(t){if(typeof t=="string"){return t}return"M "+t.x0+",50"+" L "+t.x1+","+(t.y1+50)+" L "+t.x2+","+(t.y2+50)+" L "+t.x3+",50 "+" L "+t.x2+","+(50-t.y2)+" L "+t.x1+","+(50-t.y1)+" Z"}o.prototype.handleEvent=s.handleEvent;o.prototype.onclick=function(){if(!this.isEnabled){return}this.parent.uiChange();var t=this.isPrevious?"previous":"next";this.parent[t]()};o.prototype.enable=function(){if(this.isEnabled){return}this.element.disabled=false;this.isEnabled=true};o.prototype.disable=function(){if(!this.isEnabled){return}this.element.disabled=true;this.isEnabled=false};o.prototype.update=function(){var t=this.parent.slides;if(this.parent.options.wrapAround&&t.length>1){this.enable();return}var e=t.length?t.length-1:0;var i=this.isPrevious?0:e;var n=this.parent.selectedIndex==i?"disable":"enable";this[n]()};o.prototype.destroy=function(){this.deactivate();this.allOff()};s.extend(i.defaults,{prevNextButtons:true,arrowShape:{x0:10,x1:60,y1:50,x2:70,y2:40,x3:30}});i.createMethods.push("_createPrevNextButtons");var l=i.prototype;l._createPrevNextButtons=function(){if(!this.options.prevNextButtons){return}this.prevButton=new o(-1,this);this.nextButton=new o(1,this);this.on("activate",this.activatePrevNextButtons)};l.activatePrevNextButtons=function(){this.prevButton.activate();this.nextButton.activate();this.on("deactivate",this.deactivatePrevNextButtons)};l.deactivatePrevNextButtons=function(){this.prevButton.deactivate();this.nextButton.deactivate();this.off("deactivate",this.deactivatePrevNextButtons)};i.PrevNextButton=o;return i});(function(n,s){if(typeof define=="function"&&define.amd){define("flickity/js/page-dots",["./flickity","unipointer/unipointer","fizzy-ui-utils/utils"],function(t,e,
10475i){return s(n,t,e,i)})}else if(typeof module=="object"&&module.exports){module.exports=s(n,require("./flickity"),require("unipointer"),require("fizzy-ui-utils"))}else{s(n,n.Flickity,n.Unipointer,n.fizzyUIUtils)}})(window,function t(e,i,n,s){function r(t){this.parent=t;this._create()}r.prototype=Object.create(n.prototype);r.prototype._create=function(){this.holder=document.createElement("ol");this.holder.className="flickity-page-dots";this.dots=[];this.handleClick=this.onClick.bind(this);this.on("pointerDown",this.parent.childUIPointerDown.bind(this.parent))};r.prototype.activate=function(){this.setDots();this.holder.addEventListener("click",this.handleClick);this.bindStartEvent(this.holder);this.parent.element.appendChild(this.holder)};r.prototype.deactivate=function(){this.holder.removeEventListener("click",this.handleClick);this.unbindStartEvent(this.holder);this.parent.element.removeChild(this.holder)};r.prototype.setDots=function(){var t=this.parent.slides.length-this.dots.length;if(t>0){this.addDots(t)}else if(t<0){this.removeDots(-t)}};r.prototype.addDots=function(t){var e=document.createDocumentFragment();var i=[];var n=this.dots.length;var s=n+t;for(var r=n;r<s;r++){var o=document.createElement("li");o.className="dot";o.setAttribute("aria-label","Page dot "+(r+1));e.appendChild(o);i.push(o)}this.holder.appendChild(e);this.dots=this.dots.concat(i)};r.prototype.removeDots=function(t){var e=this.dots.splice(this.dots.length-t,t);e.forEach(function(t){this.holder.removeChild(t)},this)};r.prototype.updateSelected=function(){if(this.selectedDot){this.selectedDot.className="dot";this.selectedDot.removeAttribute("aria-current")}if(!this.dots.length){return}this.selectedDot=this.dots[this.parent.selectedIndex];this.selectedDot.className="dot is-selected";this.selectedDot.setAttribute("aria-current","step")};r.prototype.onTap=r.prototype.onClick=function(t){var e=t.target;if(e.nodeName!="LI"){return}this.parent.uiChange();var i=this.dots.indexOf(e);this.parent.select(i)};r.prototype.destroy=function(){this.deactivate();this.allOff()};i.PageDots=r;s.extend(i.defaults,{pageDots:true});i.createMethods.push("_createPageDots");var o=i.prototype;o._createPageDots=function(){if(!this.options.pageDots){return}this.pageDots=new r(this);this.on("activate",this.activatePageDots);this.on("select",this.updateSelectedPageDots);this.on("cellChange",this.updatePageDots);this.on("resize",this.updatePageDots);this.on("deactivate",this.deactivatePageDots)};o.activatePageDots=function(){this.pageDots.activate()};o.updateSelectedPageDots=function(){this.pageDots.updateSelected()};o.updatePageDots=function(){this.pageDots.setDots()};o.deactivatePageDots=function(){this.pageDots.deactivate()};i.PageDots=r;return i});(function(t,n){if(typeof define=="function"&&define.amd){define("flickity/js/player",["ev-emitter/ev-emitter","fizzy-ui-utils/utils","./flickity"],function(t,e,i){return n(t,e,i)})}else if(typeof module=="object"&&module.exports){module.exports=n(require("ev-emitter"),require("fizzy-ui-utils"),require("./flickity"))}else{n(t.EvEmitter,t.fizzyUIUtils,t.Flickity)}})(window,function t(e,i,n){function s(t){this.parent=t;this.state="stopped";this.onVisibilityChange=this.visibilityChange.bind(this);this.onVisibilityPlay=this.visibilityPlay.bind(this)}s.prototype=Object.create(e.prototype);s.prototype.play=function(){if(this.state=="playing"){return}var t=document.hidden;if(t){document.addEventListener("visibilitychange",this.onVisibilityPlay);return}this.state="playing";document.addEventListener("visibilitychange",this.onVisibilityChange);this.tick()};s.prototype.tick=function(){if(this.state!="playing"){return}var t=this.parent.options.autoPlay;t=typeof t=="number"?t:3e3;var e=this;this.clear();this.timeout=setTimeout(function(){e.parent.next(true);e.tick()},t)};s.prototype.stop=function(){this.state="stopped";this.clear();document.removeEventListener("visibilitychange",this.onVisibilityChange)};s.prototype.clear=function(){clearTimeout(this.timeout)};s.prototype.pause=function(){if(this.state=="playing"){this.state="paused";this.clear()}};s.prototype.unpause=function(){if(this.state=="paused"){this.play()}};s.prototype.visibilityChange=function(){var t=document.hidden;this[t?"pause":"unpause"]()};s.prototype.visibilityPlay=function(){this.play();document.removeEventListener("visibilitychange",this.onVisibilityPlay)};i.extend(n.defaults,{pauseAutoPlayOnHover:true});n.createMethods.push("_createPlayer");var r=n.prototype;r._createPlayer=function(){this.player=new s(this);this.on("activate",this.activatePlayer);this.on("uiChange",this.stopPlayer);this.on("pointerDown",this.stopPlayer);this.on("deactivate",this.deactivatePlayer)};r.activatePlayer=function(){if(!this.options.autoPlay){return}this.player.play();this.element.addEventListener("mouseenter",this)};r.playPlayer=function(){this.player.play()};r.stopPlayer=function(){this.player.stop()};r.pausePlayer=function(){this.player.pause()};r.unpausePlayer=function(){this.player.unpause()};r.deactivatePlayer=function(){this.player.stop();this.element.removeEventListener("mouseenter",this)};r.onmouseenter=function(){if(!this.options.pauseAutoPlayOnHover){return}this.player.pause();this.element.addEventListener("mouseleave",this)};r.onmouseleave=function(){this.player.unpause();this.element.removeEventListener("mouseleave",this)};n.Player=s;return n});(function(i,n){if(typeof define=="function"&&define.amd){define("flickity/js/add-remove-cell",["./flickity","fizzy-ui-utils/utils"],function(t,e){return n(i,t,e)})}else if(typeof module=="object"&&module.exports){module.exports=n(i,require("./flickity"),require("fizzy-ui-utils"))}else{n(i,i.Flickity,i.fizzyUIUtils)}})(window,function t(e,i,n){function l(t){var e=document.createDocumentFragment();t.forEach(function(t){e.appendChild(t.element)});return e}var s=i.prototype;s.insert=function(t,e){var i=this._makeCells(t);if(!i||!i.length){return}var n=this.cells.length;e=e===undefined?n:e;var s=l(i);var r=e==n;if(r){this.slider.appendChild(s)}else{var o=this.cells[e].element;this.slider.insertBefore(s,o)}if(e===0){this.cells=i.concat(this.cells)}else if(r){this.cells=this.cells.concat(i)}else{var a=this.cells.splice(e,n-e);
10475this.cells=this.cells.concat(i).concat(a)}this._sizeCells(i);this.cellChange(e,true)};s.append=function(t){this.insert(t,this.cells.length)};s.prepend=function(t){this.insert(t,0)};s.remove=function(t){var e=this.getCells(t);if(!e||!e.length){return}var i=this.cells.length-1;e.forEach(function(t){t.remove();var e=this.cells.indexOf(t);i=Math.min(e,i);n.removeFrom(this.cells,t)},this);this.cellChange(i,true)};s.cellSizeChange=function(t){var e=this.getCell(t);if(!e){return}e.getSize();var i=this.cells.indexOf(e);this.cellChange(i)};s.cellChange=function(t,e){var i=this.selectedElement;this._positionCells(t);this._getWrapShiftCells();this.setGallerySize();var n=this.getCell(i);if(n){this.selectedIndex=this.getCellSlideIndex(n)}this.selectedIndex=Math.min(this.slides.length-1,this.selectedIndex);this.emitEvent("cellChange",[t]);this.select(this.selectedIndex);if(e){this.positionSliderAtSelected()}};return i});(function(i,n){if(typeof define=="function"&&define.amd){define("flickity/js/lazyload",["./flickity","fizzy-ui-utils/utils"],function(t,e){return n(i,t,e)})}else if(typeof module=="object"&&module.exports){module.exports=n(i,require("./flickity"),require("fizzy-ui-utils"))}else{n(i,i.Flickity,i.fizzyUIUtils)}})(window,function t(e,i,o){"use strict";i.createMethods.push("_createLazyload");var n=i.prototype;n._createLazyload=function(){this.on("select",this.lazyLoad)};n.lazyLoad=function(){var t=this.options.lazyLoad;if(!t){return}var e=typeof t=="number"?t:0;var i=this.getAdjacentCellElements(e);var n=[];i.forEach(function(t){var e=s(t);n=n.concat(e)});n.forEach(function(t){new r(t,this)},this)};function s(t){if(t.nodeName=="IMG"){var e=t.getAttribute("data-flickity-lazyload");var i=t.getAttribute("data-flickity-lazyload-src");var n=t.getAttribute("data-flickity-lazyload-srcset");if(e||i||n){return[t]}}var s="img[data-flickity-lazyload], "+"img[data-flickity-lazyload-src], img[data-flickity-lazyload-srcset]";var r=t.querySelectorAll(s);return o.makeArray(r)}function r(t,e){this.img=t;this.flickity=e;this.load()}r.prototype.handleEvent=o.handleEvent;r.prototype.load=function(){this.img.addEventListener("load",this);this.img.addEventListener("error",this);var t=this.img.getAttribute("data-flickity-lazyload")||this.img.getAttribute("data-flickity-lazyload-src");var e=this.img.getAttribute("data-flickity-lazyload-srcset");this.img.src=t;if(e){this.img.setAttribute("srcset",e)}this.img.removeAttribute("data-flickity-lazyload");this.img.removeAttribute("data-flickity-lazyload-src");this.img.removeAttribute("data-flickity-lazyload-srcset")};r.prototype.onload=function(t){this.complete(t,"flickity-lazyloaded")};r.prototype.onerror=function(t){this.complete(t,"flickity-lazyerror")};r.prototype.complete=function(t,e){this.img.removeEventListener("load",this);this.img.removeEventListener("error",this);var i=this.flickity.getParentCell(this.img);var n=i&&i.element;this.flickity.cellSizeChange(n);this.img.classList.add(e);this.flickity.dispatchEvent("lazyLoad",t,n)};i.LazyLoader=r;return i});
10476/*!
10477 * Flickity v2.3.0
10478 * Touch, responsive, flickable carousels
10479 *
10480 * Licensed GPLv3 for open source use
10481 * or Flickity Commercial License for commercial use
10482 *
10483 * https://flickity.metafizzy.co
10484 * Copyright 2015-2021 Metafizzy
10485 */
10486(function(t,e){if(typeof define=="function"&&define.amd){define("flickity/js/index",["./flickity","./drag","./prev-next-button","./page-dots","./player","./add-remove-cell","./lazyload"],e)}else if(typeof module=="object"&&module.exports){module.exports=e(require("./flickity"),require("./drag"),require("./prev-next-button"),require("./page-dots"),require("./player"),require("./add-remove-cell"),require("./lazyload"))}})(window,function t(e){return e});
10487/*!
10488 * Flickity asNavFor v2.0.2
10489 * enable asNavFor for Flickity
10490 */
10491(function(t,e){if(typeof define=="function"&&define.amd){define("flickity-as-nav-for/as-nav-for",["flickity/js/index","fizzy-ui-utils/utils"],e)}else if(typeof module=="object"&&module.exports){module.exports=e(require("flickity"),require("fizzy-ui-utils"))}else{t.Flickity=e(t.Flickity,t.fizzyUIUtils)}})(window,function t(n,s){n.createMethods.push("_createAsNavFor");var e=n.prototype;e._createAsNavFor=function(){this.on("activate",this.activateAsNavFor);this.on("deactivate",this.deactivateAsNavFor);this.on("destroy",this.destroyAsNavFor);var e=this.options.asNavFor;if(!e){return}var i=this;setTimeout(function t(){i.setNavCompanion(e)})};e.setNavCompanion=function(t){t=s.getQueryElement(t);var e=n.data(t);
10491if(!e||e==this){return}this.navCompanion=e;var i=this;this.onNavCompanionSelect=function(){i.navCompanionSelect()};e.on("select",this.onNavCompanionSelect);this.on("staticClick",this.onNavStaticClick);this.navCompanionSelect(true)};e.navCompanionSelect=function(t){var e=this.navCompanion&&this.navCompanion.selectedCells;if(!e){return}var i=e[0];var n=this.navCompanion.cells.indexOf(i);var s=n+e.length-1;var r=Math.floor(a(n,s,this.navCompanion.cellAlign));this.selectCell(r,false,t);this.removeNavSelectedElements();if(r>=this.cells.length){return}var o=this.cells.slice(n,s+1);this.navSelectedElements=o.map(function(t){return t.element});this.changeNavSelectedClass("add")};function a(t,e,i){return(e-t)*i+t}e.changeNavSelectedClass=function(e){this.navSelectedElements.forEach(function(t){t.classList[e]("is-nav-selected")})};e.activateAsNavFor=function(){this.navCompanionSelect(true)};e.removeNavSelectedElements=function(){if(!this.navSelectedElements){return}this.changeNavSelectedClass("remove");delete this.navSelectedElements};e.onNavStaticClick=function(t,e,i,n){if(typeof n=="number"){this.navCompanion.selectCell(n)}};e.deactivateAsNavFor=function(){this.removeNavSelectedElements()};e.destroyAsNavFor=function(){if(!this.navCompanion){return}this.navCompanion.off("select",this.onNavCompanionSelect);this.off("staticClick",this.onNavStaticClick);delete this.navCompanion};return n});
10492/*!
10493 * imagesLoaded v4.1.4
10494 * JavaScript is all like "You images are done yet or what?"
10495 * MIT License
10496 */
10497(function(e,i){"use strict";if(typeof define=="function"&&define.amd){define("imagesloaded/imagesloaded",["ev-emitter/ev-emitter"],function(t){return i(e,t)})}else if(typeof module=="object"&&module.exports){module.exports=i(e,require("ev-emitter"))}else{e.imagesLoaded=i(e,e.EvEmitter)}})(typeof window!=="undefined"?window:this,function t(e,i){var s=e.jQuery;var r=e.console;function o(t,e){for(var i in e){t[i]=e[i]}return t}var n=Array.prototype.slice;function a(t){if(Array.isArray(t)){return t}var e=typeof t=="object"&&typeof t.length=="number";if(e){return n.call(t)}return[t]}function l(t,e,i){if(!(this instanceof l)){return new l(t,e,i)}var n=t;if(typeof t=="string"){n=document.querySelectorAll(t)}if(!n){r.error("Bad element for imagesLoaded "+(n||t));return}this.elements=a(n);this.options=o({},this.options);if(typeof e=="function"){i=e}else{o(this.options,e)}if(i){this.on("always",i)}this.getImages();if(s){this.jqDeferred=new s.Deferred}setTimeout(this.check.bind(this))}l.prototype=Object.create(i.prototype);l.prototype.options={};l.prototype.getImages=function(){this.images=[];this.elements.forEach(this.addElementImages,this)};l.prototype.addElementImages=function(t){if(t.nodeName=="IMG"){this.addImage(t)}if(this.options.background===true){this.addElementBackgroundImages(t)}var e=t.nodeType;if(!e||!h[e]){return}var i=t.querySelectorAll("img");for(var n=0;n<i.length;n++){var s=i[n];this.addImage(s)}if(typeof this.options.background=="string"){var r=t.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var o=r[n];this.addElementBackgroundImages(o)}}};var h={1:true,9:true,11:true};l.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t);if(!e){return}var i=/url\((['"])?(.*?)\1\)/gi;var n=i.exec(e.backgroundImage);while(n!==null){var s=n&&n[2];if(s){this.addBackground(s,t)}n=i.exec(e.backgroundImage)}};l.prototype.addImage=function(t){var e=new c(t);this.images.push(e)};l.prototype.addBackground=function(t,e){var i=new u(t,e);this.images.push(i)};l.prototype.check=function(){var n=this;this.progressedCount=0;this.hasAnyBroken=false;if(!this.images.length){this.complete();return}function e(t,e,i){setTimeout(function(){n.progress(t,e,i)})}this.images.forEach(function(t){t.once("progress",e);t.check()})};l.prototype.progress=function(t,e,i){this.progressedCount++;this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded;this.emitEvent("progress",[this,t,e]);if(this.jqDeferred&&this.jqDeferred.notify){this.jqDeferred.notify(this,t)}if(this.progressedCount==this.images.length){this.complete()}if(this.options.debug&&r){r.log("progress: "+i,t,e)}};l.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done";this.isComplete=true;this.emitEvent(t,[this]);this.emitEvent("always",[this]);if(this.jqDeferred){var e=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[e](this)}};function c(t){this.img=t}c.prototype=Object.create(i.prototype);c.prototype.check=function(){var t=this.getIsImageComplete();
10497if(t){this.confirm(this.img.naturalWidth!==0,"naturalWidth");return}this.proxyImage=new Image;this.proxyImage.addEventListener("load",this);this.proxyImage.addEventListener("error",this);this.img.addEventListener("load",this);this.img.addEventListener("error",this);this.proxyImage.src=this.img.src};c.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth};c.prototype.confirm=function(t,e){this.isLoaded=t;this.emitEvent("progress",[this,this.img,e])};c.prototype.handleEvent=function(t){var e="on"+t.type;if(this[e]){this[e](t)}};c.prototype.onload=function(){this.confirm(true,"onload");this.unbindEvents()};c.prototype.onerror=function(){this.confirm(false,"onerror");this.unbindEvents()};c.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this);this.proxyImage.removeEventListener("error",this);this.img.removeEventListener("load",this);this.img.removeEventListener("error",this)};function u(t,e){this.url=t;this.element=e;this.img=new Image}u.prototype=Object.create(c.prototype);u.prototype.check=function(){this.img.addEventListener("load",this);this.img.addEventListener("error",this);this.img.src=this.url;var t=this.getIsImageComplete();if(t){this.confirm(this.img.naturalWidth!==0,"naturalWidth");this.unbindEvents()}};u.prototype.unbindEvents=function(){this.img.removeEventListener("load",this);this.img.removeEventListener("error",this)};u.prototype.confirm=function(t,e){this.isLoaded=t;this.emitEvent("progress",[this,this.element,e])};l.makeJQueryPlugin=function(t){t=t||e.jQuery;if(!t){return}s=t;s.fn.imagesLoaded=function(t,e){var i=new l(this,t,e);return i.jqDeferred.promise(s(this))}};l.makeJQueryPlugin();return l});
10498/*!
10499 * Flickity imagesLoaded v2.0.0
10500 * enables imagesLoaded option for Flickity
10501 */
10502(function(i,n){if(typeof define=="function"&&define.amd){define(["flickity/js/index","imagesloaded/imagesloaded"],function(t,e){return n(i,t,e)})}else if(typeof module=="object"&&module.exports){module.exports=n(i,require("flickity"),require("imagesloaded"))}else{i.Flickity=n(i,i.Flickity,i.imagesLoaded)}})(window,function t(e,i,s){"use strict";i.createMethods.push("_createImagesLoaded");var n=i.prototype;n._createImagesLoaded=function(){this.on("activate",this.imagesLoaded)};n.imagesLoaded=function(){if(!this.options.imagesLoaded){return}var n=this;function t(t,e){var i=n.getParentCell(e.img);n.cellSizeChange(i&&i.element);if(!n.options.freeScroll){n.positionSliderAtSelected()}}s(this.slider).on("progress",t)};return i});
10503/**
10504 * Flickity fade v1.0.0
10505 * Fade between Flickity slides
10506 */
10507
10508/* jshint browser: true, undef: true, unused: true */
10509
10510( function( window, factory ) {
10511  // universal module definition
10512  /*globals define, module, require */
10513  if ( typeof define == 'function' && define.amd ) {
10514    // AMD
10515    define( [
10516      'flickity/js/index',
10517      'fizzy-ui-utils/utils',
10518    ], factory );
10519  } else if ( typeof module == 'object' && module.exports ) {
10520    // CommonJS
10521    module.exports = factory(
10522      require('flickity'),
10523      require('fizzy-ui-utils')
10524    );
10525  } else {
10526    // browser global
10527    factory(
10528      window.Flickity,
10529      window.fizzyUIUtils
10530    );
10531  }
10532
10533}( this, function factory( Flickity, utils ) {
10534
10535// ---- Slide ---- //
10536
10537var Slide = Flickity.Slide;
10538
10539var slideUpdateTarget = Slide.prototype.updateTarget;
10540Slide.prototype.updateTarget = function() {
10541  slideUpdateTarget.apply( this, arguments );
10542  if ( !this.parent.options.fade ) {
10543    return;
10544  }
10545  // position cells at selected target
10546  var slideTargetX = this.target - this.x;
10547  var firstCellX = this.cells[0].x;
10548  this.cells.forEach( function( cell ) {
10549    var targetX = cell.x - firstCellX - slideTargetX;
10550    cell.renderPosition( targetX );
10551  });
10552};
10553
10554Slide.prototype.setOpacity = function( alpha ) {
10555  this.cells.forEach( function( cell ) {
10556    cell.element.style.opacity = alpha;
10557  });
10558};
10559
10560// ---- Flickity ---- //
10561
10562var proto = Flickity.prototype;
10563
10564Flickity.createMethods.push('_createFade');
10565
10566proto._createFade = function() {
10567  this.fadeIndex = this.selectedIndex;
10568  this.prevSelectedIndex = this.selectedIndex;
10569  this.on( 'select', this.onSelectFade );
10570  this.on( 'dragEnd', this.onDragEndFade );
10571  this.on( 'settle', this.onSettleFade );
10572  this.on( 'activate', this.onActivateFade );
10573  this.on( 'deactivate', this.onDeactivateFade );
10574};
10575
10576var updateSlides = proto.updateSlides;
10577proto.updateSlides = function() {
10578  updateSlides.apply( this, arguments );
10579  if ( !this.options.fade ) {
10580    return;
10581  }
10582  // set initial opacity
10583  this.slides.forEach( function( slide, i ) {
10584    var alpha = i == this.selectedIndex ? 1 : 0;
10585    slide.setOpacity( alpha );
10586  }, this );
10587};
10588
10589/* ---- events ---- */
10590
10591proto.onSelectFade = function() {
10592  // in case of resize, keep fadeIndex within current count
10593  this.fadeIndex = Math.min( this.prevSelectedIndex, this.slides.length - 1 );
10594  this.prevSelectedIndex = this.selectedIndex;
10595};
10596
10597proto.onSettleFade = function() {
10598  delete this.didDragEnd;
10599  if ( !this.options.fade ) {
10600    return;
10601  }
10602  // set full and 0 opacity on selected & faded slides
10603  this.selectedSlide.setOpacity( 1 );
10604  var fadedSlide = this.slides[ this.fadeIndex ];
10605  if ( fadedSlide && this.fadeIndex != this.selectedIndex ) {
10606    this.slides[ this.fadeIndex ].setOpacity( 0 );
10607  }
10608};
10609
10610proto.onDragEndFade = function() {
10611  // set flag
10612  this.didDragEnd = true;
10613};
10614
10615proto.onActivateFade = function() {
10616  if ( this.options.fade ) {
10617    this.element.classList.add('is-fade');
10618  }
10619};
10620
10621proto.onDeactivateFade = function() {
10622  if ( !this.options.fade ) {
10623    return;
10624  }
10625  this.element.classList.remove('is-fade');
10626  // reset opacity
10627  this.slides.forEach( function( slide ) {
10628    slide.setOpacity('');
10629  });
10630};
10631
10632/* ---- position & fading ---- */
10633
10634var positionSlider = proto.positionSlider;
10635proto.positionSlider = function() {
10636  if ( !this.options.fade ) {
10637    positionSlider.apply( this, arguments );
10638    return;
10639  }
10640
10641  this.fadeSlides();
10642  this.dispatchScrollEvent();
10643};
10644
10645var positionSliderAtSelected = proto.positionSliderAtSelected;
10646proto.positionSliderAtSelected = function() {
10647  if ( this.options.fade ) {
10648    // position fade slider at origin
10649    this.setTranslateX( 0 );
10650  }
10651  positionSliderAtSelected.apply( this, arguments );
10652};
10653
10654proto.fadeSlides = function() {
10655  if ( this.slides.length < 2 ) {
10656    return;
10657  }
10658  // get slides to fade-in & fade-out
10659  var indexes = this.getFadeIndexes();
10660  var fadeSlideA = this.slides[ indexes.a ];
10661  var fadeSlideB = this.slides[ indexes.b ];
10662  var distance = this.wrapDifference( fadeSlideA.target, fadeSlideB.target );
10663  var progress = this.wrapDifference( fadeSlideA.target, -this.x );
10664  progress = progress / distance;
10665
10666  fadeSlideA.setOpacity( 1 - progress );
10667  fadeSlideB.setOpacity( progress );
10668
10669  // hide previous slide
10670  var fadeHideIndex = indexes.a;
10671  if ( this.isDragging ) {
10672    fadeHideIndex = progress > 0.5 ? indexes.a : indexes.b;
10673  }
10674  var isNewHideIndex = this.fadeHideIndex != undefined &&
10675    this.fadeHideIndex != fadeHideIndex &&
10676    this.fadeHideIndex != indexes.a &&
10677    this.fadeHideIndex != indexes.b;
10678  if ( isNewHideIndex ) {
10679    // new fadeHideSlide set, hide previous
10680    this.slides[ this.fadeHideIndex ].setOpacity( 0 );
10681  }
10682  this.fadeHideIndex = fadeHideIndex;
10683};
10684
10685proto.getFadeIndexes = function() {
10686  if ( !this.isDragging && !this.didDragEnd ) {
10687    return {
10688      a: this.fadeIndex,
10689      b: this.selectedIndex,
10690    };
10691  }
10692  if ( this.options.wrapAround ) {
10693    return this.getFadeDragWrapIndexes();
10694  } else {
10695    return this.getFadeDragLimitIndexes();
10696  }
10697};
10698
10699proto.getFadeDragWrapIndexes = function() {
10700  var distances = this.slides.map( function( slide, i ) {
10701    return this.getSlideDistance( -this.x, i );
10702  }, this );
10703  var absDistances = distances.map( function( distance ) {
10704    return Math.abs( distance );
10705  });
10706  var minDistance = Math.min.apply( Math, absDistances );
10707  var closestIndex = absDistances.indexOf( minDistance );
10708  var distance = distances[ closestIndex ];
10709  var len = this.slides.length;
10710
10711  var delta = distance >= 0 ? 1 : -1;
10712  return {
10713    a: closestIndex,
10714    b: utils.modulo( closestIndex + delta, len ),
10715  };
10716};
10717
10718proto.getFadeDragLimitIndexes = function() {
10719  // calculate closest previous slide
10720  var dragIndex = 0;
10721  for ( var i=0; i < this.slides.length - 1; i++ ) {
10722    var slide = this.slides[i];
10723    if ( -this.x < slide.target ) {
10724      break;
10725    }
10726    dragIndex = i;
10727  }
10728  return {
10729    a: dragIndex,
10730    b: dragIndex + 1,
10731  };
10732};
10733
10734proto.wrapDifference = function( a, b ) {
10735  var diff = b - a;
10736
10737  if ( !this.options.wrapAround ) {
10738    return diff;
10739  }
10740
10741  var diffPlus = diff + this.slideableWidth;
10742  var diffMinus = diff - this.slideableWidth;
10743  if ( Math.abs( diffPlus ) < Math.abs( diff ) ) {
10744    diff = diffPlus;
10745  }
10746  if ( Math.abs( diffMinus ) < Math.abs( diff ) ) {
10747    diff = diffMinus;
10748  }
10749  return diff;
10750};
10751
10752// ---- wrapAround ---- //
10753
10754var _getWrapShiftCells = proto._getWrapShiftCells;
10755proto._getWrapShiftCells = function() {
10756  if ( !this.options.fade ) {
10757    _getWrapShiftCells.apply( this, arguments );
10758  }
10759};
10760
10761var shiftWrapCells = proto.shiftWrapCells;
10762proto.shiftWrapCells = function() {
10763  if ( !this.options.fade ) {
10764    shiftWrapCells.apply( this, arguments );
10765  }
10766};
10767
10768return Flickity;
10769
10770}));
10771/**
10772 * Character Counter v1.5.1
10773 * ======================
10774 *
10775 * Character Counter is a simple, Twitter style character counter.
10776 *
10777 * https://github.com/dtisgodsson/jquery-character-counter
10778 *
10779 * @author Darren Taylor
10780 * @author Email: [email protected]
10781 * @author Twitter: darrentaytay
10782 * @author Website: http://darrenonthe.net
10783 *
10784 * Block property added by Sergio Cerrutti
10785 * https://github.com/sergiocerrutti/jquery-character-counter
10786 *
10787 */
10788(function($) {
10789
10790    $.fn.characterCounter = function(opts){
10791
10792        var defaults = {
10793            exceeded: false,
10794            counterSelector: false,
10795            limit: 150,
10796            block: false,
10797            renderTotal: false,
10798            counterWrapper: 'span',
10799            counterCssClass: 'counter',
10800            counterFormat: '%1',
10801            counterExceededCssClass: 'exceeded',
10802            increaseCounting: false,
10803            onExceed: function(count) {},
10804            onDeceed: function(count) {},
10805            customFields: {}
10806        };
10807
10808        var options = $.extend(defaults, opts);
10809
10810        return this.each(function() {
10811            var html5len = $(this).attr('maxlength');
10812            if (typeof html5len !== typeof undefined && html5len !== false) {
10813                $.extend(defaults, {
10814                    limit: parseInt($(this).attr('maxlength'))
10815                });
10816            }
10817            if (!options.counterSelector) {
10818                $(this).after(generateCounter());
10819            }
10820            bindEvents(this);
10821            checkCount(this);
10822        });
10823
10824        function customFields(params)
10825        {
10826            var i, html='';
10827
10828            for (i in params)
10829            {
10830                html += ' ' + i + '="' + params[i] + '"';
10831            }
10832
10833            return html;
10834        }
10835
10836        function generateCounter()
10837        {
10838            var classString = options.counterCssClass;
10839
10840            if ( options.customFields['class'] )
10841            {
10842                classString += " " + options.customFields['class'];
10843                delete options.customFields['class'];
10844            }
10845
10846            return '<'+ options.counterWrapper +customFields(options.customFields)+' class="' + classString + '"></'+ options.counterWrapper +'>';
10847        }
10848
10849        function renderText(count)
10850        {
10851            var rendered_count = options.counterFormat.replace(/%1/, count);
10852
10853            if ( options.renderTotal )
10854            {
10855                rendered_count += '/'+ options.limit;
10856            }
10857
10858            return rendered_count;
10859        }
10860
10861        function checkCount(element)
10862        {
10863            var characterCount = $(element).val().length;
10864            var counter = options.counterSelector ? $(options.counterSelector) : $(element).nextAll("." + options.counterCssClass).first();
10865            var remaining = options.limit - characterCount;
10866            var condition = remaining < 0;
10867            var conditionBlock = options.block && condition;
10868
10869            if ( conditionBlock )
10870            {
10871                remaining = 0;
10872                $(element).val($(element).val().substr(0, options.limit));
10873            } else {
10874                if ( options.increaseCounting )
10875                {
10876                    remaining = characterCount;
10877                    condition = remaining > options.limit;
10878                }
10879
10880                if ( condition )
10881                {
10882                    counter.addClass(options.counterExceededCssClass);
10883                    options.exceeded = true;
10884                    options.onExceed(characterCount);
10885                }
10886                else
10887                {
10888                    if ( options.exceeded ) {
10889                        counter.removeClass(options.counterExceededCssClass);
10890                        options.onDeceed(characterCount);
10891                        options.exceeded = false;
10892                    }
10893                }
10894            }
10895
10896            counter.html(renderText(remaining));
10897        }
10898
10899        function bindEvents(element)
10900        {
10901            $(element)
10902                .on("input change", function () {
10903                    checkCount(element);
10904                });
10905        }
10906    };
10907
10908})(jQuery);
10909/*!
10910 * Bootstrap Colorpicker
10911 * http://mjolnic.github.io/bootstrap-colorpicker/
10912 *
10913 * Originally written by (c) 2012 Stefan Petre
10914 * Licensed under the Apache License v2.0
10915 * http://www.apache.org/licenses/LICENSE-2.0.txt
10916 *
10917 * @todo Update DOCS
10918 */
10919
10920(function(factory) {
10921    "use strict";
10922    if (typeof exports === 'object') {
10923      module.exports = factory(window.jQuery);
10924    } else if (typeof define === 'function' && define.amd) {
10925      define(['jquery'], factory);
10926    } else if (window.jQuery && !window.jQuery.fn.colorpicker) {
10927      factory(window.jQuery);
10928    }
10929  }
10930  (function($) {
10931    'use strict';
10932
10933    // Color object
10934    var Color = function(val, customColors) {
10935      this.value = {
10936        h: 0,
10937        s: 0,
10938        b: 0,
10939        a: 1
10940      };
10941      this.origFormat = null; // original string format
10942      if (customColors) {
10943        $.extend(this.colors, customColors);
10944      }
10945      if (val) {
10946        if (val.toLowerCase !== undefined) {
10947          // cast to string
10948          val = val + '';
10949          this.setColor(val);
10950        } else if (val.h !== undefined) {
10951          this.value = val;
10952        }
10953      }
10954    };
10955
10956    Color.prototype = {
10957      constructor: Color,
10958      // 140 predefined colors from the HTML Colors spec
10959      colors: {
10960        "aliceblue": "#f0f8ff",
10961        "antiquewhite": "#faebd7",
10962        "aqua": "#00ffff",
10963        "aquamarine": "#7fffd4",
10964        "azure": "#f0ffff",
10965        "beige": "#f5f5dc",
10966        "bisque": "#ffe4c4",
10967        "black": "#000000",
10968        "blanchedalmond": "#ffebcd",
10969        "blue": "#0000ff",
10970        "blueviolet": "#8a2be2",
10971        "brown": "#a52a2a",
10972        "burlywood": "#deb887",
10973        "cadetblue": "#5f9ea0",
10974        "chartreuse": "#7fff00",
10975        "chocolate": "#d2691e",
10976        "coral": "#ff7f50",
10977        "cornflowerblue": "#6495ed",
10978        "cornsilk": "#fff8dc",
10979        "crimson": "#dc143c",
10980        "cyan": "#00ffff",
10981        "darkblue": "#00008b",
10982        "darkcyan": "#008b8b",
10983        "darkgoldenrod": "#b8860b",
10984        "darkgray": "#a9a9a9",
10985        "darkgreen": "#006400",
10986        "darkkhaki": "#bdb76b",
10987        "darkmagenta": "#8b008b",
10988        "darkolivegreen": "#556b2f",
10989        "darkorange": "#ff8c00",
10990        "darkorchid": "#9932cc",
10991        "darkred": "#8b0000",
10992        "darksalmon": "#e9967a",
10993        "darkseagreen": "#8fbc8f",
10994        "darkslateblue": "#483d8b",
10995        "darkslategray": "#2f4f4f",
10996        "darkturquoise": "#00ced1",
10997        "darkviolet": "#9400d3",
10998        "deeppink": "#ff1493",
10999        "deepskyblue": "#00bfff",
11000        "dimgray": "#696969",
11001        "dodgerblue": "#1e90ff",
11002        "firebrick": "#b22222",
11003        "floralwhite": "#fffaf0",
11004        "forestgreen": "#228b22",
11005        "fuchsia": "#ff00ff",
11006        "gainsboro": "#dcdcdc",
11007        "ghostwhite": "#f8f8ff",
11008        "gold": "#ffd700",
11009        "goldenrod": "#daa520",
11010        "gray": "#808080",
11011        "green": "#008000",
11012        "greenyellow": "#adff2f",
11013        "honeydew": "#f0fff0",
11014        "hotpink": "#ff69b4",
11015        "indianred": "#cd5c5c",
11016        "indigo": "#4b0082",
11017        "ivory": "#fffff0",
11018        "khaki": "#f0e68c",
11019        "lavender": "#e6e6fa",
11020        "lavenderblush": "#fff0f5",
11021        "lawngreen": "#7cfc00",
11022        "lemonchiffon": "#fffacd",
11023        "lightblue": "#add8e6",
11024        "lightcoral": "#f08080",
11025        "lightcyan": "#e0ffff",
11026        "lightgoldenrodyellow": "#fafad2",
11027        "lightgrey": "#d3d3d3",
11028        "lightgreen": "#90ee90",
11029        "lightpink": "#ffb6c1",
11030        "lightsalmon": "#ffa07a",
11031        "lightseagreen": "#20b2aa",
11032        "lightskyblue": "#87cefa",
11033        "lightslategray": "#778899",
11034        "lightsteelblue": "#b0c4de",
11035        "lightyellow": "#ffffe0",
11036        "lime": "#00ff00",
11037        "limegreen": "#32cd32",
11038        "linen": "#faf0e6",
11039        "magenta": "#ff00ff",
11040        "maroon": "#800000",
11041        "mediumaquamarine": "#66cdaa",
11042        "mediumblue": "#0000cd",
11043        "mediumorchid": "#ba55d3",
11044        "mediumpurple": "#9370d8",
11045        "mediumseagreen": "#3cb371",
11046        "mediumslateblue": "#7b68ee",
11047        "mediumspringgreen": "#00fa9a",
11048        "mediumturquoise": "#48d1cc",
11049        "mediumvioletred": "#c71585",
11050        "midnightblue": "#191970",
11051        "mintcream": "#f5fffa",
11052        "mistyrose": "#ffe4e1",
11053        "moccasin": "#ffe4b5",
11054        "navajowhite": "#ffdead",
11055        "navy": "#000080",
11056        "oldlace": "#fdf5e6",
11057        "olive": "#808000",
11058        "olivedrab": "#6b8e23",
11059        "orange": "#ffa500",
11060        "orangered": "#ff4500",
11061        "orchid": "#da70d6",
11062        "palegoldenrod": "#eee8aa",
11063        "palegreen": "#98fb98",
11064        "paleturquoise": "#afeeee",
11065        "palevioletred": "#d87093",
11066        "papayawhip": "#ffefd5",
11067        "peachpuff": "#ffdab9",
11068        "peru": "#cd853f",
11069        "pink": "#ffc0cb",
11070        "plum": "#dda0dd",
11071        "powderblue": "#b0e0e6",
11072        "purple": "#800080",
11073        "red": "#ff0000",
11074        "rosybrown": "#bc8f8f",
11075        "royalblue": "#4169e1",
11076        "saddlebrown": "#8b4513",
11077        "salmon": "#fa8072",
11078        "sandybrown": "#f4a460",
11079        "seagreen": "#2e8b57",
11080        "seashell": "#fff5ee",
11081        "sienna": "#a0522d",
11082        "silver": "#c0c0c0",
11083        "skyblue": "#87ceeb",
11084        "slateblue": "#6a5acd",
11085        "slategray": "#708090",
11086        "snow": "#fffafa",
11087        "springgreen": "#00ff7f",
11088        "steelblue": "#4682b4",
11089        "tan": "#d2b48c",
11090        "teal": "#008080",
11091        "thistle": "#d8bfd8",
11092        "tomato": "#ff6347",
11093        "turquoise": "#40e0d0",
11094        "violet": "#ee82ee",
11095        "wheat": "#f5deb3",
11096        "white": "#ffffff",
11097        "whitesmoke": "#f5f5f5",
11098        "yellow": "#ffff00",
11099        "yellowgreen": "#9acd32",
11100        "transparent": "transparent"
11101      },
11102      _sanitizeNumber: function(val) {
11103        if (typeof val === 'number') {
11104          return val;
11105        }
11106        if (isNaN(val) || (val === null) || (val === '') || (val === undefined)) {
11107          return 1;
11108        }
11109        if (val.toLowerCase !== undefined) {
11110          return parseFloat(val);
11111        }
11112        return 1;
11113      },
11114      isTransparent: function(strVal) {
11115        if (!strVal) {
11116          return false;
11117        }
11118        strVal = strVal.toLowerCase().trim();
11119        return (strVal === 'transparent') || (strVal.match(/#?00000000/)) || (strVal.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/));
11120      },
11121      rgbaIsTransparent: function(rgba) {
11122        return ((rgba.r === 0) && (rgba.g === 0) && (rgba.b === 0) && (rgba.a === 0));
11123      },
11124      //parse a string to HSB
11125      setColor: function(strVal) {
11126        strVal = strVal.toLowerCase().trim();
11127        if (strVal) {
11128          if (this.isTransparent(strVal)) {
11129            this.value = {
11130              h: 0,
11131              s: 0,
11132              b: 0,
11133              a: 0
11134            };
11135          } else {
11136            this.value = this.stringToHSB(strVal) || {
11137              h: 0,
11138              s: 0,
11139              b: 0,
11140              a: 1
11141            }; // if parser fails, defaults to black
11142          }
11143        }
11144      },
11145      stringToHSB: function(strVal) {
11146        strVal = strVal.toLowerCase();
11147        var alias;
11148        if (typeof this.colors[strVal] !== 'undefined') {
11149          strVal = this.colors[strVal];
11150          alias = 'alias';
11151        }
11152        var that = this,
11153          result = false;
11154        $.each(this.stringParsers, function(i, parser) {
11155          var match = parser.re.exec(strVal),
11156            values = match && parser.parse.apply(that, [match]),
11157            format = alias || parser.format || 'rgba';
11158          if (values) {
11159            if (format.match(/hsla?/)) {
11160              result = that.RGBtoHSB.apply(that, that.HSLtoRGB.apply(that, values));
11161            } else {
11162              result = that.RGBtoHSB.apply(that, values);
11163            }
11164            that.origFormat = format;
11165            return false;
11166          }
11167          return true;
11168        });
11169        return result;
11170      },
11171      setHue: function(h) {
11172        this.value.h = 1 - h;
11173      },
11174      setSaturation: function(s) {
11175        this.value.s = s;
11176      },
11177      setBrightness: function(b) {
11178        this.value.b = 1 - b;
11179      },
11180      setAlpha: function(a) {
11181        this.value.a = parseInt((1 - a) * 100, 10) / 100;
11182      },
11183      toRGB: function(h, s, b, a) {
11184        if (!h) {
11185          h = this.value.h;
11186          s = this.value.s;
11187          b = this.value.b;
11188        }
11189        h *= 360;
11190        var R, G, B, X, C;
11191        h = (h % 360) / 60;
11192        C = b * s;
11193        X = C * (1 - Math.abs(h % 2 - 1));
11194        R = G = B = b - C;
11195
11196        h = ~~h;
11197        R += [C, X, 0, 0, X, C][h];
11198        G += [X, C, C, X, 0, 0][h];
11199        B += [0, 0, X, C, C, X][h];
11200        return {
11201          r: Math.round(R * 255),
11202          g: Math.round(G * 255),
11203          b: Math.round(B * 255),
11204          a: a || this.value.a
11205        };
11206      },
11207      toHex: function(h, s, b, a) {
11208        var rgb = this.toRGB(h, s, b, a);
11209        if (this.rgbaIsTransparent(rgb)) {
11210          return 'transparent';
11211        }
11212        return '#' + ((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
11213      },
11214      toHSL: function(h, s, b, a) {
11215        h = h || this.value.h;
11216        s = s || this.value.s;
11217        b = b || this.value.b;
11218        a = a || this.value.a;
11219
11220        var H = h,
11221          L = (2 - s) * b,
11222          S = s * b;
11223        if (L > 0 && L <= 1) {
11224          S /= L;
11225        } else {
11226          S /= 2 - L;
11227        }
11228        L /= 2;
11229        if (S > 1) {
11230          S = 1;
11231        }
11232        return {
11233          h: isNaN(H) ? 0 : H,
11234          s: isNaN(S) ? 0 : S,
11235          l: isNaN(L) ? 0 : L,
11236          a: isNaN(a) ? 0 : a
11237        };
11238      },
11239      toAlias: function(r, g, b, a) {
11240        var rgb = this.toHex(r, g, b, a);
11241        for (var alias in this.colors) {
11242          if (this.colors[alias] === rgb) {
11243            return alias;
11244          }
11245        }
11246        return false;
11247      },
11248      RGBtoHSB: function(r, g, b, a) {
11249        r /= 255;
11250        g /= 255;
11251        b /= 255;
11252
11253        var H, S, V, C;
11254        V = Math.max(r, g, b);
11255        C = V - Math.min(r, g, b);
11256        H = (C === 0 ? null :
11257          V === r ? (g - b) / C :
11258          V === g ? (b - r) / C + 2 :
11259          (r - g) / C + 4
11260        );
11261        H = ((H + 360) % 6) * 60 / 360;
11262        S = C === 0 ? 0 : C / V;
11263        return {
11264          h: this._sanitizeNumber(H),
11265          s: S,
11266          b: V,
11267          a: this._sanitizeNumber(a)
11268        };
11269      },
11270      HueToRGB: function(p, q, h) {
11271        if (h < 0) {
11272          h += 1;
11273        } else if (h > 1) {
11274          h -= 1;
11275        }
11276        if ((h * 6) < 1) {
11277          return p + (q - p) * h * 6;
11278        } else if ((h * 2) < 1) {
11279          return q;
11280        } else if ((h * 3) < 2) {
11281          return p + (q - p) * ((2 / 3) - h) * 6;
11282        } else {
11283          return p;
11284        }
11285      },
11286      HSLtoRGB: function(h, s, l, a) {
11287        if (s < 0) {
11288          s = 0;
11289        }
11290        var q;
11291        if (l <= 0.5) {
11292          q = l * (1 + s);
11293        } else {
11294          q = l + s - (l * s);
11295        }
11296
11297        var p = 2 * l - q;
11298
11299        var tr = h + (1 / 3);
11300        var tg = h;
11301        var tb = h - (1 / 3);
11302
11303        var r = Math.round(this.HueToRGB(p, q, tr) * 255);
11304        var g = Math.round(this.HueToRGB(p, q, tg) * 255);
11305        var b = Math.round(this.HueToRGB(p, q, tb) * 255);
11306        return [r, g, b, this._sanitizeNumber(a)];
11307      },
11308      toString: function(format) {
11309        format = format || 'rgba';
11310        var c = false;
11311        switch (format) {
11312          case 'rgb':
11313            {
11314              c = this.toRGB();
11315              if (this.rgbaIsTransparent(c)) {
11316                return 'transparent';
11317              }
11318              return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')';
11319            }
11320            break;
11321          case 'rgba':
11322            {
11323              c = this.toRGB();
11324              return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')';
11325            }
11326            break;
11327          case 'hsl':
11328            {
11329              c = this.toHSL();
11330              return 'hsl(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%)';
11331            }
11332            break;
11333          case 'hsla':
11334            {
11335              c = this.toHSL();
11336              return 'hsla(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%,' + c.a + ')';
11337            }
11338            break;
11339          case 'hex':
11340            {
11341              return this.toHex();
11342            }
11343            break;
11344          case 'alias':
11345            return this.toAlias() || this.toHex();
11346          default:
11347            {
11348              return c;
11349            }
11350            break;
11351        }
11352      },
11353      // a set of RE's that can match strings and generate color tuples.
11354      // from John Resig color plugin
11355      // https://github.com/jquery/jquery-color/
11356      stringParsers: [{
11357        re: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,
11358        format: 'rgb',
11359        parse: function(execResult) {
11360          return [
11361            execResult[1],
11362            execResult[2],
11363            execResult[3],
11364            1
11365          ];
11366        }
11367      }, {
11368        re: /rgb\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*?\)/,
11369        format: 'rgb',
11370        parse: function(execResult) {
11371          return [
11372            2.55 * execResult[1],
11373            2.55 * execResult[2],
11374            2.55 * execResult[3],
11375            1
11376          ];
11377        }
11378      }, {
11379        re: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
11380        format: 'rgba',
11381        parse: function(execResult) {
11382          return [
11383            execResult[1],
11384            execResult[2],
11385            execResult[3],
11386            execResult[4]
11387          ];
11388        }
11389      }, {
11390        re: /rgba\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
11391        format: 'rgba',
11392        parse: function(execResult) {
11393          return [
11394            2.55 * execResult[1],
11395            2.55 * execResult[2],
11396            2.55 * execResult[3],
11397            execResult[4]
11398          ];
11399        }
11400      }, {
11401        re: /hsl\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*?\)/,
11402        format: 'hsl',
11403        parse: function(execResult) {
11404          return [
11405            execResult[1] / 360,
11406            execResult[2] / 100,
11407            execResult[3] / 100,
11408            execResult[4]
11409          ];
11410        }
11411      }, {
11412        re: /hsla\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
11413        format: 'hsla',
11414        parse: function(execResult) {
11415          return [
11416            execResult[1] / 360,
11417            execResult[2] / 100,
11418            execResult[3] / 100,
11419            execResult[4]
11420          ];
11421        }
11422      }, {
11423        re: /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
11424        format: 'hex',
11425        parse: function(execResult) {
11426          return [
11427            parseInt(execResult[1], 16),
11428            parseInt(execResult[2], 16),
11429            parseInt(execResult[3], 16),
11430            1
11431          ];
11432        }
11433      }, {
11434        re: /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
11435        format: 'hex',
11436        parse: function(execResult) {
11437          return [
11438            parseInt(execResult[1] + execResult[1], 16),
11439            parseInt(execResult[2] + execResult[2], 16),
11440            parseInt(execResult[3] + execResult[3], 16),
11441            1
11442          ];
11443        }
11444      }],
11445      colorNameToHex: function(name) {
11446        if (typeof this.colors[name.toLowerCase()] !== 'undefined') {
11447          return this.colors[name.toLowerCase()];
11448        }
11449        return false;
11450      }
11451    };
11452
11453
11454    var defaults = {
11455      horizontal: false, // horizontal mode layout ?
11456      inline: false, //forces to show the colorpicker as an inline element
11457      color: false, //forces a color
11458      format: false, //forces a format
11459      input: 'input', // children input selector
11460      container: false, // container selector
11461      component: '.add-on, .input-group-addon', // children component selector
11462      sliders: {
11463        saturation: {
11464          maxLeft: 100,
11465          maxTop: 100,
11466          callLeft: 'setSaturation',
11467          callTop: 'setBrightness'
11468        },
11469        hue: {
11470          maxLeft: 0,
11471          maxTop: 100,
11472          callLeft: false,
11473          callTop: 'setHue'
11474        },
11475        alpha: {
11476          maxLeft: 0,
11477          maxTop: 100,
11478          callLeft: false,
11479          callTop: 'setAlpha'
11480        }
11481      },
11482      slidersHorz: {
11483        saturation: {
11484          maxLeft: 100,
11485          maxTop: 100,
11486          callLeft: 'setSaturation',
11487          callTop: 'setBrightness'
11488        },
11489        hue: {
11490          maxLeft: 100,
11491          maxTop: 0,
11492          callLeft: 'setHue',
11493          callTop: false
11494        },
11495        alpha: {
11496          maxLeft: 100,
11497          maxTop: 0,
11498          callLeft: 'setAlpha',
11499          callTop: false
11500        }
11501      },
11502      template: '<div class="colorpicker dropdown-menu">' +
11503        '<div class="colorpicker-saturation"><i><b></b></i></div>' +
11504        '<div class="colorpicker-hue"><i></i></div>' +
11505        '<div class="colorpicker-alpha"><i></i></div>' +
11506        '<div class="colorpicker-color"><div /></div>' +
11507        '<div class="colorpicker-selectors"></div>' +
11508        '</div>',
11509      align: 'right',
11510      customClass: null,
11511      colorSelectors: null
11512    };
11513
11514    var Colorpicker = function(element, options) {
11515      this.element = $(element).addClass('colorpicker-element');
11516      this.options = $.extend(true, {}, defaults, this.element.data(), options);
11517      this.component = this.options.component;
11518      this.component = (this.component !== false) ? this.element.find(this.component) : false;
11519      if (this.component && (this.component.length === 0)) {
11520        this.component = false;
11521      }
11522      this.container = (this.options.container === true) ? this.element : this.options.container;
11523      this.container = (this.container !== false) ? $(this.container) : false;
11524
11525      // Is the element an input? Should we search inside for any input?
11526      this.input = this.element.is('input') ? this.element : (this.options.input ?
11527        this.element.find(this.options.input) : false);
11528      if (this.input && (this.input.length === 0)) {
11529        this.input = false;
11530      }
11531      // Set HSB color
11532      this.color = new Color(this.options.color !== false ? this.options.color : this.getValue(), this.options.colorSelectors);
11533      this.format = this.options.format !== false ? this.options.format : this.color.origFormat;
11534
11535      // Setup picker
11536      this.picker = $(this.options.template);
11537      if (this.options.customClass) {
11538        this.picker.addClass(this.options.customClass);
11539      }
11540      if (this.options.inline) {
11541        this.picker.addClass('colorpicker-inline colorpicker-visible');
11542      } else {
11543        this.picker.addClass('colorpicker-hidden');
11544      }
11545      if (this.options.horizontal) {
11546        this.picker.addClass('colorpicker-horizontal');
11547      }
11548      if (this.format === 'rgba' || this.format === 'hsla' || this.options.format === false) {
11549        this.picker.addClass('colorpicker-with-alpha');
11550      }
11551      if (this.options.align === 'right') {
11552        this.picker.addClass('colorpicker-right');
11553      }
11554      if (this.options.colorSelectors) {
11555        var colorpicker = this;
11556        $.each(this.options.colorSelectors, function(name, color) {
11557          var $btn = $('<i />').css('background-color', color).data('class', name);
11558          $btn.click(function() {
11559            colorpicker.setValue($(this).css('background-color'));
11560          });
11561          colorpicker.picker.find('.colorpicker-selectors').append($btn);
11562        });
11563        this.picker.find('.colorpicker-selectors').show();
11564      }
11565      this.picker.on('mousedown.colorpicker touchstart.colorpicker', $.proxy(this.mousedown, this));
11566      this.picker.appendTo(this.container ? this.container : $('body'));
11567
11568      // Bind events
11569      if (this.input !== false) {
11570        this.input.on({
11571          'keyup.colorpicker': $.proxy(this.keyup, this)
11572        });
11573        this.input.on({
11574          'change.colorpicker': $.proxy(this.change, this)
11575        });
11576        if (this.component === false) {
11577          this.element.on({
11578            'focus.colorpicker': $.proxy(this.show, this)
11579          });
11580        }
11581        if (this.options.inline === false) {
11582          this.element.on({
11583            'focusout.colorpicker': $.proxy(this.hide, this)
11584          });
11585        }
11586      }
11587
11588      if (this.component !== false) {
11589        this.component.on({
11590          'click.colorpicker': $.proxy(this.show, this)
11591        });
11592      }
11593
11594      if ((this.input === false) && (this.component === false)) {
11595        this.element.on({
11596          'click.colorpicker': $.proxy(this.show, this)
11597        });
11598      }
11599
11600      // for HTML5 input[type='color']
11601      if ((this.input !== false) && (this.component !== false) && (this.input.attr('type') === 'color')) {
11602
11603        this.input.on({
11604          'click.colorpicker': $.proxy(this.show, this),
11605          'focus.colorpicker': $.proxy(this.show, this)
11606        });
11607      }
11608      this.update();
11609
11610      $($.proxy(function() {
11611        this.element.trigger('create');
11612      }, this));
11613    };
11614
11615    Colorpicker.Color = Color;
11616
11617    Colorpicker.prototype = {
11618      constructor: Colorpicker,
11619      destroy: function() {
11620        this.picker.remove();
11621        this.element.removeData('colorpicker').off('.colorpicker');
11622        if (this.input !== false) {
11623          this.input.off('.colorpicker');
11624        }
11625        if (this.component !== false) {
11626          this.component.off('.colorpicker');
11627        }
11628        this.element.removeClass('colorpicker-element');
11629        this.element.trigger({
11630          type: 'destroy'
11631        });
11632      },
11633      reposition: function() {
11634        if (this.options.inline !== false || this.options.container) {
11635          return false;
11636        }
11637        var type = this.container && this.container[0] !== document.body ? 'position' : 'offset';
11638        var element = this.component || this.element;
11639        var offset = element[type]();
11640        if (this.options.align === 'right') {
11641          offset.left -= this.picker.outerWidth() - element.outerWidth();
11642        }
11643        this.picker.css({
11644          top: offset.top + element.outerHeight(),
11645          left: offset.left
11646        });
11647      },
11648      show: function(e) {
11649        if (this.isDisabled()) {
11650          return false;
11651        }
11652        this.picker.addClass('colorpicker-visible').removeClass('colorpicker-hidden');
11653        this.reposition();
11654        $(window).on('resize.colorpicker', $.proxy(this.reposition, this));
11655        if (e && (!this.hasInput() || this.input.attr('type') === 'color')) {
11656          if (e.stopPropagation && e.preventDefault) {
11657            e.stopPropagation();
11658            e.preventDefault();
11659          }
11660        }
11661        if (this.options.inline === false) {
11662          $(window.document).on({
11663            'mousedown.colorpicker': $.proxy(this.hide, this)
11664          });
11665        }
11666        this.element.trigger({
11667          type: 'showPicker',
11668          color: this.color
11669        });
11670      },
11671      hide: function() {
11672        this.picker.addClass('colorpicker-hidden').removeClass('colorpicker-visible');
11673        $(window).off('resize.colorpicker', this.reposition);
11674        $(document).off({
11675          'mousedown.colorpicker': this.hide
11676        });
11677        this.update();
11678        this.element.trigger({
11679          type: 'hidePicker',
11680          color: this.color
11681        });
11682      },
11683      updateData: function(val) {
11684        val = val || this.color.toString(this.format);
11685        this.element.data('color', val);
11686        return val;
11687      },
11688      updateInput: function(val) {
11689        val = val || this.color.toString(this.format);
11690        if (this.input !== false) {
11691          if (this.options.colorSelectors) {
11692            var color = new Color(val, this.options.colorSelectors);
11693            var alias = color.toAlias();
11694            if (typeof this.options.colorSelectors[alias] !== 'undefined') {
11695              val = alias;
11696            }
11697          }
11698          this.input.prop('value', val);
11699        }
11700        return val;
11701      },
11702      updatePicker: function(val) {
11703        if (val !== undefined) {
11704          this.color = new Color(val, this.options.colorSelectors);
11705        }
11706        var sl = (this.options.horizontal === false) ? this.options.sliders : this.options.slidersHorz;
11707        var icns = this.picker.find('i');
11708        if (icns.length === 0) {
11709          return;
11710        }
11711        if (this.options.horizontal === false) {
11712          sl = this.options.sliders;
11713          icns.eq(1).css('top', sl.hue.maxTop * (1 - this.color.value.h)).end()
11714            .eq(2).css('top', sl.alpha.maxTop * (1 - this.color.value.a));
11715        } else {
11716          sl = this.options.slidersHorz;
11717          icns.eq(1).css('left', sl.hue.maxLeft * (1 - this.color.value.h)).end()
11718            .eq(2).css('left', sl.alpha.maxLeft * (1 - this.color.value.a));
11719        }
11720        icns.eq(0).css({
11721          'top': sl.saturation.maxTop - this.color.value.b * sl.saturation.maxTop,
11722          'left': this.color.value.s * sl.saturation.maxLeft
11723        });
11724        this.picker.find('.colorpicker-saturation').css('backgroundColor', this.color.toHex(this.color.value.h, 1, 1, 1));
11725        this.picker.find('.colorpicker-alpha').css('backgroundColor', this.color.toHex());
11726        this.picker.find('.colorpicker-color, .colorpicker-color div').css('backgroundColor', this.color.toString(this.format));
11727        return val;
11728      },
11729      updateComponent: function(val) {
11730        val = val || this.color.toString(this.format);
11731        if (this.component !== false) {
11732          var icn = this.component.find('i').eq(0);
11733          if (icn.length > 0) {
11734            icn.css({
11735              'backgroundColor': val
11736            });
11737          } else {
11738            this.component.css({
11739              'backgroundColor': val
11740            });
11741          }
11742        }
11743        return val;
11744      },
11745      update: function(force) {
11746        var val;
11747        if ((this.getValue(false) !== false) || (force === true)) {
11748          // Update input/data only if the current value is not empty
11749          val = this.updateComponent();
11750          this.updateInput(val);
11751          this.updateData(val);
11752          this.updatePicker(); // only update picker if value is not empty
11753        }
11754        return val;
11755
11756      },
11757      setValue: function(val) { // set color manually
11758        this.color = new Color(val, this.options.colorSelectors);
11759        this.update(true);
11760        this.element.trigger({
11761          type: 'changeColor',
11762          color: this.color,
11763          value: val
11764        });
11765      },
11766      getValue: function(defaultValue) {
11767        defaultValue = (defaultValue === undefined) ? '#000000' : defaultValue;
11768        var val;
11769        if (this.hasInput()) {
11770          val = this.input.val();
11771        } else {
11772          val = this.element.data('color');
11773        }
11774        if ((val === undefined) || (val === '') || (val === null)) {
11775          // if not defined or empty, return default
11776          val = defaultValue;
11777        }
11778        return val;
11779      },
11780      hasInput: function() {
11781        return (this.input !== false);
11782      },
11783      isDisabled: function() {
11784        if (this.hasInput()) {
11785          return (this.input.prop('disabled') === true);
11786        }
11787        return false;
11788      },
11789      disable: function() {
11790        if (this.hasInput()) {
11791          this.input.prop('disabled', true);
11792          this.element.trigger({
11793            type: 'disable',
11794            color: this.color,
11795            value: this.getValue()
11796          });
11797          return true;
11798        }
11799        return false;
11800      },
11801      enable: function() {
11802        if (this.hasInput()) {
11803          this.input.prop('disabled', false);
11804          this.element.trigger({
11805            type: 'enable',
11806            color: this.color,
11807            value: this.getValue()
11808          });
11809          return true;
11810        }
11811        return false;
11812      },
11813      currentSlider: null,
11814      mousePointer: {
11815        left: 0,
11816        top: 0
11817      },
11818      mousedown: function(e) {
11819        if (!e.pageX && !e.pageY && e.originalEvent) {
11820          e.pageX = e.originalEvent.touches[0].pageX;
11821          e.pageY = e.originalEvent.touches[0].pageY;
11822        }
11823        e.stopPropagation();
11824        e.preventDefault();
11825
11826        var target = $(e.target);
11827
11828        //detect the slider and set the limits and callbacks
11829        var zone = target.closest('div');
11830        var sl = this.options.horizontal ? this.options.slidersHorz : this.options.sliders;
11831        if (!zone.is('.colorpicker')) {
11832          if (zone.is('.colorpicker-saturation')) {
11833            this.currentSlider = $.extend({}, sl.saturation);
11834          } else if (zone.is('.colorpicker-hue')) {
11835            this.currentSlider = $.extend({}, sl.hue);
11836          } else if (zone.is('.colorpicker-alpha')) {
11837            this.currentSlider = $.extend({}, sl.alpha);
11838          } else {
11839            return false;
11840          }
11841          var offset = zone.offset();
11842          //reference to guide's style
11843          this.currentSlider.guide = zone.find('i')[0].style;
11844          this.currentSlider.left = e.pageX - offset.left;
11845          this.currentSlider.top = e.pageY - offset.top;
11846          this.mousePointer = {
11847            left: e.pageX,
11848            top: e.pageY
11849          };
11850          //trigger mousemove to move the guide to the current position
11851          $(document).on({
11852            'mousemove.colorpicker': $.proxy(this.mousemove, this),
11853            'touchmove.colorpicker': $.proxy(this.mousemove, this),
11854            'mouseup.colorpicker': $.proxy(this.mouseup, this),
11855            'touchend.colorpicker': $.proxy(this.mouseup, this)
11856          }).trigger('mousemove');
11857        }
11858        return false;
11859      },
11860      mousemove: function(e) {
11861        if (!e.pageX && !e.pageY && e.originalEvent) {
11862          e.pageX = e.originalEvent.touches[0].pageX;
11863          e.pageY = e.originalEvent.touches[0].pageY;
11864        }
11865        e.stopPropagation();
11866        e.preventDefault();
11867        var left = Math.max(
11868          0,
11869          Math.min(
11870            this.currentSlider.maxLeft,
11871            this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left)
11872          )
11873        );
11874        var top = Math.max(
11875          0,
11876          Math.min(
11877            this.currentSlider.maxTop,
11878            this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top)
11879          )
11880        );
11881        this.currentSlider.guide.left = left + 'px';
11882        this.currentSlider.guide.top = top + 'px';
11883        if (this.currentSlider.callLeft) {
11884          this.color[this.currentSlider.callLeft].call(this.color, left / this.currentSlider.maxLeft);
11885        }
11886        if (this.currentSlider.callTop) {
11887          this.color[this.currentSlider.callTop].call(this.color, top / this.currentSlider.maxTop);
11888        }
11889        // Change format dynamically
11890        // Only occurs if user choose the dynamic format by
11891        // setting option format to false
11892        if (this.currentSlider.callTop === 'setAlpha' && this.options.format === false) {
11893
11894          // Converting from hex / rgb to rgba
11895          if (this.color.value.a !== 1) {
11896            this.format = 'rgba';
11897            this.color.origFormat = 'rgba';
11898          }
11899
11900          // Converting from rgba to hex
11901          else {
11902            this.format = 'hex';
11903            this.color.origFormat = 'hex';
11904          }
11905        }
11906        this.update(true);
11907
11908        this.element.trigger({
11909          type: 'changeColor',
11910          color: this.color
11911        });
11912        return false;
11913      },
11914      mouseup: function(e) {
11915        e.stopPropagation();
11916        e.preventDefault();
11917        $(document).off({
11918          'mousemove.colorpicker': this.mousemove,
11919          'touchmove.colorpicker': this.mousemove,
11920          'mouseup.colorpicker': this.mouseup,
11921          'touchend.colorpicker': this.mouseup
11922        });
11923        return false;
11924      },
11925      change: function(e) {
11926        this.keyup(e);
11927      },
11928      keyup: function(e) {
11929        if ((e.keyCode === 38)) {
11930          if (this.color.value.a < 1) {
11931            this.color.value.a = Math.round((this.color.value.a + 0.01) * 100) / 100;
11932          }
11933          this.update(true);
11934        } else if ((e.keyCode === 40)) {
11935          if (this.color.value.a > 0) {
11936            this.color.value.a = Math.round((this.color.value.a - 0.01) * 100) / 100;
11937          }
11938          this.update(true);
11939        } else {
11940          this.color = new Color(this.input.val(), this.options.colorSelectors);
11941          // Change format dynamically
11942          // Only occurs if user choose the dynamic format by
11943          // setting option format to false
11944          if (this.color.origFormat && this.options.format === false) {
11945            this.format = this.color.origFormat;
11946          }
11947          if (this.getValue(false) !== false) {
11948            this.updateData();
11949            this.updateComponent();
11950            this.updatePicker();
11951          }
11952        }
11953        this.element.trigger({
11954          type: 'changeColor',
11955          color: this.color,
11956          value: this.input.val()
11957        });
11958      }
11959    };
11960
11961    $.colorpicker = Colorpicker;
11962
11963    $.fn.colorpicker = function(option) {
11964      var pickerArgs = arguments,
11965        rv;
11966
11967      var $returnValue = this.each(function() {
11968        var $this = $(this),
11969          inst = $this.data('colorpicker'),
11970          options = ((typeof option === 'object') ? option : {});
11971        if ((!inst) && (typeof option !== 'string')) {
11972          $this.data('colorpicker', new Colorpicker(this, options));
11973        } else {
11974          if (typeof option === 'string') {
11975            rv = inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
11976          }
11977        }
11978      });
11979      if (option === 'getValue') {
11980        return rv;
11981      }
11982      return $returnValue;
11983    };
11984
11985    $.fn.colorpicker.constructor = Colorpicker;
11986
11987  }));
11988(function (factory) {
11989
11990  if (typeof define === 'function' && define.amd) {
11991    // AMD. Register as an anonymous module.
11992    define(['jquery'], factory);
11993  } else if (typeof exports === 'object') {
11994    // Node/CommonJS
11995    factory(require('jquery'));
11996  } else {
11997    // Browser globals
11998    factory(jQuery);
11999  }
12000
12001}(function ($, undef) {
12002
12003  var dataKey = 'plugin_hideShowPassword',
12004    shorthandArgs = ['show', 'innerToggle'],
12005    SPACE = 32,
12006    ENTER = 13;
12007
12008  var canSetInputAttribute = (function(){
12009    var body = document.body,
12010      input = document.createElement('input'),
12011      result = true;
12012    if (! body) {
12013      body = document.createElement('body');
12014    }
12015    input = body.appendChild(input);
12016    try {
12017      input.setAttribute('type', 'text');
12018    } catch (e) {
12019      result = false;
12020    }
12021    body.removeChild(input);
12022    return result;
12023  }());
12024
12025  var defaults = {
12026    // Visibility of the password text. Can be true, false, 'toggle'
12027    // or 'infer'. If 'toggle', it will be the opposite of whatever
12028    // it currently is. If 'infer', it will be based on the input
12029    // type (false if 'password', otherwise true).
12030    show: 'infer',
12031
12032    // Set to true to create an inner toggle for this input. Can
12033    // also be sent to an event name to delay visibility of toggle
12034    // until that event is triggered on the input element.
12035    innerToggle: false,
12036
12037    // If false, the plugin will be disabled entirely. Set to
12038    // the outcome of a test to insure input attributes can be
12039    // set after input has been inserted into the DOM.
12040    enable: canSetInputAttribute,
12041
12042    // Class to add to input element when the plugin is enabled.
12043    className: 'hideShowPassword-field',
12044
12045    // Event to trigger when the plugin is initialized and enabled.
12046    initEvent: 'hideShowPasswordInit',
12047
12048    // Event to trigger whenever the visibility changes.
12049    changeEvent: 'passwordVisibilityChange',
12050
12051    // Properties to add to the input element.
12052    props: {
12053      autocapitalize: 'off',
12054      autocomplete: 'off',
12055      autocorrect: 'off',
12056      spellcheck: 'false'
12057    },
12058
12059    // Options specific to the inner toggle.
12060    toggle: {
12061      // The element to create.
12062      element: '<button type="button">',
12063      // Class name of element.
12064      className: 'hideShowPassword-toggle',
12065      // Whether or not to support touch-specific enhancements.
12066      // Defaults to the value of Modernizr.touch if available,
12067      // otherwise false.
12068      touchSupport: (typeof Modernizr === 'undefined') ? false : Modernizr.touch,
12069      // Non-touch event to bind to.
12070      attachToEvent: 'click.hideShowPassword',
12071      // Event to bind to when touchSupport is true.
12072      attachToTouchEvent: 'touchstart.hideShowPassword mousedown.hideShowPassword',
12073      // Key event to bind to if attachToKeyCodes is an array
12074      // of at least one keycode.
12075      attachToKeyEvent: 'keyup',
12076      // Key codes to bind the toggle event to for accessibility.
12077      // If false, this feature is disabled entirely.
12078      // If true, the array of key codes will be determined based
12079      // on the value of the element option.
12080      attachToKeyCodes: true,
12081      // Styles to add to the toggle element. Does not include
12082      // positioning styles.
12083      styles: { position: 'absolute' },
12084      // Styles to add only when touchSupport is true.
12085      touchStyles: { pointerEvents: 'none' },
12086      // Where to position the inner toggle relative to the
12087      // input element. Can be 'right', 'left' or 'infer'. If
12088      // 'infer', it will be based on the text-direction of the
12089      // input element.
12090      position: 'infer',
12091      // Where to position the inner toggle on the y-axis
12092      // relative to the input element. Can be 'top', 'bottom'
12093      // or 'middle'.
12094      verticalAlign: 'middle',
12095      // Amount by which to "offset" the toggle from the edge
12096      // of the input element.
12097      offset: 0,
12098      // Attributes to add to the toggle element.
12099      attr: {
12100        role: 'button',
12101        'aria-label': 'Show Password',
12102        tabIndex: 0
12103      }
12104    },
12105
12106    // Options specific to the wrapper element, created
12107    // when the innerToggle is initialized to help with
12108    // positioning of that element.
12109    wrapper: {
12110      // The element to create.
12111      element: '<div>',
12112      // Class name of element.
12113      className: 'hideShowPassword-wrapper',
12114      // If true, the width of the wrapper will be set
12115      // unless it is already the same width as the inner
12116      // element. If false, the width will never be set. Any
12117      // other value will be used as the width.
12118      enforceWidth: true,
12119      // Styles to add to the wrapper element. Does not
12120      // include inherited styles or width if enforceWidth
12121      // is not false.
12122      styles: { position: 'relative' },
12123      // Styles to "inherit" from the input element, allowing
12124      // the wrapper to avoid disrupting page styles.
12125      inheritStyles: [
12126        'display',
12127        'verticalAlign',
12128        'marginTop',
12129        'marginRight',
12130        'marginBottom',
12131        'marginLeft'
12132      ],
12133      // Styles for the input element when wrapped.
12134      innerElementStyles: {
12135        marginTop: 0,
12136        marginRight: 0,
12137        marginBottom: 0,
12138        marginLeft: 0
12139      }
12140    },
12141
12142    // Options specific to the 'shown' or 'hidden'
12143    // states of the input element.
12144    states: {
12145      shown: {
12146        className: 'hideShowPassword-shown',
12147        changeEvent: 'passwordShown',
12148        props: { type: 'text' },
12149        toggle: {
12150          className: 'hideShowPassword-toggle-hide',
12151          content: 'Hide',
12152          attr: { 'aria-pressed': 'true' }
12153        }
12154      },
12155      hidden: {
12156        className: 'hideShowPassword-hidden',
12157        changeEvent: 'passwordHidden',
12158        props: { type: 'password' },
12159        toggle: {
12160          className: 'hideShowPassword-toggle-show',
12161          content: 'Show',
12162          attr: { 'aria-pressed': 'false' }
12163        }
12164      }
12165    }
12166
12167  };
12168
12169  function HideShowPassword (element, options) {
12170    this.element = $(element);
12171    this.wrapperElement = $();
12172    this.toggleElement = $();
12173    this.init(options);
12174  }
12175
12176  HideShowPassword.prototype = {
12177
12178    init: function (options) {
12179      if (this.update(options, defaults)) {
12180        this.element.addClass(this.options.className);
12181        if (this.options.innerToggle) {
12182          this.wrapElement(this.options.wrapper);
12183          this.initToggle(this.options.toggle);
12184          if (typeof this.options.innerToggle === 'string') {
12185            this.toggleElement.hide();
12186            this.element.one(this.options.innerToggle, $.proxy(function(){
12187              this.toggleElement.show();
12188            }, this));
12189          }
12190        }
12191        this.element.trigger(this.options.initEvent, [ this ]);
12192      }
12193    },
12194
12195    update: function (options, base) {
12196      this.options = this.prepareOptions(options, base);
12197      if (this.updateElement()) {
12198        this.element
12199          .trigger(this.options.changeEvent, [ this ])
12200          .trigger(this.state().changeEvent, [ this ]);
12201      }
12202      return this.options.enable;
12203    },
12204
12205    toggle: function (showVal) {
12206      showVal = showVal || 'toggle';
12207      return this.update({ show: showVal });
12208    },
12209
12210    prepareOptions: function (options, base) {
12211      var original = options || {},
12212        keyCodes = [],
12213        testElement;
12214      base = base || this.options;
12215      options = $.extend(true, {}, base, options);
12216      // Ugly conditional to resolve #34 in a backwards-compatible way (for now)
12217      if (original.hasOwnProperty('wrapper') && original.wrapper.hasOwnProperty('inheritStyles')) {
12218        options.wrapper.inheritStyles = original.wrapper.inheritStyles;
12219      }
12220      if (options.enable) {
12221        if (options.show === 'toggle') {
12222          options.show = this.isType('hidden', options.states);
12223        }
12223 else if (options.show === 'infer') {
12224          options.show = this.isType('shown', options.states);
12225        }
12226        if (options.toggle.position === 'infer') {
12227          options.toggle.position = (this.element.css('text-direction') === 'rtl') ? 'left' : 'right';
12228        }
12229        if (! $.isArray(options.toggle.attachToKeyCodes)) {
12230          if (options.toggle.attachToKeyCodes === true) {
12231            testElement = $(options.toggle.element);
12232            switch(testElement.prop('tagName').toLowerCase()) {
12233              case 'button':
12234              case 'input':
12235                break;
12236              case 'a':
12237                if (testElement.filter('[href]').length) {
12238                  keyCodes.push(SPACE);
12239                  break;
12240                }
12241              default:
12242                keyCodes.push(SPACE, ENTER);
12243                break;
12244            }
12245          }
12246          options.toggle.attachToKeyCodes = keyCodes;
12247        }
12248      }
12249      return options;
12250    },
12251
12252    updateElement: function () {
12253      if (! this.options.enable || this.isType()) return false;
12254      this.element
12255        .prop($.extend({}, this.options.props, this.state().props))
12256        .addClass(this.state().className)
12257        .removeClass(this.otherState().className);
12258      this.updateToggle();
12259      return true;
12260    },
12261
12262    isType: function (comparison, states) {
12263      states = states || this.options.states;
12264      comparison = comparison || this.state(undef, undef, states).props.type;
12265      if (states[comparison]) {
12266        comparison = states[comparison].props.type;
12267      }
12268      return this.element.prop('type') === comparison;
12269    },
12270
12271    state: function (key, invert, states) {
12272      states = states || this.options.states;
12273      if (key === undef) {
12274        key = this.options.show;
12275      }
12276      if (typeof key === 'boolean') {
12277        key = key ? 'shown' : 'hidden';
12278      }
12279      if (invert) {
12280        key = (key === 'shown') ? 'hidden' : 'shown';
12281      }
12282      return states[key];
12283    },
12284
12285    otherState: function (key) {
12286      return this.state(key, true);
12287    },
12288
12289    wrapElement: function (options) {
12290      var enforceWidth = options.enforceWidth,
12291        targetWidth;
12292      if (! this.wrapperElement.length) {
12293        targetWidth = this.element.outerWidth();
12294        $.each(options.inheritStyles, $.proxy(function (index, prop) {
12295          options.styles[prop] = this.element.css(prop);
12296        }, this));
12297        this.element.css(options.innerElementStyles).wrap(
12298          $(options.element).addClass(options.className).css(options.styles)
12299        );
12300        this.wrapperElement = this.element.parent();
12301        if (enforceWidth === true) {
12302          enforceWidth = (this.wrapperElement.outerWidth() === targetWidth) ? false : targetWidth;
12303        }
12304        if (enforceWidth !== false) {
12305          this.wrapperElement.css('width', enforceWidth);
12306        }
12307      }
12308      return this.wrapperElement;
12309    },
12310
12311    initToggle: function (options) {
12312      if (! this.toggleElement.length) {
12313        // Create element
12314        this.toggleElement = $(options.element)
12315          .attr(options.attr)
12316          .addClass(options.className)
12317          .css(options.styles)
12318          .appendTo(this.wrapperElement);
12319        // Update content/attributes
12320        this.updateToggle();
12321        // Position
12322        this.positionToggle(options.position, options.verticalAlign, options.offset);
12323        // Events
12324        if (options.touchSupport) {
12325          this.toggleElement.css(options.touchStyles);
12326          this.element.on(options.attachToTouchEvent, $.proxy(this.toggleTouchEvent, this));
12327        } else {
12328          this.toggleElement.on(options.attachToEvent, $.proxy(this.toggleEvent, this));
12329        }
12330        if (options.attachToKeyCodes.length) {
12331          this.toggleElement.on(options.attachToKeyEvent, $.proxy(this.toggleKeyEvent, this));
12332        }
12333      }
12334      return this.toggleElement;
12335    },
12336
12337    positionToggle: function (position, verticalAlign, offset) {
12338      var styles = {};
12339      styles[position] = offset;
12340      switch (verticalAlign) {
12341        case 'top':
12342        case 'bottom':
12343          styles[verticalAlign] = offset;
12344          break;
12345        case 'middle':
12346          styles.top = '50%';
12347          styles.marginTop = this.toggleElement.outerHeight() / -2;
12348          break;
12349      }
12350      return this.toggleElement.css(styles);
12351    },
12352
12353    updateToggle: function (state, otherState) {
12354      var paddingProp,
12355        targetPadding;
12356      if (this.toggleElement.length) {
12357        paddingProp = 'padding-' + this.options.toggle.position;
12358        state = state || this.state().toggle;
12359        otherState = otherState || this.otherState().toggle;
12360        this.toggleElement
12361          .attr(state.attr)
12362          .addClass(state.className)
12363          .removeClass(otherState.className)
12364          .html(state.content);
12365        targetPadding = this.toggleElement.outerWidth() + (this.options.toggle.offset * 2);
12366        if (this.element.css(paddingProp) !== targetPadding) {
12367          this.element.css(paddingProp, targetPadding);
12368        }
12369      }
12370      return this.toggleElement;
12371    },
12372
12373    toggleEvent: function (event) {
12374      event.preventDefault();
12375      this.toggle();
12376    },
12377
12378    toggleKeyEvent: function (event) {
12379      $.each(this.options.toggle.attachToKeyCodes, $.proxy(function(index, keyCode) {
12380        if (event.which === keyCode) {
12381          this.toggleEvent(event);
12382          return false;
12383        }
12384      }, this));
12385    },
12386
12387    toggleTouchEvent: function (event) {
12388      var toggleX = this.toggleElement.offset().left,
12389        eventX,
12390        lesser,
12391        greater;
12392      if (toggleX) {
12393        eventX = event.pageX || event.originalEvent.pageX;
12394        if (this.options.toggle.position === 'left') {
12395          toggleX+= this.toggleElement.outerWidth();
12396          lesser = eventX;
12397          greater = toggleX;
12398        } else {
12399          lesser = toggleX;
12400          greater = eventX;
12401        }
12402        if (greater >= lesser) {
12403          this.toggleEvent(event);
12404        }
12405      }
12406    }
12407
12408  };
12409
12410  $.fn.hideShowPassword = function () {
12411    var options = {};
12412    $.each(arguments, function (index, value) {
12413      var newOptions = {};
12414      if (typeof value === 'object') {
12415        newOptions = value;
12416      } else if (shorthandArgs[index]) {
12417        newOptions[shorthandArgs[index]] = value;
12418      } else {
12419        return false;
12420      }
12421      $.extend(true, options, newOptions);
12422    });
12423    return this.each(function(){
12424      var $this = $(this),
12425        data = $this.data(dataKey);
12426      if (data) {
12427        data.update(options);
12428      } else {
12429        $this.data(dataKey, new HideShowPassword(this, options));
12430      }
12431    });
12432  };
12433
12434  $.each({ 'show':true, 'hide':false, 'toggle':'toggle' }, function (verb, showVal) {
12435    $.fn[verb + 'Password'] = function (innerToggle, options) {
12436      return this.hideShowPassword(showVal, innerToggle, options);
12437    };
12438  });
12439
12440}));
12441/*! Stellar.js v0.6.2 | Copyright 2014, Mark Dalgleish | http://markdalgleish.com/projects/stellar.js | http://markdalgleish.mit-license.org */
12442!function(a,b,c,d){function e(b,c){this.element=b,this.options=a.extend({},g,c),this._defaults=g,this._name=f,this.init()}var f="stellar",g={scrollProperty:"scroll",positionProperty:"position",horizontalScrolling:!0,verticalScrolling:!0,horizontalOffset:0,verticalOffset:0,responsive:!1,parallaxBackgrounds:!0,parallaxElements:!0,hideDistantElements:!0,hideElement:function(a){a.hide()},showElement:function(a){a.show()}},h={scroll:{getLeft:function(a){return a.scrollLeft()},setLeft:function(a,b){a.scrollLeft(b)},getTop:function(a){return a.scrollTop()},setTop:function(a,b){a.scrollTop(b)}},position:{getLeft:function(a){return-1*parseInt(a.css("left"),10)},getTop:function(a){return-1*parseInt(a.css("top"),10)}},margin:{getLeft:function(a){return-1*parseInt(a.css("margin-left"),10)},getTop:function(a){return-1*parseInt(a.css("margin-top"),10)}},transform:{getLeft:function(a){var b=getComputedStyle(a[0])[k];return"none"!==b?-1*parseInt(b.match(/(-?[0-9]+)/g)[4],10):0},getTop:function(a){var b=getComputedStyle(a[0])[k];return"none"!==b?-1*parseInt(b.match(/(-?[0-9]+)/g)[5],10):0}}},i={position:{setLeft:function(a,b){a.css("left",b)},setTop:function(a,b){a.css("top",b)}},transform:{setPosition:function(a,b,c,d,e){a[0].style[k]="translate3d("+(b-c)+"px, "+(d-e)+"px, 0)"}}},j=function(){var b,c=/^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/,d=a("script")[0].style,e="";for(b in d)if(c.test(b)){e=b.match(c)[0];break}return"WebkitOpacity"in d&&(e="Webkit"),"KhtmlOpacity"in d&&(e="Khtml"),function(a){return e+(e.length>0?a.charAt(0).toUpperCase()+a.slice(1):a)}}(),k=j("transform"),l=a("<div />",{style:"background:#fff"}).css("background-position-x")!==d,m=l?function(a,b,c){a.css({"background-position-x":b,"background-position-y":c})}:function(a,b,c){a.css("background-position",b+" "+c)},n=l?function(a){return[a.css("background-position-x"),a.css("background-position-y")]}:function(a){return a.css("background-position").split(" ")},o=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame||b.oRequestAnimationFrame||b.msRequestAnimationFrame||function(a){setTimeout(a,1e3/60)};e.prototype={init:function(){this.options.name=f+"_"+Math.floor(1e9*Math.random()),this._defineElements(),this._defineGetters(),this._defineSetters(),this._handleWindowLoadAndResize(),this._detectViewport(),this.refresh({firstLoad:!0}),"scroll"===this.options.scrollProperty?this._handleScrollEvent():this._startAnimationLoop()},_defineElements:function(){this.element===c.body&&(this.element=b),this.$scrollElement=a(this.element),this.$element=this.element===b?a("body"):this.$scrollElement,this.$viewportElement=this.options.viewportElement!==d?a(this.options.viewportElement):this.$scrollElement[0]===b||"scroll"===this.options.scrollProperty?this.$scrollElement:this.$scrollElement.parent()},_defineGetters:function(){var a=this,b=h[a.options.scrollProperty];this._getScrollLeft=function(){return b.getLeft(a.$scrollElement)},this._getScrollTop=function(){return b.getTop(a.$scrollElement)}},_defineSetters:function(){var b=this,c=h[b.options.scrollProperty],d=i[b.options.positionProperty],e=c.setLeft,f=c.setTop;this._setScrollLeft="function"==typeof e?function(a){e(b.$scrollElement,a)}:a.noop,this._setScrollTop="function"==typeof f?function(a){f(b.$scrollElement,a)}:a.noop,this._setPosition=d.setPosition||function(a,c,e,f,g){b.options.horizontalScrolling&&d.setLeft(a,c,e),b.options.verticalScrolling&&d.setTop(a,f,g)}}
12442,_handleWindowLoadAndResize:function(){var c=this,d=a(b);c.options.responsive&&d.bind("load."+this.name,function(){c.refresh()}),d.bind("resize."+this.name,function(){c._detectViewport(),c.options.responsive&&c.refresh()})},refresh:function(c){var d=this,e=d._getScrollLeft(),f=d._getScrollTop();c&&c.firstLoad||this._reset(),this._setScrollLeft(0),this._setScrollTop(0),this._setOffsets(),this._findParticles(),this._findBackgrounds(),c&&c.firstLoad&&/WebKit/.test(navigator.userAgent)&&a(b).load(function(){var a=d._getScrollLeft(),b=d._getScrollTop();d._setScrollLeft(a+1),d._setScrollTop(b+1),d._setScrollLeft(a),d._setScrollTop(b)}),this._setScrollLeft(e),this._setScrollTop(f)},_detectViewport:function(){var a=this.$viewportElement.offset(),b=null!==a&&a!==d;this.viewportWidth=this.$viewportElement.width(),this.viewportHeight=this.$viewportElement.height(),this.viewportOffsetTop=b?a.top:0,this.viewportOffsetLeft=b?a.left:0},_findParticles:function(){{var b=this;this._getScrollLeft(),this._getScrollTop()}if(this.particles!==d)for(var c=this.particles.length-1;c>=0;c--)this.particles[c].$element.data("stellar-elementIsActive",d);this.particles=[],this.options.parallaxElements&&this.$element.find("[data-stellar-ratio]").each(function(){var c,e,f,g,h,i,j,k,l,m=a(this),n=0,o=0,p=0,q=0;if(m.data("stellar-elementIsActive")){if(m.data("stellar-elementIsActive")!==this)return}else m.data("stellar-elementIsActive",this);b.options.showElement(m),m.data("stellar-startingLeft")?(m.css("left",m.data("stellar-startingLeft")),m.css("top",m.data("stellar-startingTop"))):(m.data("stellar-startingLeft",m.css("left")),m.data("stellar-startingTop",m.css("top"))),f=m.position().left,g=m.position().top,h="auto"===m.css("margin-left")?0:parseInt(m.css("margin-left"),10),i="auto"===m.css("margin-top")?0:parseInt(m.css("margin-top"),10),k=m.offset().left-h,l=m.offset().top-i,m.parents().each(function(){var b=a(this);return b.data("stellar-offset-parent")===!0?(n=p,o=q,j=b,!1):(p+=b.position().left,void(q+=b.position().top))}),c=m.data("stellar-horizontal-offset")!==d?m.data("stellar-horizontal-offset"):j!==d&&j.data("stellar-horizontal-offset")!==d?j.data("stellar-horizontal-offset"):b.horizontalOffset,e=m.data("stellar-vertical-offset")!==d?m.data("stellar-vertical-offset"):j!==d&&j.data("stellar-vertical-offset")!==d?j.data("stellar-vertical-offset"):b.verticalOffset,b.particles.push({$element:m,$offsetParent:j,isFixed:"fixed"===m.css("position"),horizontalOffset:c,verticalOffset:e,startingPositionLeft:f,startingPositionTop:g,startingOffsetLeft:k,startingOffsetTop:l,parentOffsetLeft:n,parentOffsetTop:o,stellarRatio:m.data("stellar-ratio")!==d?m.data("stellar-ratio"):1,width:m.outerWidth(!0),height:m.outerHeight(!0),isHidden:!1})})},_findBackgrounds:function(){var b,c=this,e=this._getScrollLeft(),f=this._getScrollTop();this.backgrounds=[],this.options.parallaxBackgrounds&&(b=this.$element.find("[data-stellar-background-ratio]"),this.$element.data("stellar-background-ratio")&&(b=b.add(this.$element)),b.each(function(){var b,g,h,i,j,k,l,o=a(this),p=n(o),q=0,r=0,s=0,t=0;if(o.data("stellar-backgroundIsActive")){if(o.data("stellar-backgroundIsActive")!==this)return}else o.data("stellar-backgroundIsActive",this);o.data("stellar-backgroundStartingLeft")?m(o,o.data("stellar-backgroundStartingLeft"),o.data("stellar-backgroundStartingTop")):(o.data("stellar-backgroundStartingLeft",p[0]),o.data("stellar-backgroundStartingTop",p[1])),h="auto"===o.css("margin-left")?0:parseInt(o.css("margin-left"),10),i="auto"===o.css("margin-top")?0:parseInt(o.css("margin-top"),10),j=o.offset().left-h-e,k=o.offset().top-i-f,o.parents().each(function(){var b=a(this);return b.data("stellar-offset-parent")===!0?(q=s,r=t,l=b,!1):(s+=b.position().left,void(t+=b.position().top))}),b=o.data("stellar-horizontal-offset")!==d?o.data("stellar-horizontal-offset"):l!==d&&l.data("stellar-horizontal-offset")!==d?l.data("stellar-horizontal-offset"):c.horizontalOffset,g=o.data("stellar-vertical-offset")!==d?o.data("stellar-vertical-offset"):l!==d&&l.data("stellar-vertical-offset")!==d?l.data("stellar-vertical-offset"):c.verticalOffset,c.backgrounds.push({$element:o,$offsetParent:l,isFixed:"fixed"===o.css("background-attachment"),horizontalOffset:b,verticalOffset:g,startingValueLeft:p[0],startingValueTop:p[1],startingBackgroun
12442dPositionLeft:isNaN(parseInt(p[0],10))?0:parseInt(p[0],10),startingBackgroundPositionTop:isNaN(parseInt(p[1],10))?0:parseInt(p[1],10),startingPositionLeft:o.position().left,startingPositionTop:o.position().top,startingOffsetLeft:j,startingOffsetTop:k,parentOffsetLeft:q,parentOffsetTop:r,stellarRatio:o.data("stellar-background-ratio")===d?1:o.data("stellar-background-ratio")})}))},_reset:function(){var a,b,c,d,e;for(e=this.particles.length-1;e>=0;e--)a=this.particles[e],b=a.$element.data("stellar-startingLeft"),c=a.$element.data("stellar-startingTop"),this._setPosition(a.$element,b,b,c,c),this.options.showElement(a.$element),a.$element.data("stellar-startingLeft",null).data("stellar-elementIsActive",null).data("stellar-backgroundIsActive",null);for(e=this.backgrounds.length-1;e>=0;e--)d=this.backgrounds[e],d.$element.data("stellar-backgroundStartingLeft",null).data("stellar-backgroundStartingTop",null),m(d.$element,d.startingValueLeft,d.startingValueTop)},destroy:function(){this._reset(),this.$scrollElement.unbind("resize."+this.name).unbind("scroll."+this.name),this._animationLoop=a.noop,a(b).unbind("load."+this.name).unbind("resize."+this.name)},_setOffsets:function(){var c=this,d=a(b);d.unbind("resize.horizontal-"+this.name).unbind("resize.vertical-"+this.name),"function"==typeof this.options.horizontalOffset?(this.horizontalOffset=this.options.horizontalOffset(),d.bind("resize.horizontal-"+this.name,function(){c.horizontalOffset=c.options.horizontalOffset()})):this.horizontalOffset=this.options.horizontalOffset,"function"==typeof this.options.verticalOffset?(this.verticalOffset=this.options.verticalOffset(),d.bind("resize.vertical-"+this.name,function(){c.verticalOffset=c.options.verticalOffset()})):this.verticalOffset=this.options.verticalOffset},_repositionElements:function(){var a,b,c,d,e,f,g,h,i,j,k=this._getScrollLeft(),l=this._getScrollTop(),n=!0,o=!0;if(this.currentScrollLeft!==k||this.currentScrollTop!==l||this.currentWidth!==this.viewportWidth||this.currentHeight!==this.viewportHeight){for(this.currentScrollLeft=k,this.currentScrollTop=l,this.currentWidth=this.viewportWidth,this.currentHeight=this.viewportHeight,j=this.particles.length-1;j>=0;j--)a=this.particles[j],b=a.isFixed?1:0,this.options.horizontalScrolling?(f=(k+a.horizontalOffset+this.viewportOffsetLeft+a.startingPositionLeft-a.startingOffsetLeft+a.parentOffsetLeft)*-(a.stellarRatio+b-1)+a.startingPositionLeft,h=f-a.startingPositionLeft+a.startingOffsetLeft):(f=a.startingPositionLeft,h=a.startingOffsetLeft),this.options.verticalScrolling?(g=(l+a.verticalOffset+this.viewportOffsetTop+a.startingPositionTop-a.startingOffsetTop+a.parentOffsetTop)*-(a.stellarRatio+b-1)+a.startingPositionTop,i=g-a.startingPositionTop+a.startingOffsetTop):(g=a.startingPositionTop,i=a.startingOffsetTop),this.options.hideDistantElements&&(o=!this.options.horizontalScrolling||h+a.width>(a.isFixed?0:k)&&h<(a.isFixed?0:k)+this.viewportWidth+this.viewportOffsetLeft,n=!this.options.verticalScrolling||i+a.height>(a.isFixed?0:l)&&i<(a.isFixed?0:l)+this.viewportHeight+this.viewportOffsetTop),o&&n?(a.isHidden&&(this.options.showElement(a.$element),a.isHidden=!1),this._setPosition(a.$element,f,a.startingPositionLeft,g,a.startingPositionTop)):a.isHidden||(this.options.hideElement(a.$element),a.isHidden=!0);for(j=this.backgrounds.length-1;j>=0;j--)c=this.backgrounds[j],b=c.isFixed?0:1,d=this.options.horizontalScrolling?(k+c.horizontalOffset-this.viewportOffsetLeft-c.startingOffsetLeft+c.parentOffsetLeft-c.startingBackgroun
12442dPositionLeft)*(b-c.stellarRatio)+"px":c.startingValueLeft,e=this.options.verticalScrolling?(l+c.verticalOffset-this.viewportOffsetTop-c.startingOffsetTop+c.parentOffsetTop-c.startingBackgroundPositionTop)*(b-c.stellarRatio)+"px":c.startingValueTop,m(c.$element,d,e)}},_handleScrollEvent:function(){var a=this,b=!1,c=function(){a._repositionElements(),b=!1},d=function(){b||(o(c),b=!0)};this.$scrollElement.bind("scroll."+this.name,d),d()},_startAnimationLoop:function(){var a=this;this._animationLoop=function(){o(a._animationLoop),a._repositionElements()},this._animationLoop()}},a.fn[f]=function(b){var c=arguments;return b===d||"object"==typeof b?this.each(function(){a.data(this,"plugin_"+f)||a.data(this,"plugin_"+f,new e(this,b))}):"string"==typeof b&&"_"!==b[0]&&"init"!==b?this.each(function(){var d=a.data(this,"plugin_"+f);d instanceof e&&"function"==typeof d[b]&&d[b].apply(d,Array.prototype.slice.call(c,1)),"destroy"===b&&a.data(this,"plugin_"+f,null)}):void 0},a[f]=function(){var c=a(b);return c.stellar.apply(c,Array.prototype.slice.call(arguments,0))},a[f].scrollProperty=h,a[f].positionProperty=i,b.Stellar=e}(jQuery,this,document);
12443/*!
12444 * clipboard.js v1.6.1
12445 * https://zenorocha.github.io/clipboard.js
12446 *
12447 * Licensed MIT © Zeno Rocha
12448 */
12449!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Clipboard=e()}}(function(){var e,t,n;return function e(t,n,o){function i(a,c){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var s=n[a]={exports:{}};t[a][0].call(s.exports,function(e){var n=t[a][1][e];return i(n?n:e)},s,s.exports,e,t,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a<o.length;a++)i(o[a]);return i}({1:[function(e,t,n){function o(e,t){for(;e&&e.nodeType!==i;){if(e.matches(t))return e;e=e.parentNode}}var i=9;if("undefined"!=typeof Element&&!Element.prototype.matches){var r=Element.prototype;r.matches=r.matchesSelector||r.mozMatchesSelector||r.msMatchesSelector||r.oMatchesSelector||r.webkitMatchesSelector}t.exports=o},{}],2:[function(e,t,n){function o(e,t,n,o,r){var a=i.apply(this,arguments);return e.addEventListener(n,a,r),{destroy:function(){e.removeEventListener(n,a,r)}}}function i(e,t,n,o){return function(n){n.delegateTarget=r(n.target,t),n.delegateTarget&&o.call(e,n)}}var r=e("./closest");t.exports=o},{"./closest":1}],3:[function(e,t,n){n.node=function(e){return void 0!==e&&e instanceof HTMLElement&&1===e.nodeType},n.nodeList=function(e){var t=Object.prototype.toString.call(e);return void 0!==e&&("[object NodeList]"===t||"[object HTMLCollection]"===t)&&"length"in e&&(0===e.length||n.node(e[0]))},n.string=function(e){return"string"==typeof e||e instanceof String},n.fn=function(e){var t=Object.prototype.toString.call(e);return"[object Function]"===t}},{}],4:[function(e,t,n){function o(e,t,n){if(!e&&!t&&!n)throw new Error("Missing required arguments");if(!c.string(t))throw new TypeError("Second argument must be a String");if(!c.fn(n))throw new TypeError("Third argument must be a Function");if(c.node(e))return i(e,t,n);if(c.nodeList(e))return r(e,t,n);if(c.string(e))return a(e,t,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function i(e,t,n){return e.addEventListener(t,n),{destroy:function(){e.removeEventListener(t,n)}}}function r(e,t,n){return Array.prototype.forEach.call(e,function(e){e.addEventListener(t,n)}),{destroy:function(){Array.prototype.forEach.call(e,function(e){e.removeEventListener(t,n)})}}}function a(e,t,n){return l(document.body,e,t,n)}var c=e("./is"),l=e("delegate");t.exports=o},{"./is":3,delegate:2}],5:[function(e,t,n){function o(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var n=e.hasAttribute("readonly");n||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),n||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var o=window.getSelection(),i=document.createRange();i.selectNodeContents(e),o.removeAllRanges(),o.addRange(i),t=o.toString()}return t}t.exports=o},{}],6:[function(e,t,n){function o(){}o.prototype={on:function(e,t,n){var o=this.e||(this.e={});return(o[e]||(o[e]=[])).push({fn:t,ctx:n}),this},once:function(e,t,n){function o(){i.off(e,o),t.apply(n,arguments)}var i=this;return o._=t,this.on(e,o,n)}
12449,emit:function(e){var t=[].slice.call(arguments,1),n=((this.e||(this.e={}))[e]||[]).slice(),o=0,i=n.length;for(o;o<i;o++)n[o].fn.apply(n[o].ctx,t);return this},off:function(e,t){var n=this.e||(this.e={}),o=n[e],i=[];if(o&&t)for(var r=0,a=o.length;r<a;r++)o[r].fn!==t&&o[r].fn._!==t&&i.push(o[r]);return i.length?n[e]=i:delete n[e],this}},t.exports=o},{}],7:[function(t,n,o){!function(i,r){if("function"==typeof e&&e.amd)e(["module","select"],r);else if("undefined"!=typeof o)r(n,t("select"));else{var a={exports:{}};r(a,i.select),i.clipboardAction=a.exports}}(this,function(e,t){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=n(t),r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),c=function(){function e(t){o(this,e),this.resolveOptions(t),this.initSelection()}return a(e,[{key:"resolveOptions",value:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function e(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function e(){var t=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function e(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function e(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function e(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function e(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function e(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function e(){this.removeFake()}},{key:"action",set:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function e(){return this._action}},{key:"target",set:function e(t){if(void 0!==t){if(!t||"object"!==("undefined"==typeof t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function e(){return this._target}}]),e}();e.exports=c})},{select:5}],8:[function(t,n,o){!function(i,r){if("function"==typeof e&&e.amd)e(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof o)r(n,t("./clipboard-action"),t("tiny-emitter"),t("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(e,t,n,o){"use strict";
12449function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}var u=i(t),s=i(n),f=i(o),d=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),h=function(e){function t(e,n){r(this,t);var o=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return o.resolveOptions(n),o.listenClick(e),o}return c(t,e),d(t,[{key:"resolveOptions",value:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText}},{key:"listenClick",value:function e(t){var n=this;this.listener=(0,f.default)(t,"click",function(e){return n.onClick(e)})}},{key:"onClick",value:function e(t){var n=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new u.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})}},{key:"defaultAction",value:function e(t){return l("action",t)}},{key:"defaultTarget",value:function e(t){var n=l("target",t);if(n)return document.querySelector(n)}},{key:"defaultText",value:function e(t){return l("text",t)}},{key:"destroy",value:function e(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof t?[t]:t,o=!!document.queryCommandSupported;return n.forEach(function(e){o=o&&!!document.queryCommandSupported(e)}),o}}]),t}(s.default);e.exports=h})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)});
12450
12451/*
12452 *
12453 * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
12454 *
12455 * Copyright (c) 2012, Matias Meno
12456 *
12457 * Permission is hereby granted, free of charge, to any person obtaining a copy
12458 * of this software and associated documentation files (the "Software"), to deal
12459 * in the Software without restriction, including without limitation the rights
12460 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12461 * copies of the Software, and to permit persons to whom the Software is
12462 * furnished to do so, subject to the following conditions:
12463 *
12464 * The above copyright notice and this permission notice shall be included in
12465 * all copies or substantial portions of the Software.
12466 *
12467 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12468 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12469 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12470 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
12471 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12472 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
12473 * THE SOFTWARE.
12474 *
12475 */
12476
12477(function() {
12478  var Dropzone, Emitter, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without,
12479    __slice = [].slice,
12480    __hasProp = {}.hasOwnProperty,
12481    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
12482
12483  noop = function() {};
12484
12485  Emitter = (function() {
12486    function Emitter() {}
12487
12488    Emitter.prototype.addEventListener = Emitter.prototype.on;
12489
12490    Emitter.prototype.on = function(event, fn) {
12491      this._callbacks = this._callbacks || {};
12492      if (!this._callbacks[event]) {
12493        this._callbacks[event] = [];
12494      }
12495      this._callbacks[event].push(fn);
12496      return this;
12497    };
12498
12499    Emitter.prototype.emit = function() {
12500      var args, callback, callbacks, event, _i, _len;
12501      event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
12502      this._callbacks = this._callbacks || {};
12503      callbacks = this._callbacks[event];
12504      if (callbacks) {
12505        for (_i = 0, _len = callbacks.length; _i < _len; _i++) {
12506          callback = callbacks[_i];
12507          callback.apply(this, args);
12508        }
12509      }
12510      return this;
12511    };
12512
12513    Emitter.prototype.removeListener = Emitter.prototype.off;
12514
12515    Emitter.prototype.removeAllListeners = Emitter.prototype.off;
12516
12517    Emitter.prototype.removeEventListener = Emitter.prototype.off;
12518
12519    Emitter.prototype.off = function(event, fn) {
12520      var callback, callbacks, i, _i, _len;
12521      if (!this._callbacks || arguments.length === 0) {
12522        this._callbacks = {};
12523        return this;
12524      }
12525      callbacks = this._callbacks[event];
12526      if (!callbacks) {
12527        return this;
12528      }
12529      if (arguments.length === 1) {
12530        delete this._callbacks[event];
12531        return this;
12532      }
12533      for (i = _i = 0, _len = callbacks.length; _i < _len; i = ++_i) {
12534        callback = callbacks[i];
12535        if (callback === fn) {
12536          callbacks.splice(i, 1);
12537          break;
12538        }
12539      }
12540      return this;
12541    };
12542
12543    return Emitter;
12544
12545  })();
12546
12547  Dropzone = (function(_super) {
12548    var extend, resolveOption;
12549
12550    __extends(Dropzone, _super);
12551
12552    Dropzone.prototype.Emitter = Emitter;
12553
12554
12555    /*
12556    This is a list of all available events you can register on a dropzone object.
12557    
12558    You can register an event handler like this:
12559    
12560        dropzone.on("dragEnter", function() { });
12561     */
12562
12563    Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
12564
12565    Dropzone.prototype.defaultOptions = {
12566      url: null,
12567      method: "post",
12568      withCredentials: false,
12569      parallelUploads: 2,
12570      uploadMultiple: false,
12571      maxFilesize: 256,
12572      paramName: "file",
12573      createImageThumbnails: true,
12574      maxThumbnailFilesize: 10,
12575      thumbnailWidth: 120,
12576      thumbnailHeight: 120,
12577      filesizeBase: 1000,
12578      maxFiles: null,
12579      params: {},
12580      clickable: true,
12581      ignoreHiddenFiles: true,
12582      acceptedFiles: null,
12583      acceptedMimeTypes: null,
12584      autoProcessQueue: true,
12585      autoQueue: true,
12586      addRemoveLinks: false,
12587      previewsContainer: null,
12588      hiddenInputContainer: "body",
12589      capture: null,
12590      renameFilename: null,
12591      dictDefaultMessage: "Drop files here to upload",
12592      dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
12593      dictFallbackText: "Please use the fallback form below to upload your files like in the olde
12593n days.",
12594      dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
12595      dictInvalidFileType: "You can't upload files of this type.",
12596      dictResponseError: "Server responded with {{statusCode}} code.",
12597      dictCancelUpload: "Cancel upload",
12598      dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
12599      dictRemoveFile: "Remove file",
12600      dictRemoveFileConfirmation: null,
12601      dictMaxFilesExceeded: "You can not upload any more files.",
12602      accept: function(file, done) {
12603        return done();
12604      },
12605      init: function() {
12606        return noop;
12607      },
12608      forceFallback: false,
12609      fallback: function() {
12610        var child, messageElement, span, _i, _len, _ref;
12611        this.element.className = "" + this.element.className + " dz-browser-not-supported";
12612        _ref = this.element.getElementsByTagName("div");
12613        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12614          child = _ref[_i];
12615          if (/(^| )dz-message($| )/.test(child.className)) {
12616            messageElement = child;
12617            child.className = "dz-message";
12618            continue;
12619          }
12620        }
12621        if (!messageElement) {
12622          messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
12623          this.element.appendChild(messageElement);
12624        }
12625        span = messageElement.getElementsByTagName("span")[0];
12626        if (span) {
12627          if (span.textContent != null) {
12628            span.textContent = this.options.dictFallbackMessage;
12629          } else if (span.innerText != null) {
12630            span.innerText = this.options.dictFallbackMessage;
12631          }
12632        }
12633        return this.element.appendChild(this.getFallbackForm());
12634      },
12635      resize: function(file) {
12636        var info, srcRatio, trgRatio;
12637        info = {
12638          srcX: 0,
12639          srcY: 0,
12640          srcWidth: file.width,
12641          srcHeight: file.height
12642        };
12643        srcRatio = file.width / file.height;
12644        info.optWidth = this.options.thumbnailWidth;
12645        info.optHeight = this.options.thumbnailHeight;
12646        if ((info.optWidth == null) && (info.optHeight == null)) {
12647          info.optWidth = info.srcWidth;
12648          info.optHeight = info.srcHeight;
12649        } else if (info.optWidth == null) {
12650          info.optWidth = srcRatio * info.optHeight;
12651        } else if (info.optHeight == null) {
12652          info.optHeight = (1 / srcRatio) * info.optWidth;
12653        }
12654        trgRatio = info.optWidth / info.optHeight;
12655        if (file.height < info.optHeight || file.width < info.optWidth) {
12656          info.trgHeight = info.srcHeight;
12657          info.trgWidth = info.srcWidth;
12658        } else {
12659          if (srcRatio > trgRatio) {
12660            info.srcHeight = file.height;
12661            info.srcWidth = info.srcHeight * trgRatio;
12662          } else {
12663            info.srcWidth = file.width;
12664            info.srcHeight = info.srcWidth / trgRatio;
12665          }
12666        }
12667        info.srcX = (file.width - info.srcWidth) / 2;
12668        info.srcY = (file.height - info.srcHeight) / 2;
12669        return info;
12670      },
12671
12672      /*
12673      Those functions register themselves to the events on init and handle all
12674      the user interface specific stuff. Overwriting them won't break the upload
12675      but can break the way it's displayed.
12676      You can overwrite them if you don't like the default behavior. If you just
12677      want to add an additional event handler, register it on the dropzone object
12678      and don't overwrite those options.
12679       */
12680      drop: function(e) {
12681        return this.element.classList.remove("dz-drag-hover");
12682      },
12683      dragstart: noop,
12684      dragend: function(e) {
12685        return this.element.classList.remove("dz-drag-hover");
12686      },
12687      dragenter: function(e) {
12688        return this.element.classList.add("dz-drag-hover");
12689      },
12690      dragover: function(e) {
12691        return this.element.classList.add("dz-drag-hover");
12692      },
12693      dragleave: function(e) {
12694        return this.element.classList.remove("dz-drag-hover");
12695      },
12696      paste: noop,
12697      reset: function() {
12698        return this.element.classList.remove("dz-started");
12699      },
12700      addedfile: function(file) {
12701        var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
12702        if (this.element === this.previewsContainer) {
12703          this.element.classList.add("dz-started");
12704        }
12705        if (this.previewsContainer) {
12706          file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
12707          file.previewTemplate = file.previewElement;
12708          this.previewsContainer.appendChild(file.previewElement);
12709          _ref = file.previewElement.querySelectorAll("[data-dz-name]");
12710          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12711            node = _ref[_i];
12712            node.textContent = this._renameFilename(file.name);
12713          }
12714          _ref1 = file.previewElement.querySelectorAll("[data-dz-size]");
12715          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
12716            node = _ref1[_j];
12717            node.innerHTML = this.filesize(file.size);
12718          }
12719          if (this.options.addRemoveLinks) {
12720            file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
12721            file.previewElement.appendChild(file._removeLink);
12722          }
12723          removeFileEvent = (function(_this) {
12724            return function(e) {
12725              e.preventDefault();
12726              e.stopPropagation();
12727              if (file.status === Dropzone.UPLOADING) {
12728                return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {
12729                  return _this.removeFile(file);
12730                });
12731              } else {
12732                if (_this.options.dictRemoveFileConfirmation) {
12733                  return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {
12734                    return _this.removeFile(file);
12735                  });
12736                } else {
12737                  return _this.removeFile(file);
12738                }
12739              }
12740            };
12741          })(this);
12742          _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]");
12743          _results = [];
12744          for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
12745            removeLink = _ref2[_k];
12746            _results.push(removeLink.addEventListener("click", removeFileEvent));
12747          }
12748          return _results;
12749        }
12750      },
12751      removedfile: function(file) {
12752        var _ref;
12753        if (file.previewElement) {
12754          if ((_ref = file.previewElement) != null) {
12755            _ref.parentNode.removeChild(file.previewElement);
12756          }
12757        }
12758        return this._updateMaxFilesReachedClass();
12759      },
12760      thumbnail: function(file, dataUrl) {
12761        var thumbnailElement, _i, _len, _ref;
12762        if (file.previewElement) {
12763          file.previewElement.classList.remove("dz-file-preview");
12764          _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]");
12765          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12766            thumbnailElement = _ref[_i];
12767            thumbnailElement.alt = file.name;
12768            thumbnailElement.src = dataUrl;
12769          }
12770          return setTimeout(((function(_this) {
12771            return function() {
12772              return file.previewElement.classList.add("dz-image-preview");
12773            };
12774          })(this)), 1);
12775        }
12776      },
12777      error: function(file, message) {
12778        var node, _i, _len, _ref, _results;
12779        if (file.previewElement) {
12780          file.previewElement.classList.add("dz-error");
12781          if (typeof message !== "String" && message.error) {
12782            message = message.error;
12783          }
12784          _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]");
12785          _results = [];
12786          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12787            node = _ref[_i];
12788            _results.push(node.textContent = message);
12789          }
12790          return _results;
12791        }
12792      },
12793      errormultiple: noop,
12794      processing: function(file) {
12795        if (file.previewElement) {
12796          file.previewElement.classList.add("dz-processing");
12797          if (file._removeLink) {
12798            return file._removeLink.textContent = this.options.dictCancelUpload;
12799          }
12800        }
12801      },
12802      processingmultiple: noop,
12803      uploadprogress: function(file, progress, bytesSent) {
12804        var node, _i, _len, _ref, _results;
12805        if (file.previewElement) {
12806          _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]");
12807          _results = [];
12808          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12809            node = _ref[_i];
12810            if (node.nodeName === 'PROGRESS') {
12811              _results.push(node.value = progress);
12812            } else {
12813              _results.push(node.style.width = "" + progress + "%");
12814            }
12815          }
12816          return _results;
12817        }
12818      },
12819      totaluploadprogress: noop,
12820      sending: noop,
12821      sendingmultiple: noop,
12822      success: function(file) {
12823        if (file.previewElement) {
12824          return file.previewElement.classList.add("dz-success");
12825        }
12826      },
12827      successmultiple: noop,
12828      canceled: function(file) {
12829        return this.emit("error", file, "Upload canceled.");
12830      },
12831      canceledmultiple: noop,
12832      complete: function(file) {
12833        if (file._removeLink) {
12834          file._removeLink.textContent = this.options.dictRemoveFile;
12835        }
12836        if (file.previewElement) {
12837          return file.previewElement.classList.add("dz-complete");
12838        }
12839      },
12840      completemultiple: noop,
12841      maxfilesexceeded: noop,
12842      maxfilesreached: noop,
12843      queuecomplete: noop,
12844      addedfiles: noop,
12845      previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Check</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Error</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>"
12846    };
12847
12848    extend = function() {
12849      var key, object, objects, target, val, _i, _len;
12850      target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
12851      for (_i = 0, _len = objects.length; _i < _len; _i++) {
12852        object = objects[_i];
12853        for (key in object) {
12854          val = object[key];
12855          target[key] = val;
12856        }
12857      }
12858      return target;
12859    };
12860
12861    function Dropzone(element, options) {
12862      var elementOptions, fallback, _ref;
12863      this.element = element;
12864      this.version = Dropzone.version;
12865      this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, "");
12866      this.clickableElements = [];
12867      this.listeners = [];
12868      this.files = [];
12869      if (typeof this.element === "string") {
12870        this.element = document.querySelector(this.element);
12871      }
12872      if (!(this.element && (this.element.nodeType != null))) {
12873        throw new Error("Invalid dropzone element.");
12874      }
12875      if (this.element.dropzone) {
12876        throw new Error("Dropzone already attached.");
12877      }
12878      Dropzone.instances.push(this);
12879      this.element.dropzone = this;
12880      elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};
12881      this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});
12882      if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {
12883        return this.options.fallback.call(this);
12884      }
12885      if (this.options.url == null) {
12886        this.options.url = this.element.getAttribute("action");
12887      }
12888      if (!this.options.url) {
12889        throw new Error("No URL provided.");
12890      }
12891      if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {
12892        throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
12893      }
12894      if (this.options.acceptedMimeTypes) {
12895        this.options.acceptedFiles = this.options.acceptedMimeTypes;
12896        delete this.options.acceptedMimeTypes;
12897      }
12898      this.options.method = this.options.method.toUpperCase();
12899      if ((fallback = this.getExistingFallback()) && fallback.parentNode) {
12900        fallback.parentNode.removeChild(fallback);
12901      }
12902      if (this.options.previewsContainer !== false) {
12903        if (this.options.previewsContainer) {
12904          this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer");
12905        } else {
12906          this.previewsContainer = this.element;
12907        }
12908      }
12909      if (this.options.clickable) {
12910        if (this.options.clickable === true) {
12911          this.clickableElements = [this.element];
12912        } else {
12913          this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable");
12914        }
12915      }
12916      this.init();
12917    }
12918
12919    Dropzone.prototype.getAcceptedFiles = function() {
12920      var file, _i, _len, _ref, _results;
12921      _ref = this.files;
12922      _results = [];
12923      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12924        file = _ref[_i];
12925        if (file.accepted) {
12926          _results.push(file);
12927        }
12928      }
12929      return _results;
12930    };
12931
12932    Dropzone.prototype.getRejectedFiles = function() {
12933      var file, _i, _len, _ref, _results;
12934      _ref = this.files;
12935      _results = [];
12936      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12937        file = _ref[_i];
12938        if (!file.accepted) {
12939          _results.push(file);
12940        }
12941      }
12942      return _results;
12943    };
12944
12945    Dropzone.prototype.getFilesWithStatus = function(status) {
12946      var file, _i, _len, _ref, _results;
12947      _ref = this.files;
12948      _results = [];
12949      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12950        file = _ref[_i];
12951        if (file.status === status) {
12952          _results.push(file);
12953        }
12954      }
12955      return _results;
12956    };
12957
12958    Dropzone.prototype.getQueuedFiles = function() {
12959      return this.getFilesWithStatus(Dropzone.QUEUED);
12960    };
12961
12962    Dropzone.prototype.getUploadingFiles = function() {
12963      return this.getFilesWithStatus(Dropzone.UPLOADING);
12964    };
12965
12966    Dropzone.prototype.getAddedFiles = function() {
12967      return this.getFilesWithStatus(Dropzone.ADDED);
12968    };
12969
12970    Dropzone.prototype.getActiveFiles = function() {
12971      var file, _i, _len, _ref, _results;
12972      _ref = this.files;
12973      _results = [];
12974      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
12975        file = _ref[_i];
12976        if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {
12977          _results.push(file);
12978        }
12979      }
12980      return _results;
12981    };
12982
12983    Dropzone.prototype.init = function() {
12984      var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1;
12985      if (this.element.tagName === "form") {
12986        this.element.setAttribute("enctype", "multipart/form-data");
12987      }
12988      if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
12989        this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
12990      }
12991      if (this.clickableElements.length) {
12992        setupHiddenFileInput = (function(_this) {
12993          return function() {
12994            if (_this.hiddenFileInput) {
12995              _this.hiddenFileInput.parentNode.removeChild(_this.hiddenFileInput);
12996            }
12997            _this.hiddenFileInput = document.createElement("input");
12998            _this.hiddenFileInput.setAttribute("type", "file");
12999            if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {
13000              _this.hiddenFileInput.setAttribute("multiple", "multiple");
13001            }
13002            _this.hiddenFileInput.className = "dz-hidden-input";
13003            if (_this.options.acceptedFiles != null) {
13004              _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles);
13005            }
13006            if (_this.options.capture != null) {
13007              _this.hiddenFileInput.setAttribute("capture", _this.options.capture);
13008            }
13009            _this.hiddenFileInput.style.visibility = "hidden";
13010            _this.hiddenFileInput.style.position = "absolute";
13011            _this.hiddenFileInput.style.top = "0";
13012            _this.hiddenFileInput.style.left = "0";
13013            _this.hiddenFileInput.style.height = "0";
13014            _this.hiddenFileInput.style.width = "0";
13015            document.querySelector(_this.options.hiddenInputContainer).appendChild(_this.hiddenFileInput);
13016            return _this.hiddenFileInput.addEventListener("change", function() {
13017              var file, files, _i, _len;
13018              files = _this.hiddenFileInput.files;
13019              if (files.length) {
13020                for (_i = 0, _len = files.length; _i < _len; _i++) {
13021                  file = files[_i];
13022                  _this.addFile(file);
13023                }
13024              }
13025              _this.emit("addedfiles", files);
13026              return setupHiddenFileInput();
13027            });
13028          };
13029        })(this);
13030        setupHiddenFileInput();
13031      }
13032      this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL;
13033      _ref1 = this.events;
13034      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
13035        eventName = _ref1[_i];
13036        this.on(eventName, this.options[eventName]);
13037      }
13038      this.on("uploadprogress", (function(_this) {
13039        return function() {
13040          return _this.updateTotalUploadProgress();
13041        };
13042      })(this));
13043      this.on("removedfile", (function(_this) {
13044        return function() {
13045          return _this.updateTotalUploadProgress();
13046        };
13047      })(this));
13048      this.on("canceled", (function(_this) {
13049        return function(file) {
13050          return _this.emit("complete", file);
13051        };
13052      })(this));
13053      this.on("complete", (function(_this) {
13054        return function(file) {
13055          if (_this.getAddedFiles().length === 0 && _this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {
13056            return setTimeout((function() {
13057              return _this.emit("queuecomplete");
13058            }), 0);
13059          }
13060        };
13061      })(this));
13062      noPropagation = function(e) {
13063        e.stopPropagation();
13064        if (e.preventDefault) {
13065          return e.preventDefault();
13066        } else {
13067          return e.returnValue = false;
13068        }
13069      };
13070      this.listeners = [
13071        {
13072          element: this.element,
13073          events: {
13074            "dragstart": (function(_this) {
13075              return function(e) {
13076                return _this.emit("dragstart", e);
13077              };
13078            })(this),
13079            "dragenter": (function(_this) {
13080              return function(e) {
13081                noPropagation(e);
13082                return _this.emit("dragenter", e);
13083              };
13084            })(this),
13085            "dragover": (function(_this) {
13086              return function(e) {
13087                var efct;
13088                try {
13089                  efct = e.dataTransfer.effectAllowed;
13090                } catch (_error) {}
13091                e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
13092                noPropagation(e);
13093                return _this.emit("dragover", e);
13094              };
13095            })(this),
13096            "dragleave": (function(_this) {
13097              return function(e) {
13098                return _this.emit("dragleave", e);
13099              };
13100            })(this),
13101            "drop": (function(_this) {
13102              return function(e) {
13103                noPropagation(e);
13104                return _this.drop(e);
13105              };
13106            })(this),
13107            "dragend": (function(_this) {
13108              return function(e) {
13109                return _this.emit("dragend", e);
13110              };
13111            })(this)
13112          }
13113        }
13114      ];
13115      this.clickableElements.forEach((function(_this) {
13116        return function(clickableElement) {
13117          return _this.listeners.push({
13118            element: clickableElement,
13119            events: {
13120              "click": function(evt) {
13121                if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) {
13122                  _this.hiddenFileInput.click();
13123                }
13124                return true;
13125              }
13126            }
13127          });
13128        };
13129      })(this));
13130      this.enable();
13131      return this.options.init.call(this);
13132    };
13133
13134    Dropzone.prototype.destroy = function() {
13135      var _ref;
13136      this.disable();
13137      this.removeAllFiles(true);
13138      if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) {
13139        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
13140        this.hiddenFileInput = null;
13141      }
13142      delete this.element.dropzone;
13143      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
13144    };
13145
13146    Dropzone.prototype.updateTotalUploadProgress = function() {
13147      var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref;
13148      totalBytesSent = 0;
13149      totalBytes = 0;
13150      activeFiles = this.getActiveFiles();
13151      if (activeFiles.length) {
13152        _ref = this.getActiveFiles();
13153        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13154          file = _ref[_i];
13155          totalBytesSent += file.upload.bytesSent;
13156          totalBytes += file.upload.total;
13157        }
13158        totalUploadProgress = 100 * totalBytesSent / totalBytes;
13159      } else {
13160        totalUploadProgress = 100;
13161      }
13162      return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
13163    };
13164
13165    Dropzone.prototype._getParamName = function(n) {
13166      if (typeof this.options.paramName === "function") {
13167        return this.options.paramName(n);
13168      } else {
13169        return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
13170      }
13171    };
13172
13173    Dropzone.prototype._renameFilename = function(name) {
13174      if (typeof this.options.renameFilename !== "function") {
13175        return name;
13176      }
13177      return this.options.renameFilename(name);
13178    };
13179
13180    Dropzone.prototype.getFallbackForm = function() {
13181      var existingFallback, fields, fieldsString, form;
13182      if (existingFallback = this.getExistingFallback()) {
13183        return existingFallback;
13184      }
13185      fieldsString = "<div class=\"dz-fallback\">";
13186      if (this.options.dictFallbackText) {
13187        fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
13188      }
13189      fieldsString += "<input type=\"file\" name=\"" + (this._getParamName(0)) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : void 0) + " /><input type=\"submit\" value=\"Upload!\"></div>";
13190      fields = Dropzone.createElement(fieldsString);
13191      if (this.element.tagName !== "FORM") {
13192        form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
13193        form.appendChild(fields);
13194      } else {
13195        this.element.setAttribute("enctype", "multipart/form-data");
13196        this.element.setAttribute("method", this.options.method);
13197      }
13198      return form != null ? form : fields;
13199    };
13200
13201    Dropzone.prototype.getExistingFallback = function() {
13202      var fallback, getFallback, tagName, _i, _len, _ref;
13203      getFallback = function(elements) {
13204        var el, _i, _len;
13205        for (_i = 0, _len = elements.length; _i < _len; _i++) {
13206          el = elements[_i];
13207          if (/(^| )fallback($| )/.test(el.className)) {
13208            return el;
13209          }
13210        }
13211      };
13212      _ref = ["div", "form"];
13213      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13214        tagName = _ref[_i];
13215        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
13216          return fallback;
13217        }
13218      }
13219    };
13220
13221    Dropzone.prototype.setupEventListeners = function() {
13222      var elementListeners, event, listener, _i, _len, _ref, _results;
13223      _ref = this.listeners;
13224      _results = [];
13225      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13226        elementListeners = _ref[_i];
13227        _results.push((function() {
13228          var _ref1, _results1;
13229          _ref1 = elementListeners.events;
13230          _results1 = [];
13231          for (event in _ref1) {
13232            listener = _ref1[event];
13233            _results1.push(elementListeners.element.addEventListener(event, listener, false));
13234          }
13235          return _results1;
13236        })());
13237      }
13238      return _results;
13239    };
13240
13241    Dropzone.prototype.removeEventListeners = function() {
13242      var elementListeners, event, listener, _i, _len, _ref, _results;
13243      _ref = this.listeners;
13244      _results = [];
13245      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13246        elementListeners = _ref[_i];
13247        _results.push((function() {
13248          var _ref1, _results1;
13249          _ref1 = elementListeners.events;
13250          _results1 = [];
13251          for (event in _ref1) {
13252            listener = _ref1[event];
13253            _results1.push(elementListeners.element.removeEventListener(event, listener, false));
13254          }
13255          return _results1;
13256        })());
13257      }
13258      return _results;
13259    };
13260
13261    Dropzone.prototype.disable = function() {
13262      var file, _i, _len, _ref, _results;
13263      this.clickableElements.forEach(function(element) {
13264        return element.classList.remove("dz-clickable");
13265      });
13266      this.removeEventListeners();
13267      _ref = this.files;
13268      _results = [];
13269      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13270        file = _ref[_i];
13271        _results.push(this.cancelUpload(file));
13272      }
13273      return _results;
13274    };
13275
13276    Dropzone.prototype.enable = function() {
13277      this.clickableElements.forEach(function(element) {
13278        return element.classList.add("dz-clickable");
13279      });
13280      return this.setupEventListeners();
13281    };
13282
13283    Dropzone.prototype.filesize = function(size) {
13284      var cutoff, i, selectedSize, selectedUnit, unit, units, _i, _len;
13285      selectedSize = 0;
13286      selectedUnit = "b";
13287      if (size > 0) {
13288        units = ['TB', 'GB', 'MB', 'KB', 'b'];
13289        for (i = _i = 0, _len = units.length; _i < _len; i = ++_i) {
13290          unit = units[i];
13291          cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
13292          if (size >= cutoff) {
13293            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
13294            selectedUnit = unit;
13295            break;
13296          }
13297        }
13298        selectedSize = Math.round(10 * selectedSize) / 10;
13299      }
13300      return "<strong>" + selectedSize + "</strong> " + selectedUnit;
13301    };
13302
13303    Dropzone.prototype._updateMaxFilesReachedClass = function() {
13304      if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
13305        if (this.getAcceptedFiles().length === this.options.maxFiles) {
13306          this.emit('maxfilesreached', this.files);
13307        }
13308        return this.element.classList.add("dz-max-files-reached");
13309      } else {
13310        return this.element.classList.remove("dz-max-files-reached");
13311      }
13312    };
13313
13314    Dropzone.prototype.drop = function(e) {
13315      var files, items;
13316      if (!e.dataTransfer) {
13317        return;
13318      }
13319      this.emit("drop", e);
13320      files = e.dataTransfer.files;
13321      this.emit("addedfiles", files);
13322      if (files.length) {
13323        items = e.dataTransfer.items;
13324        if (items && items.length && (items[0].webkitGetAsEntry != null)) {
13325          this._addFilesFromItems(items);
13326        } else {
13327          this.handleFiles(files);
13328        }
13329      }
13330    };
13331
13332    Dropzone.prototype.paste = function(e) {
13333      var items, _ref;
13334      if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {
13335        return;
13336      }
13337      this.emit("paste", e);
13338      items = e.clipboardData.items;
13339      if (items.length) {
13340        return this._addFilesFromItems(items);
13341      }
13342    };
13343
13344    Dropzone.prototype.handleFiles = function(files) {
13345      var file, _i, _len, _results;
13346      _results = [];
13347      for (_i = 0, _len = files.length; _i < _len; _i++) {
13348        file = files[_i];
13349        _results.push(this.addFile(file));
13350      }
13351      return _results;
13352    };
13353
13354    Dropzone.prototype._addFilesFromItems = function(items) {
13355      var entry, item, _i, _len, _results;
13356      _results = [];
13357      for (_i = 0, _len = items.length; _i < _len; _i++) {
13358        item = items[_i];
13359        if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {
13360          if (entry.isFile) {
13361            _results.push(this.addFile(item.getAsFile()));
13362          } else if (entry.isDirectory) {
13363            _results.push(this._addFilesFromDirectory(entry, entry.name));
13364          } else {
13365            _results.push(void 0);
13366          }
13367        } else if (item.getAsFile != null) {
13368          if ((item.kind == null) || item.kind === "file") {
13369            _results.push(this.addFile(item.getAsFile()));
13370          } else {
13371            _results.push(void 0);
13372          }
13373        } else {
13374          _results.push(void 0);
13375        }
13376      }
13377      return _results;
13378    };
13379
13380    Dropzone.prototype._addFilesFromDirectory = function(directory, path) {
13381      var dirReader, errorHandler, readEntries;
13382      dirReader = directory.createReader();
13383      errorHandler = function(error) {
13384        return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0;
13385      };
13386      readEntries = (function(_this) {
13387        return function() {
13388          return dirReader.readEntries(function(entries) {
13389            var entry, _i, _len;
13390            if (entries.length > 0) {
13391              for (_i = 0, _len = entries.length; _i < _len; _i++) {
13392                entry = entries[_i];
13393                if (entry.isFile) {
13394                  entry.file(function(file) {
13395                    if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
13396                      return;
13397                    }
13398                    file.fullPath = "" + path + "/" + file.name;
13399                    return _this.addFile(file);
13400                  });
13401                } else if (entry.isDirectory) {
13402                  _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name);
13403                }
13404              }
13405              readEntries();
13406            }
13407            return null;
13408          }, errorHandler);
13409        };
13410      })(this);
13411      return readEntries();
13412    };
13413
13414    Dropzone.prototype.accept = function(file, done) {
13415      if (file.size > this.options.maxFilesize * 1024 * 1024) {
13416        return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
13417      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
13418        return done(this.options.dictInvalidFileType);
13419      } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
13420        done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
13421        return this.emit("maxfilesexceeded", file);
13422      } else {
13423        return this.options.accept.call(this, file, done);
13424      }
13425    };
13426
13427    Dropzone.prototype.addFile = function(file) {
13428      file.upload = {
13429        progress: 0,
13430        total: file.size,
13431        bytesSent: 0
13432      };
13433      this.files.push(file);
13434      file.status = Dropzone.ADDED;
13435      this.emit("addedfile", file);
13436      this._enqueueThumbnail(file);
13437      return this.accept(file, (function(_this) {
13438        return function(error) {
13439          if (error) {
13440            file.accepted = false;
13441            _this._errorProcessing([file], error);
13442          } else {
13443            file.accepted = true;
13444            if (_this.options.autoQueue) {
13445              _this.enqueueFile(file);
13446            }
13447          }
13448          return _this._updateMaxFilesReachedClass();
13449        };
13450      })(this));
13451    };
13452
13453    Dropzone.prototype.enqueueFiles = function(files) {
13454      var file, _i, _len;
13455      for (_i = 0, _len = files.length; _i < _len; _i++) {
13456        file = files[_i];
13457        this.enqueueFile(file);
13458      }
13459      return null;
13460    };
13461
13462    Dropzone.prototype.enqueueFile = function(file) {
13463      if (file.status === Dropzone.ADDED && file.accepted === true) {
13464        file.status = Dropzone.QUEUED;
13465        if (this.options.autoProcessQueue) {
13466          return setTimeout(((function(_this) {
13467            return function() {
13468              return _this.processQueue();
13469            };
13470          })(this)), 0);
13471        }
13472      } else {
13473        throw new Error("This file can't be queued because it has already been processed or was rejected.");
13474      }
13475    };
13476
13477    Dropzone.prototype._thumbnailQueue = [];
13478
13479    Dropzone.prototype._processingThumbnail = false;
13480
13481    Dropzone.prototype._enqueueThumbnail = function(file) {
13482      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
13483        this._thumbnailQueue.push(file);
13484        return setTimeout(((function(_this) {
13485          return function() {
13486            return _this._processThumbnailQueue();
13487          };
13488        })(this)), 0);
13489      }
13490    };
13491
13492    Dropzone.prototype._processThumbnailQueue = function() {
13493      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
13494        return;
13495      }
13496      this._processingThumbnail = true;
13497      return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {
13498        return function() {
13499          _this._processingThumbnail = false;
13500          return _this._processThumbnailQueue();
13501        };
13502      })(this));
13503    };
13504
13505    Dropzone.prototype.removeFile = function(file) {
13506      if (file.status === Dropzone.UPLOADING) {
13507        this.cancelUpload(file);
13508      }
13509      this.files = without(this.files, file);
13510      this.emit("removedfile", file);
13511      if (this.files.length === 0) {
13512        return this.emit("reset");
13513      }
13514    };
13515
13516    Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {
13517      var file, _i, _len, _ref;
13518      if (cancelIfNecessary == null) {
13519        cancelIfNecessary = false;
13520      }
13521      _ref = this.files.slice();
13522      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13523        file = _ref[_i];
13524        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
13525          this.removeFile(file);
13526        }
13527      }
13528      return null;
13529    };
13530
13531    Dropzone.prototype.createThumbnail = function(file, callback) {
13532      var fileReader;
13533      fileReader = new FileReader;
13534      fileReader.onload = (function(_this) {
13535        return function() {
13536          if (file.type === "image/svg+xml") {
13537            _this.emit("thumbnail", file, fileReader.result);
13538            if (callback != null) {
13539              callback();
13540            }
13541            return;
13542          }
13543          return _this.createThumbnailFromUrl(file, fileReader.result, callback);
13544        };
13545      })(this);
13546      return fileReader.readAsDataURL(file);
13547    };
13548
13549    Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback, crossOrigin) {
13550      var img;
13551      img = document.createElement("img");
13552      if (crossOrigin) {
13553        img.crossOrigin = crossOrigin;
13554      }
13555      img.onload = (function(_this) {
13556        return function() {
13557          var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;
13558          file.width = img.width;
13559          file.height = img.height;
13560          resizeInfo = _this.options.resize.call(_this, file);
13561          if (resizeInfo.trgWidth == null) {
13562            resizeInfo.trgWidth = resizeInfo.optWidth;
13563          }
13564          if (resizeInfo.trgHeight == null) {
13565            resizeInfo.trgHeight = resizeInfo.optHeight;
13566          }
13567          canvas = document.createElement("canvas");
13568          ctx = canvas.getContext("2d");
13569          canvas.width = resizeInfo.trgWidth;
13570          canvas.height = resizeInfo.trgHeight;
13571          drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
13572          thumbnail = canvas.toDataURL("image/png");
13573          _this.emit("thumbnail", file, thumbnail);
13574          if (callback != null) {
13575            return callback();
13576          }
13577        };
13578      })(this);
13579      if (callback != null) {
13580        img.onerror = callback;
13581      }
13582      return img.src = imageUrl;
13583    };
13584
13585    Dropzone.prototype.processQueue = function() {
13586      var i, parallelUploads, processingLength, queuedFiles;
13587      parallelUploads = this.options.parallelUploads;
13588      processingLength = this.getUploadingFiles().length;
13589      i = processingLength;
13590      if (processingLength >= parallelUploads) {
13591        return;
13592      }
13593      queuedFiles = this.getQueuedFiles();
13594      if (!(queuedFiles.length > 0)) {
13595        return;
13596      }
13597      if (this.options.uploadMultiple) {
13598        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
13599      } else {
13600        while (i < parallelUploads) {
13601          if (!queuedFiles.length) {
13602            return;
13603          }
13604          this.processFile(queuedFiles.shift());
13605          i++;
13606        }
13607      }
13608    };
13609
13610    Dropzone.prototype.processFile = function(file) {
13611      return this.processFiles([file]);
13612    };
13613
13614    Dropzone.prototype.processFiles = function(files) {
13615      var file, _i, _len;
13616      for (_i = 0, _len = files.length; _i < _len; _i++) {
13617        file = files[_i];
13618        file.processing = true;
13619        file.status = Dropzone.UPLOADING;
13620        this.emit("processing", file);
13621      }
13622      if (this.options.uploadMultiple) {
13623        this.emit("processingmultiple", files);
13624      }
13625      return this.uploadFiles(files);
13626    };
13627
13628    Dropzone.prototype._getFilesWithXhr = function(xhr) {
13629      var file, files;
13630      return files = (function() {
13631        var _i, _len, _ref, _results;
13632        _ref = this.files;
13633        _results = [];
13634        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13635          file = _ref[_i];
13636          if (file.xhr === xhr) {
13637            _results.push(file);
13638          }
13639        }
13640        return _results;
13641      }).call(this);
13642    };
13643
13644    Dropzone.prototype.cancelUpload = function(file) {
13645      var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref;
13646      if (file.status === Dropzone.UPLOADING) {
13647        groupedFiles = this._getFilesWithXhr(file.xhr);
13648        for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) {
13649          groupedFile = groupedFiles[_i];
13650          groupedFile.status = Dropzone.CANCELED;
13651        }
13652        file.xhr.abort();
13653        for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) {
13654          groupedFile = groupedFiles[_j];
13655          this.emit("canceled", groupedFile);
13656        }
13657        if (this.options.uploadMultiple) {
13658          this.emit("canceledmultiple", groupedFiles);
13659        }
13660      } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) {
13661        file.status = Dropzone.CANCELED;
13662        this.emit("canceled", file);
13663        if (this.options.uploadMultiple) {
13664          this.emit("canceledmultiple", [file]);
13665        }
13666      }
13667      if (this.options.autoProcessQueue) {
13668        return this.processQueue();
13669      }
13670    };
13671
13672    resolveOption = function() {
13673      var args, option;
13674      option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
13675      if (typeof option === 'function') {
13676        return option.apply(this, args);
13677      }
13678      return option;
13679    };
13680
13681    Dropzone.prototype.uploadFile = function(file) {
13682      return this.uploadFiles([file]);
13683    };
13684
13685    Dropzone.prototype.uploadFiles = function(files) {
13686      var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
13687      xhr = new XMLHttpRequest();
13688      for (_i = 0, _len = files.length; _i < _len; _i++) {
13689        file = files[_i];
13690        file.xhr = xhr;
13691      }
13692      method = resolveOption(this.options.method, files);
13693      url = resolveOption(this.options.url, files);
13694      xhr.open(method, url, true);
13695      xhr.withCredentials = !!this.options.withCredentials;
13696      response = null;
13697      handleError = (function(_this) {
13698        return function() {
13699          var _j, _len1, _results;
13700          _results = [];
13701          for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
13702            file = files[_j];
13703            _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr));
13704          }
13705          return _results;
13706        };
13707      })(this);
13708      updateProgress = (function(_this) {
13709        return function(e) {
13710          var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results;
13711          if (e != null) {
13712            progress = 100 * e.loaded / e.total;
13713            for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
13714              file = files[_j];
13715              file.upload = {
13716                progress: progress,
13717                total: e.total,
13718                bytesSent: e.loaded
13719              };
13720            }
13721          } else {
13722            allFilesFinished = true;
13723            progress = 100;
13724            for (_k = 0, _len2 = files.length; _k < _len2; _k++) {
13725              file = files[_k];
13726              if (!(file.upload.progress === 100 && file.upload.b
13726ytesSent === file.upload.total)) {
13727                allFilesFinished = false;
13728              }
13729              file.upload.progress = progress;
13730              file.upload.bytesSent = file.upload.total;
13731            }
13732            if (allFilesFinished) {
13733              return;
13734            }
13735          }
13736          _results = [];
13737          for (_l = 0, _len3 = files.length; _l < _len3; _l++) {
13738            file = files[_l];
13739            _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent));
13740          }
13741          return _results;
13742        };
13743      })(this);
13744      xhr.onload = (function(_this) {
13745        return function(e) {
13746          var _ref;
13747          if (files[0].status === Dropzone.CANCELED) {
13748            return;
13749          }
13750          if (xhr.readyState !== 4) {
13751            return;
13752          }
13753          response = xhr.responseText;
13754          if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
13755            try {
13756              response = JSON.parse(response);
13757            } catch (_error) {
13758              e = _error;
13759              response = "Invalid JSON response from server.";
13760            }
13761          }
13762          updateProgress();
13763          if (!((200 <= (_ref = xhr.status) && _ref < 300))) {
13764            return handleError();
13765          } else {
13766            return _this._finished(files, response, e);
13767          }
13768        };
13769      })(this);
13770      xhr.onerror = (function(_this) {
13771        return function() {
13772          if (files[0].status === Dropzone.CANCELED) {
13773            return;
13774          }
13775          return handleError();
13776        };
13777      })(this);
13778      progressObj = (_ref = xhr.upload) != null ? _ref : xhr;
13779      progressObj.onprogress = updateProgress;
13780      headers = {
13781        "Accept": "application/json",
13782        "Cache-Control": "no-cache",
13783        "X-Requested-With": "XMLHttpRequest"
13784      };
13785      if (this.options.headers) {
13786        extend(headers, this.options.headers);
13787      }
13788      for (headerName in headers) {
13789        headerValue = headers[headerName];
13790        if (headerValue) {
13791          xhr.setRequestHeader(headerName, headerValue);
13792        }
13793      }
13794      formData = new FormData();
13795      if (this.options.params) {
13796        _ref1 = this.options.params;
13797        for (key in _ref1) {
13798          value = _ref1[key];
13799          formData.append(key, value);
13800        }
13801      }
13802      for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
13803        file = files[_j];
13804        this.emit("sending", file, xhr, formData);
13805      }
13806      if (this.options.uploadMultiple) {
13807        this.emit("sendingmultiple", files, xhr, formData);
13808      }
13809      if (this.element.tagName === "FORM") {
13810        _ref2 = this.element.querySelectorAll("input, textarea, select, button");
13811        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
13812          input = _ref2[_k];
13813          inputName = input.getAttribute("name");
13814          inputType = input.getAttribute("type");
13815          if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
13816            _ref3 = input.options;
13817            for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
13818              option = _ref3[_l];
13819              if (option.selected) {
13820                formData.append(inputName, option.value);
13821              }
13822            }
13823          } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) {
13824            formData.append(inputName, input.value);
13825          }
13826        }
13827      }
13828      for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {
13829        formData.append(this._getParamName(i), files[i], this._renameFilename(files[i].name));
13830      }
13831      return this.submitRequest(xhr, formData, files);
13832    };
13833
13834    Dropzone.prototype.submitRequest = function(xhr, formData, files) {
13835      return xhr.send(formData);
13836    };
13837
13838    Dropzone.prototype._finished = function(files, responseText, e) {
13839      var file, _i, _len;
13840      for (_i = 0, _len = files.length; _i < _len; _i++) {
13841        file = files[_i];
13842        file.status = Dropzone.SUCCESS;
13843        this.emit("success", file, responseText, e);
13844        this.emit("complete", file);
13845      }
13846      if (this.options.uploadMultiple) {
13847        this.emit("successmultiple", files, responseText, e);
13848        this.emit("completemultiple", files);
13849      }
13850      if (this.options.autoProcessQueue) {
13851        return this.processQueue();
13852      }
13853    };
13854
13855    Dropzone.prototype._errorProcessing = function(files, message, xhr) {
13856      var file, _i, _len;
13857      for (_i = 0, _len = files.length; _i < _len; _i++) {
13858        file = files[_i];
13859        file.status = Dropzone.ERROR;
13860        this.emit("error", file, message, xhr);
13861        this.emit("complete", file);
13862      }
13863      if (this.options.uploadMultiple) {
13864        this.emit("errormultiple", files, message, xhr);
13865        this.emit("completemultiple", files);
13866      }
13867      if (this.options.autoProcessQueue) {
13868        return this.processQueue();
13869      }
13870    };
13871
13872    return Dropzone;
13873
13874  })(Emitter);
13875
13876  Dropzone.version = "4.3.0";
13877
13878  Dropzone.options = {};
13879
13880  Dropzone.optionsForElement = function(element) {
13881    if (element.getAttribute("id")) {
13882      return Dropzone.options[camelize(element.getAttribute("id"))];
13883    } else {
13884      return void 0;
13885    }
13886  };
13887
13888  Dropzone.instances = [];
13889
13890  Dropzone.forElement = function(element) {
13891    if (typeof element === "string") {
13892      element = document.querySelector(element);
13893    }
13894    if ((element != null ? element.dropzone : void 0) == null) {
13895      throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
13896    }
13897    return element.dropzone;
13898  };
13899
13900  Dropzone.autoDiscover = true;
13901
13902  Dropzone.discover = function() {
13903    var checkElements, dropzone, dropzones, _i, _len, _results;
13904    if (document.querySelectorAll) {
13905      dropzones = document.querySelectorAll(".dropzone");
13906    } else {
13907      dropzones = [];
13908      checkElements = function(elements) {
13909        var el, _i, _len, _results;
13910        _results = [];
13911        for (_i = 0, _len = elements.length; _i < _len; _i++) {
13912          el = elements[_i];
13913          if (/(^| )dropzone($| )/.test(el.className)) {
13914            _results.push(dropzones.push(el));
13915          } else {
13916            _results.push(void 0);
13917          }
13918        }
13919        return _results;
13920      };
13921      checkElements(document.getElementsByTagName("div"));
13922      checkElements(document.getElementsByTagName("form"));
13923    }
13924    _results = [];
13925    for (_i = 0, _len = dropzones.length; _i < _len; _i++) {
13926      dropzone = dropzones[_i];
13927      if (Dropzone.optionsForElement(dropzone) !== false) {
13928        _results.push(new Dropzone(dropzone));
13929      } else {
13930        _results.push(void 0);
13931      }
13932    }
13933    return _results;
13934  };
13935
13936  Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i];
13937
13938  Dropzone.isBrowserSupported = function() {
13939    var capableBrowser, regex, _i, _len, _ref;
13940    capableBrowser = true;
13941    if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
13942      if (!("classList" in document.createElement("a"))) {
13943        capableBrowser = false;
13944      } else {
13945        _ref = Dropzone.blacklistedBrowsers;
13946        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
13947          regex = _ref[_i];
13948          if (regex.test(navigator.userAgent)) {
13949            capableBrowser = false;
13950            continue;
13951          }
13952        }
13953      }
13954    } else {
13955      capableBrowser = false;
13956    }
13957    return capableBrowser;
13958  };
13959
13960  without = function(list, rejectedItem) {
13961    var item, _i, _len, _results;
13962    _results = [];
13963    for (_i = 0, _len = list.length; _i < _len; _i++) {
13964      item = list[_i];
13965      if (item !== rejectedItem) {
13966        _results.push(item);
13967      }
13968    }
13969    return _results;
13970  };
13971
13972  camelize = function(str) {
13973    return str.replace(/[\-_](\w)/g, function(match) {
13974      return match.charAt(1).toUpperCase();
13975    });
13976  };
13977
13978  Dropzone.createElement = function(string) {
13979    var div;
13980    div = document.createElement("div");
13981    div.innerHTML = string;
13982    return div.childNodes[0];
13983  };
13984
13985  Dropzone.elementInside = function(element, container) {
13986    if (element === container) {
13987      return true;
13988    }
13989    while (element = element.parentNode) {
13990      if (element === container) {
13991        return true;
13992      }
13993    }
13994    return false;
13995  };
13996
13997  Dropzone.getElement = function(el, name) {
13998    var element;
13999    if (typeof el === "string") {
14000      element = document.querySelector(el);
14001    } else if (el.nodeType != null) {
14002      element = el;
14003    }
14004    if (element == null) {
14005      throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
14006    }
14007    return element;
14008  };
14009
14010  Dropzone.getElements = function(els, name) {
14011    var e, el, elements, _i, _j, _len, _len1, _ref;
14012    if (els instanceof Array) {
14013      elements = [];
14014      try {
14015        for (_i = 0, _len = els.length; _i < _len; _i++) {
14016          el = els[_i];
14017          elements.push(this.getElement(el, name));
14018        }
14019      } catch (_error) {
14020        e = _error;
14021        elements = null;
14022      }
14023    } else if (typeof els === "string") {
14024      elements = [];
14025      _ref = document.querySelectorAll(els);
14026      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
14027        el = _ref[_j];
14028        elements.push(el);
14029      }
14030    } else if (els.nodeType != null) {
14031      elements = [els];
14032    }
14033    if (!((elements != null) && elements.length)) {
14034      throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
14035    }
14036    return elements;
14037  };
14038
14039  Dropzone.confirm = function(question, accepted, rejected) {
14040    if (window.confirm(question)) {
14041      return accepted();
14042    } else if (rejected != null) {
14043      return rejected();
14044    }
14045  };
14046
14047  Dropzone.isValidFile = function(file, acceptedFiles) {
14048    var baseMimeType, mimeType, validType, _i, _len;
14049    if (!acceptedFiles) {
14050      return true;
14051    }
14052    acceptedFiles = acceptedFiles.split(",");
14053    mimeType = file.type;
14054    baseMimeType = mimeType.replace(/\/.*$/, "");
14055    for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) {
14056      validType = acceptedFiles[_i];
14057      validType = validType.trim();
14058      if (validType.charAt(0) === ".") {
14059        if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
14060          return true;
14061        }
14062      } else if (/\/\*$/.test(validType)) {
14063        if (baseMimeType === validType.replace(/\/.*$/, "")) {
14064          return true;
14065        }
14066      } else {
14067        if (mimeType === validType) {
14068          return true;
14069        }
14070      }
14071    }
14072    return false;
14073  };
14074
14075  if (typeof jQuery !== "undefined" && jQuery !== null) {
14076    jQuery.fn.dropzone = function(options) {
14077      return this.each(function() {
14078        return new Dropzone(this, options);
14079      });
14080    };
14081  }
14082
14083  if (typeof module !== "undefined" && module !== null) {
14084    module.exports = Dropzone;
14085  } else {
14086    window.Dropzone = Dropzone;
14087  }
14088
14089  Dropzone.ADDED = "added";
14090
14091  Dropzone.QUEUED = "queued";
14092
14093  Dropzone.ACCEPTED = Dropzone.QUEUED;
14094
14095  Dropzone.UPLOADING = "uploading";
14096
14097  Dropzone.PROCESSING = Dropzone.UPLOADING;
14098
14099  Dropzone.CANCELED = "canceled";
14100
14101  Dropzone.ERROR = "error";
14102
14103  Dropzone.SUCCESS = "success";
14104
14105
14106  /*
14107  
14108  Bugfix for iOS 6 and 7
14109  Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
14110  based on the work of https://github.com/stomita/ios-imagefile-megapixel
14111   */
14112
14113  detectVerticalSquash = function(img) {
14114    var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;
14115    iw = img.naturalWidth;
14116    ih = img.naturalHeight;
14117    canvas = document.createElement("canvas");
14118    canvas.width = 1;
14119    canvas.height = ih;
14120    ctx = canvas.getContext("2d");
14121    ctx.drawImage(img, 0, 0);
14122    data = ctx.getImageData(0, 0, 1, ih).data;
14123    sy = 0;
14124    ey = ih;
14125    py = ih;
14126    while (py > sy) {
14127      alpha = data[(py - 1) * 4 + 3];
14128      if (alpha === 0) {
14129        ey = py;
14130      } else {
14131        sy = py;
14132      }
14133      py = (ey + sy) >> 1;
14134    }
14135    ratio = py / ih;
14136    if (ratio === 0) {
14137      return 1;
14138    } else {
14139      return ratio;
14140    }
14141  };
14142
14143  drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
14144    var vertSquashRatio;
14145    vertSquashRatio = detectVerticalSquash(img);
14146    return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
14147  };
14148
14149
14150  /*
14151   * contentloaded.js
14152   *
14153   * Author: Diego Perini (diego.perini at gmail.com)
14154   * Summary: cross-browser wrapper for DOMContentLoaded
14155   * Updated: 20101020
14156   * License: MIT
14157   * Version: 1.2
14158   *
14159   * URL:
14160   * http://javascript.nwbox.com/ContentLoaded/
14161   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
14162   */
14163
14164  contentLoaded = function(win, fn) {
14165    var add, doc, done, init, poll, pre, rem, root, top;
14166    done = false;
14167    top = true;
14168    doc = win.document;
14169    root = doc.documentElement;
14170    add = (doc.addEventListener ? "addEventListener" : "attachEvent");
14171    rem = (doc.addEventListener ? "removeEventListener" : "detachEvent");
14172    pre = (doc.addEventListener ? "" : "on");
14173    init = function(e) {
14174      if (e.type === "readystatechange" && doc.readyState !== "complete") {
14175        return;
14176      }
14177      (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
14178      if (!done && (done = true)) {
14179        return fn.call(win, e.type || e);
14180      }
14181    };
14182    poll = function() {
14183      var e;
14184      try {
14185        root.doScroll("left");
14186      } catch (_error) {
14187        e = _error;
14188        setTimeout(poll, 50);
14189        return;
14190      }
14191      return init("poll");
14192    };
14193    if (doc.readyState !== "complete") {
14194      if (doc.createEventObject && root.doScroll) {
14195        try {
14196          top = !win.frameElement;
14197        } catch (_error) {}
14198        if (top) {
14199          poll();
14200        }
14201      }
14202      doc[add](pre + "DOMContentLoaded", init, false);
14203      doc[add](pre + "readystatechange", init, false);
14204      return win[add](pre + "load", init, false);
14205    }
14206  };
14207
14208  Dropzone._autoDiscoverFunction = function() {
14209    if (Dropzone.autoDiscover) {
14210      return Dropzone.discover();
14211    }
14212  };
14213
14214  contentLoaded(window, Dropzone._autoDiscoverFunction);
14215
14216}).call(this);
14217/**
14218 * menu-aim is a jQuery plugin for dropdown menus that can differentiate
14219 * between a user trying hover over a dropdown item vs trying to navigate into
14220 * a submenu's contents.
14221 *
14222 * menu-aim assumes that you have are using a menu with submenus that expand
14223 * to the menu's right. It will fire events when the user's mouse enters a new
14224 * dropdown item *and* when that item is being intentionally hovered over.
14225 *
14226 * __________________________
14227 * | Monkeys  >|   Gorilla  |
14228 * | Gorillas >|   Content  |
14229 * | Chimps   >|   Here     |
14230 * |___________|____________|
14231 *
14232 * In the above example, "Gorillas" is selected and its submenu content is
14233 * being shown on the right. Imagine that the user's cursor is hovering over
14234 * "Gorillas." When they move their mouse into the "Gorilla Content" area, they
14235 * may briefly hover over "Chimps." This shouldn't close the "Gorilla Content"
14236 * area.
14237 *
14238 * This problem is normally solved using timeouts and delays. menu-aim tries to
14239 * solve this by detecting the direction of the user's mouse movement. This can
14240 * make for quicker transitions when navigating up and down the menu. The
14241 * experience is hopefully similar to amazon.com/'s "Shop by Department"
14242 * dropdown.
14243 *
14244 * Use like so:
14245 *
14246 *      $("#menu").menuAim({
14247 *          activate: $.noop,  // fired on row activation
14248 *          deactivate: $.noop  // fired on row deactivation
14249 *      });
14250 *
14251 *  ...to receive events when a menu's row has been purposefully (de)activated.
14252 *
14253 * The following options can be passed to menuAim. All functions execute with
14254 * the relevant row's HTML element as the execution context ('this'):
14255 *
14256 *      .menuAim({
14257 *          // Function to call when a row is purposefully activated. Use this
14258 *          // to show a submenu's content for the activated row.
14259 *          activate: function() {},
14260 *
14261 *          // Function to call when a row is deactivated.
14262 *          deactivate: function() {},
14263 *
14264 *          // Function to call when mouse enters a menu row. Entering a row
14265 *          // does not mean the row has been activated, as the user may be
14266 *          // mousing over to a submenu.
14267 *          enter: function() {},
14268 *
14269 *          // Function to call when mouse exits a menu row.
14270 *          exit: function() {},
14271 *
14272 *          // Selector for identifying which elements in the menu are rows
14273 *          // that can trigger the above events. Defaults to "> li".
14274 *          rowSelector: "> li",
14275 *
14276 *          // You may have some menu rows that aren't submenus and therefore
14277 *          // shouldn't ever need to "activate." If so, filter submenu rows w/
14278 *          // this selector. Defaults to "*" (all elements).
14279 *          submenuSelector: "*",
14280 *
14281 *          // Direction the submenu opens relative to the main menu. Can be
14282 *          // left, right, above, or below. Defaults to "right".
14283 *          submenuDirection: "right"
14284 *      });
14285 *
14286 * https://github.com/kamens/jQuery-menu-aim
14287*/
14288(function($) {
14289
14290    $.fn.menuAim = function(opts) {
14291        // Initialize menu-aim for all elements in jQuery collection
14292        this.each(function() {
14293            init.call(this, opts);
14294        });
14295
14296        return this;
14297    };
14298
14299    function init(opts) {
14300        var $menu = $(this),
14301            activeRow = null,
14302            mouseLocs = [],
14303            lastDelayLoc = null,
14304            timeoutId = null,
14305            options = $.extend({
14306                rowSelector: "> li",
14307                submenuSelector: "*",
14308                submenuDirection: "right",
14309                tolerance: 75,  // bigger = more forgivey when entering submenu
14310                enter: $.noop,
14311                exit: $.noop,
14312                activate: $.noop,
14313                deactivate: $.noop,
14314                exitMenu: $.noop
14315            }, opts);
14316
14317        var MOUSE_LOCS_TRACKED = 3,  // number of past mouse locations to track
14318            DELAY = 300;  // ms delay when user appears to be entering submenu
14319
14320        /**
14321         * Keep track of the last few locations of the mouse.
14322         */
14323        var mousemoveDocument = function(e) {
14324                mouseLocs.push({x: e.pageX, y: e.pageY});
14325
14326                if (mouseLocs.length > MOUSE_LOCS_TRACKED) {
14327                    mouseLocs.shift();
14328                }
14329            };
14330
14331        /**
14332         * Cancel possible row activations when leaving the menu entirely
14333         */
14334        var mouseleaveMenu = function() {
14335                if (timeoutId) {
14336                    clearTimeout(timeoutId);
14337                }
14338
14339                // If exitMenu is supplied and returns true, deactivate the
14340                // currently active row on menu exit.
14341                if (options.exitMenu(this)) {
14342                    if (activeRow) {
14343                        options.deactivate(activeRow);
14344                    }
14345
14346                    activeRow = null;
14347                }
14348            };
14349
14350        /**
14351         * Trigger a possible row activation whenever entering a new row.
14352         */
14353        var mouseenterRow = function() {
14354                if (timeoutId) {
14355                    // Cancel any previous activation delays
14356                    clearTimeout(timeoutId);
14357                }
14358
14359                options.enter(this);
14360                possiblyActivate(this);
14361            },
14362            mouseleaveRow = function() {
14363                options.exit(this);
14364            };
14365
14366        /*
14367         * Immediately activate a row if the user clicks on it.
14368         */
14369        var clickRow = function() {
14370                activate(this);
14371            };
14372
14373        /**
14374         * Activate a menu row.
14375         */
14376        var activate = function(row) {
14377                if (row == activeRow) {
14378                    return;
14379                }
14380
14381                if (activeRow) {
14382                    options.deactivate(activeRow);
14383                }
14384
14385                options.activate(row);
14386                activeRow = row;
14387            };
14388
14389        /**
14390         * Possibly activate a menu row. If mouse movement indicates that we
14391         * shouldn't activate yet because user may be trying to enter
14392         * a submenu's content, then delay and check again later.
14393         */
14394        var possiblyActivate = function(row) {
14395                var delay = activationDelay();
14396
14397                if (delay) {
14398                    timeoutId = setTimeout(function() {
14399                        possiblyActivate(row);
14400                    }, delay);
14401                } else {
14402                    activate(row);
14403                }
14404            };
14405
14406        /**
14407         * Return the amount of time that should be used as a delay before the
14408         * currently hovered row is activated.
14409         *
14410         * Returns 0 if the activation should happen immediately. Otherwise,
14411         * returns the number of milliseconds that should be delayed before
14412         * checking again to see if the row should be activated.
14413         */
14414        var activationDelay = function() {
14415                if (!activeRow || !$(activeRow).is(options.submenuSelector)) {
14416                    // If there is no other submenu row already active, then
14417                    // go ahead and activate immediately.
14418                    return 0;
14419                }
14420
14421                var offset = $menu.offset(),
14422                    upperLeft = {
14423                        x: offset.left,
14424                        y: offset.top - options.tolerance
14425                    },
14426                    upperRight = {
14427                        x: offset.left + $menu.outerWidth(),
14428                        y: upperLeft.y
14429                    },
14430                    lowerLeft = {
14431                        x: offset.left,
14432                        y: offset.top + $menu.outerHeight() + options.tolerance
14433                    },
14434                    lowerRight = {
14435                        x: offset.left + $menu.outerWidth(),
14436                        y: lowerLeft.y
14437                    },
14438                    loc = mouseLocs[mouseLocs.length - 1],
14439                    prevLoc = mouseLocs[0];
14440
14441                if (!loc) {
14442                    return 0;
14443                }
14444
14445                if (!prevLoc) {
14446                    prevLoc = loc;
14447                }
14448
14449                if (prevLoc.x < offset.left || prevLoc.x > lowerRight.x ||
14450                    prevLoc.y < offset.top || prevLoc.y > lowerRight.y) {
14451                    // If the previous mouse location was outside of the entire
14452                    // menu's bounds, immediately activate.
14453                    return 0;
14454                }
14455
14456                if (lastDelayLoc &&
14457                        loc.x == lastDelayLoc.x && loc.y == lastDelayLoc.y) {
14458                    // If the mouse hasn't moved since the last time we checked
14459                    // for activation status, immediately activate.
14460                    return 0;
14461                }
14462
14463                // Detect if the user is moving towards the currently activated
14464                // submenu.
14465                //
14466                // If the mouse is heading relatively clearly towards
14467                // the submenu's content, we should wait and give the user more
14468                // time before activating a new row. If the mouse is heading
14469                // elsewhere, we can immediately activate a new row.
14470                //
14471                // We detect this by calculating the slope formed between the
14472                // current mouse location and the upper/lower right points of
14473                // the menu. We do the same for the previous mouse location.
14474                // If the current mouse location's slopes are
14475                // increasing/decreasing appropriately compared to the
14476                // previous's, we know the user is moving toward the submenu.
14477                //
14478                // Note that since the y-axis increases as the cursor moves
14479                // down the screen, we are looking for the slope between the
14480                // cursor and the upper right corner to decrease over time, not
14481                // increase (somewhat counterintuitively).
14482                function slope(a, b) {
14483                    return (b.y - a.y) / (b.x - a.x);
14484                };
14485
14486                var decreasingCorner = upperRight,
14487                    increasingCorner = lowerRight;
14488
14489                // Our expectations for decreasing or increasing slope values
14490                // depends on which direction the submenu opens relative to the
14491                // main menu. By default, if the menu opens on the right, we
14492                // expect the slope between the cursor and the upper right
14493                // corner to decrease over time, as explained above. If the
14494                // submenu opens in a different direction, we change our slope
14495                // expectations.
14496                if (options.submenuDirection == "left") {
14497                    decreasingCorner = lowerLeft;
14498                    increasingCorner = upperLeft;
14499                } else if (options.submenuDirection == "below") {
14500                    decreasingCorner = lowerRight;
14501                    increasingCorner = lowerLeft;
14502                } else if (options.submenuDirection == "above") {
14503                    decreasingCorner = upperLeft;
14504                    increasingCorner = upperRight;
14505                }
14506
14507                var decreasingSlope = slope(loc, decreasingCorner),
14508                    increasingSlope = slope(loc, increasingCorner),
14509                    prevDecreasingSlope = slope(prevLoc, decreasingCorner),
14510                    prevIncreasingSlope = slope(prevLoc, increasingCorner);
14511
14512                if (decreasingSlope < prevDecreasingSlope &&
14513                        increasingSlope > prevIncreasingSlope) {
14514                    // Mouse is moving from previous location towards the
14515                    // currently activated submenu. Delay before activating a
14516                    // new menu row, because user may be moving into submenu.
14517                    lastDelayLoc = loc;
14518                    return DELAY;
14519                }
14520
14521                lastDelayLoc = null;
14522                return 0;
14523            };
14524
14525        /**
14526         * Hook up initial menu events
14527         */
14528        $menu
14529            .mouseleave(mouseleaveMenu)
14530            .find(options.rowSelector)
14531                .mouseenter(mouseenterRow)
14532                .mouseleave(mouseleaveRow)
14533                .click(clickRow);
14534
14535        $(document).mousemove(mousemoveDocument);
14536
14537    };
14538})(jQuery);
14539
14540// Textarea and select clone() bug workaround | Spencer Tipping
14541// Licensed under the terms of the MIT source code license
14542
14543// Motivation.
14544// jQuery's clone() method works in most cases, but it fails to copy the value of textareas and select elements. This patch replaces jQuery's clone() method with a wrapper that fills in the
14545// values after the fact.
14546
14547// An interesting error case submitted by Piotr Przybyl: If two <select> options had the same value, the clone() method would select the wrong one in the cloned box. The fix, suggested by Piotr
14548// and implemented here, is to use the selectedIndex property on the <select> box itself rather than relying on jQuery's value-based val().
14549
14550(function (original) {
14551  jQuery.fn.clone = function () {
14552    var result           = original.apply(this, arguments),
14553        my_textareas     = this.find('textarea').add(this.filter('textarea')),
14554        result_textareas = result.find('textarea').add(result.filter('textarea')),
14555        my_selects       = this.find('select').add(this.filter('select')),
14556        result_selects   = result.find('select').add(result.filter('select'));
14557
14558    for (var i = 0, l = my_textareas.length; i < l; ++i) $(result_textareas[i]).val($(my_textareas[i]).val());
14559    for (var i = 0, l = my_selects.length;   i < l; ++i) {
14560      for (var j = 0, m = my_selects[i].options.length; j < m; ++j) {
14561        if (my_selects[i].options[j].selected === true) {
14562          result_selects[i].options[j].selected = true;
14563        }
14564      }
14565    }
14566    return result;
14567  };
14568}) (jQuery.fn.clone);
14569
14570// Generated by SDoc ;
14571//! moment.js
14572//! version : 2.18.1
14573//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
14574//! license : MIT
14575//! momentjs.com
14576!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return sd.apply(null,arguments)}function b(a){sd=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return null!=a&&"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a)return!1;return!0}function f(a){return void 0===a}
14576function g(a){return"number"==typeof a||"[object Number]"===Object.prototype.toString.call(a)}function h(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function i(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function j(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function k(a,b){for(var c in b)j(b,c)&&(a[c]=b[c]);return j(b,"toString")&&(a.toString=b.toString),j(b,"valueOf")&&(a.valueOf=b.valueOf),a}function l(a,b,c,d){return sb(a,b,c,d,!0).utc()}function m(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}}function n(a){return null==a._pf&&(a._pf=m()),a._pf}function o(a){if(null==a._isValid){var b=n(a),c=ud.call(b.parsedDateParts,function(a){return null!=a}),d=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c);if(a._strict&&(d=d&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour),null!=Object.isFrozen&&Object.isFrozen(a))return d;a._isValid=d}return a._isValid}function p(a){var b=l(NaN);return null!=a?k(n(b),a):n(b).userInvalidated=!0,b}function q(a,b){var c,d,e;if(f(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),f(b._i)||(a._i=b._i),f(b._f)||(a._f=b._f),f(b._l)||(a._l=b._l),f(b._strict)||(a._strict=b._strict),f(b._tzm)||(a._tzm=b._tzm),f(b._isUTC)||(a._isUTC=b._isUTC),f(b._offset)||(a._offset=b._offset),f(b._pf)||(a._pf=n(b)),f(b._locale)||(a._locale=b._locale),vd.length>0)for(c=0;c<vd.length;c++)d=vd[c],e=b[d],f(e)||(a[d]=e);return a}function r(b){q(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),wd===!1&&(wd=!0,a.updateOffset(this),wd=!1)}function s(a){return a instanceof r||null!=a&&null!=a._isAMomentObject}function t(a){return a<0?Math.ceil(a)||0:Math.floor(a)}function u(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=t(b)),c}function v(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;d<e;d++)(c&&a[d]!==b[d]||!c&&u(a[d])!==u(b[d]))&&g++;return g+f}function w(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function x(b,c){var d=!0;return k(function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,b),d){for(var e,f=[],g=0;g<arguments.length;g++){if(e="","object"==typeof arguments[g]){e+="\n["+g+"] ";for(var h in arguments[0])e+=h+": "+arguments[0][h]+", ";e=e.slice(0,-2)}else e=arguments[g];f.push(e)}w(b+"\nArguments: "+Array.prototype.slice.call(f).join("")+"\n"+(new Error).stack),d=!1}return c.apply(this,arguments)},c)}function y(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),xd[b]||(w(c),xd[b]=!0)}function z(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function A(a){var b,c;for(c in a)b=a[c],z(b)?this[c]=b:this["_"+c]=b;this._config=a,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)}function B(a,b){var c,e=k({},a);for(c in b)j(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},k(e[c],a[c]),k(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);
14576for(c in a)j(a,c)&&!j(b,c)&&d(a[c])&&(e[c]=k({},e[c]));return e}function C(a){null!=a&&this.set(a)}function D(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return z(d)?d.call(b,c):d}function E(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function F(){return this._invalidDate}function G(a){return this._ordinal.replace("%d",a)}function H(a,b,c,d){var e=this._relativeTime[c];return z(e)?e(a,b,c,d):e.replace(/%d/i,a)}function I(a,b){var c=this._relativeTime[a>0?"future":"past"];return z(c)?c(b):c.replace(/%s/i,b)}function J(a,b){var c=a.toLowerCase();Hd[c]=Hd[c+"s"]=Hd[b]=a}function K(a){return"string"==typeof a?Hd[a]||Hd[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)j(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(a,b){Id[a]=b}function N(a){var b=[];for(var c in a)b.push({unit:c,priority:Id[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function O(b,c){return function(d){return null!=d?(Q(this,b,d),a.updateOffset(this,c),this):P(this,b)}}function P(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function Q(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}function R(a){return a=K(a),z(this[a])?this[a]():this}function S(a,b){if("object"==typeof a){a=L(a);for(var c=N(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=K(a),z(this[a]))return this[a](b);return this}function T(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function U(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Md[a]=e),b&&(Md[b[0]]=function(){return T(e.apply(this,arguments),b[1],b[2])}),c&&(Md[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function V(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function W(a){var b,c,d=a.match(Jd);for(b=0,c=d.length;b<c;b++)Md[d[b]]?d[b]=Md[d[b]]:d[b]=V(d[b]);return function(b){var e,f="";for(e=0;e<c;e++)f+=z(d[e])?d[e].call(b,a):d[e];return f}}function X(a,b){return a.isValid()?(b=Y(b,a.localeData()),Ld[b]=Ld[b]||W(b),Ld[b](a)):a.localeData().invalidDate()}function Y(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Kd.lastIndex=0;d>=0&&Kd.test(a);)a=a.replace(Kd,c),Kd.lastIndex=0,d-=1;return a}function Z(a,b,c){ce[a]=z(b)?b:function(a,d){return a&&c?c:b}}function $(a,b){return j(ce,a)?ce[a](b._strict,b._locale):new RegExp(_(a))}function _(a){return aa(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function aa(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function ba(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),g(b)&&(d=function(a,c){c[b]=u(a)}),c=0;c<a.length;c++)de[a[c]]=d}function ca(a,b){ba(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function da(a,b,c){null!=b&&j(de,a)&&de[a](b,c._a,c,a)}function ea(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function fa(a,b){return a?c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||oe).test(b)?"format":"standalone"][a.month()]:c(this._months)?this._months:this._months.standalone}function ga(a,b){return a?c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[oe.test(b)?"format":"standalone"][a.month()]:c(this._monthsShort)?this._monthsShort:this._monthsShort.standalone}function ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;d<12;++d)f=l([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=ne.call(this._shortMonthsParse,g),e!==-1?e:null):(e=ne.call(this._longMonthsParse,g),e!==-1?e:null):"MMM"===b?(e=ne.call(this._shortMonthsParse,g),e!==-1?e:(e=ne.call(this._longMonthsParse,g),e!==-1?e:null)):(e=ne.call(this._longMonthsParse,g),e!==-1?e:(e=ne.call(this._shortMonthsParse,g),e!==-1?e:null))}function ia(a,b,c){var d,e,f;if(this._monthsParseExact)return ha.call(this,a,b,c);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;d<12;d++){if(e=l([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function ja(a,b){var c;if(!a.isValid())return a;
vendor: 7,975 bytes, line 14576
14576if("string"==typeof b)if(/^\d+$/.test(b))b=u(b);else if(b=a.localeData().monthsParse(b),!g(b))return a;return c=Math.min(a.date(),ea(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ka(b){return null!=b?(ja(this,b),a.updateOffset(this,!0),this):P(this,"Month")}function la(){return ea(this.year(),this.month())}function ma(a){return this._monthsParseExact?(j(this,"_monthsRegex")||oa.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(j(this,"_monthsShortRegex")||(this._monthsShortRegex=re),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function na(a){return this._monthsParseExact?(j(this,"_monthsRegex")||oa.call(this),a?this._monthsStrictRegex:this._monthsRegex):(j(this,"_monthsRegex")||(this._monthsRegex=se),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function oa(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;b<12;b++)c=l([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(d.sort(a),e.sort(a),f.sort(a),b=0;b<12;b++)d[b]=aa(d[b]),e[b]=aa(e[b]);for(b=0;b<24;b++)f[b]=aa(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}function pa(a){return qa(a)?366:365}function qa(a){return a%4===0&&a%100!==0||a%400===0}function ra(){return qa(this.year())}function sa(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return a<100&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function ta(a){var b=new Date(Date.UTC.apply(null,arguments));return a<100&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}function ua(a,b,c){var d=7+b-c,e=(7+ta(a,0,d).getUTCDay()-b)%7;return-e+d-1}function va(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ua(a,d,e),j=1+7*(b-1)+h+i;return j<=0?(f=a-1,g=pa(f)+j):j>pa(a)?(f=a+1,g=j-pa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function wa(a,b,c){var d,e,f=ua(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return g<1?(e=a.year()-1,d=g+xa(e,b,c)):g>xa(a.year(),b,c)?(d=g-xa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function xa(a,b,c){var d=ua(a,b,c),e=ua(a+1,b,c);return(pa(a)-d+e)/7}function ya(a){return wa(a,this._week.dow,this._week.doy).week}function za(){return this._week.dow}function Aa(){return this._week.doy}function Ba(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ca(a){var b=wa(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function Da(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Ea(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Fa(a,b){return a?c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]:c(this._weekdays)?this._weekdays:this._weekdays.standalone}function Ga(a){return a?this._weekdaysShort[a.day()]:this._weekdaysShort}function Ha(a){return a?this._weekdaysMin[a.day()]:this._weekdaysMin}function Ia(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;d<7;++d)f=l([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=ne.call(this._weekdaysParse,g),e!==-1?e:null):"ddd"===b?(e=ne.call(this._shortWeekdaysParse,g),e!==-1?e:null):(e=ne.call(this._minWeekdaysParse,g),e!==-1?e:null):"dddd"===b?(e=ne.call(this._weekdaysParse,g),e!==-1?e:(e=ne.call(this._shortWeekdaysParse,g),e!==-1?e:(e=ne.call(this._minWeekdaysParse,g),e!==-1?e:null))):"ddd"===b?(e=ne.call(this._shortWeekdaysParse,g),e!==-1?e:(e=ne.call(this._weekdaysParse,g),e!==-1?e:(e=ne.call(this._minWeekdaysParse,g),e!==-1?e:null))):(e=ne.call(this._minWeekdaysParse,g),e!==-1?e:(e=ne.call(this._weekdaysParse,g),e!==-1?e:(e=ne.call(this._shortWeekdaysParse,g),e!==-1?e:null)))}function Ja(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ia.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;d<7;d++){if(e=l([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Da(a,this.localeData()),this.add(a-b,"d")):b}function La(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Ma(a){if(!this.isValid())return null!=a?this:NaN;if(null!=a){var b=Ea(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Na(a){return this._weekdaysParseExact?(j(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(j(this,"_weekdaysRegex")||(this._weekdaysRegex=ye),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Oa(a){return this._weekdaysParseExact?(j(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(j(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=ze),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Pa(a){return this._weekdaysParseExact?(j(this,"_weekdaysRegex")||Qa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(j(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Ae),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Qa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],j=[];for(b=0;b<7;b++)c=l([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),j.push(d),j.push(e),j.push(f);for(g.sort(a),h.sort(a),i.sort(a),j.sort(a),b=0;b<7;b++)h[b]=aa(h[b]),i[b]=aa(i[b]),j[b]=aa(j[b]);this._weekdaysRegex=new RegExp("^("+j.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}function Ra(){return this.hours()%12||12}function Sa(){return this.hours()||24}function Ta(a,b){U(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Ua(a,b){return b._meridiemParse}function Va(a){return"p"===(a+"").toLowerCase().charAt(0)}function Wa(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Xa(a){return a?a.toLowerCase().replace("_","-"):a}function Ya(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Xa(a[f]).split("-"),b=e.length,c=Xa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Za(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&v(e,c,!0)>=b-1)break;b--}f++}return null}function Za(a){var b=null;if(!Fe[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Be._abbr,require("./locale/"+a),$a(b)}catch(a){}return Fe[a]}function $a(a,b){var c;
14576return a&&(c=f(b)?bb(a):_a(a,b),c&&(Be=c)),Be._abbr}function _a(a,b){if(null!==b){var c=Ee;if(b.abbr=a,null!=Fe[a])y("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=Fe[a]._config;else if(null!=b.parentLocale){if(null==Fe[b.parentLocale])return Ge[b.parentLocale]||(Ge[b.parentLocale]=[]),Ge[b.parentLocale].push({name:a,config:b}),null;c=Fe[b.parentLocale]._config}return Fe[a]=new C(B(c,b)),Ge[a]&&Ge[a].forEach(function(a){_a(a.name,a.config)}),$a(a),Fe[a]}return delete Fe[a],null}function ab(a,b){if(null!=b){var c,d=Ee;null!=Fe[a]&&(d=Fe[a]._config),b=B(d,b),c=new C(b),c.parentLocale=Fe[a],Fe[a]=c,$a(a)}else null!=Fe[a]&&(null!=Fe[a].parentLocale?Fe[a]=Fe[a].parentLocale:null!=Fe[a]&&delete Fe[a]);return Fe[a]}function bb(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Be;if(!c(a)){if(b=Za(a))return b;a=[a]}return Ya(a)}function cb(){return Ad(Fe)}function db(a){var b,c=a._a;return c&&n(a).overflow===-2&&(b=c[fe]<0||c[fe]>11?fe:c[ge]<1||c[ge]>
14576ea(c[ee],c[fe])?ge:c[he]<0||c[he]>24||24===c[he]&&(0!==c[ie]||0!==c[je]||0!==c[ke])?he:c[ie]<0||c[ie]>59?ie:c[je]<0||c[je]>59?je:c[ke]<0||c[ke]>999?ke:-1,n(a)._overflowDayOfYear&&(b<ee||b>ge)&&(b=ge),n(a)._overflowWeeks&&b===-1&&(b=le),n(a)._overflowWeekday&&b===-1&&(b=me),n(a).overflow=b),a}function eb(a){var b,c,d,e,f,g,h=a._i,i=He.exec(h)||Ie.exec(h);if(i){for(n(a).iso=!0,b=0,c=Ke.length;b<c;b++)if(Ke[b][1].exec(i[1])){e=Ke[b][0],d=Ke[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Le.length;b<c;b++)if(Le[b][1].exec(i[3])){f=(i[2]||" ")+Le[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!Je.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),lb(a)}else a._isValid=!1}function fb(a){var b,c,d,e,f,g,h,i,j={" GMT":" +0000"," EDT":" -0400"," EST":" -0500"," CDT":" -0500"," CST":" -0600"," MDT":" -0600"," MST":" -0700"," PDT":" -0700"," PST":" -0800"},k="YXWVUTSRQPONZABCDEFGHIKLM";if(b=a._i.replace(/\([^\)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s|\s$/g,""),c=Ne.exec(b)){if(d=c[1]?"ddd"+(5===c[1].length?", ":" "):"",e="D MMM "+(c[2].length>10?"YYYY ":"YY "),f="HH:mm"+(c[4]?":ss":""),c[1]){var l=new Date(c[2]),m=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][l.getDay()];if(c[1].substr(0,3)!==m)return n(a).weekdayMismatch=!0,void(a._isValid=!1)}switch(c[5].length){case 2:0===i?h=" +0000":(i=k.indexOf(c[5][1].toUpperCase())-12,h=(i<0?" -":" +")+(""+i).replace(/^-?/,"0").match(/..$/)[0]+"00");break;case 4:h=j[c[5]];break;default:h=j[" GMT"]}c[5]=h,a._i=c.splice(1).join(""),g=" ZZ",a._f=d+e+f+g,lb(a),n(a).rfc2822=!0}else a._isValid=!1}function gb(b){var c=Me.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(eb(b),void(b._isValid===!1&&(delete b._isValid,fb(b),b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b)))))}function hb(a,b,c){return null!=a?a:null!=b?b:c}function ib(b){var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}function jb(a){var b,c,d,e,f=[];if(!a._d){for(d=ib(a),a._w&&null==a._a[ge]&&null==a._a[fe]&&kb(a),null!=a._dayOfYear&&(e=hb(a._a[ee],d[ee]),(a._dayOfYear>pa(e)||0===a._dayOfYear)&&(n(a)._overflowDayOfYear=!0),c=ta(e,0,a._dayOfYear),a._a[fe]=c.getUTCMonth(),a._a[ge]=c.getUTCDate()),b=0;b<3&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;b<7;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[he]&&0===a._a[ie]&&0===a._a[je]&&0===a._a[ke]&&(a._nextDay=!0,a._a[he]=0),a._d=(a._useUTC?ta:sa).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[he]=24)}}function kb(a){var b,c,d,e,f,g,h,i;if(b=a._w,null!=b.GG||null!=b.W||null!=b.E)f=1,g=4,c=hb(b.GG,a._a[ee],wa(tb(),1,4).year),d=hb(b.W,1),e=hb(b.E,1),(e<1||e>7)&&(i=!0);else{f=a._locale._week.dow,g=a._locale._week.doy;var j=wa(tb(),f,g);c=hb(b.gg,a._a[ee],j.year),d=hb(b.w,j.week),null!=b.d?(e=b.d,(e<0||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f}d<1||d>xa(c,f,g)?n(a)._overflowWeeks=!0:null!=i?n(a)._overflowWeekday=!0:(h=va(c,d,e,f,g),a._a[ee]=h.year,a._dayOfYear=h.dayOfYear)}function lb(b){if(b._f===a.ISO_8601)return void eb(b);if(b._f===a.RFC_2822)return void fb(b);b._a=[],n(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=Y(b._f,b._locale).match(Jd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match($(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&n(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Md[f]?(d?n(b).empty=!1:n(b).unusedTokens.push(f),da(f,d,b)):b._strict&&!d&&n(b).unusedTokens.push(f);n(b).charsLeftOver=i-j,h.length>0&&n(b).unusedInput.push(h),b._a[he]<=12&&n(b).bigHour===!0&&b._a[he]>0&&(n(b).bigHour=void 0),n(b).parsedDateParts=b._a.slice(0),n(b).meridiem=b._meridiem,b._a[he]=mb(b._locale,b._a[he],b._meridiem),jb(b),db(b)}function mb(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&b<12&&(b+=12),d||12!==b||(b=0),b):b}function nb(a){var b,c,d,e,f;if(0===a._f.length)return n(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=q({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],lb(b),o(b)&&(f+=n(b).charsLeftOver,f+=10*n(b).unusedTokens.length,n(b).score=f,(null==d||f<d)&&(d=f,c=b));k(a,c||b)}function ob(a){if(!a._d){var b=L(a._i);a._a=i([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),jb(a)}}function pb(a){var b=new r(db(qb(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function qb(a){var b=a._i,d=a._f;return a._locale=a._locale||bb(a._l),null===b||void 0===d&&""===b?p({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),s(b)?new r(db(b)):(h(b)?a._d=b:c(d)?nb(a):d?lb(a):rb(a),o(a)||(a._d=null),a))}function rb(b){var e=b._i;f(e)?b._d=new Date(a.now()):h(e)?b._d=new Date(e.valueOf()):"string"==typeof e?gb(b):c(e)?(b._a=i(e.slice(0),function(a){return parseInt(a,10)}),jb(b)):d(e)?ob(b):g(e)?b._d=new Date(e):a.createFromInputFallback(b)}
14576function sb(a,b,f,g,h){var i={};return f!==!0&&f!==!1||(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,pb(i)}function tb(a,b,c,d){return sb(a,b,c,d,!1)}function ub(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return tb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d}function vb(){var a=[].slice.call(arguments,0);return ub("isBefore",a)}function wb(){var a=[].slice.call(arguments,0);return ub("isAfter",a)}function xb(a){for(var b in a)if(Re.indexOf(b)===-1||null!=a[b]&&isNaN(a[b]))return!1;for(var c=!1,d=0;d<Re.length;++d)if(a[Re[d]]){if(c)return!1;parseFloat(a[Re[d]])!==u(a[Re[d]])&&(c=!0)}return!0}function yb(){return this._isValid}function zb(){return Sb(NaN)}function Ab(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._isValid=xb(b),this._milliseconds=+k+1e3*j+6e4*i+1e3*h*60*60,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=bb(),this._bubble()}function Bb(a){return a instanceof Ab}function Cb(a){return a<0?Math.round(-1*a)*-1:Math.round(a)}function Db(a,b){U(a,0,0,function(){var a=this.utcOffset(),c="+";return a<0&&(a=-a,c="-"),c+T(~~(a/60),2)+b+T(~~a%60,2)})}function Eb(a,b){var c=(b||"").match(a);if(null===c)return null;var d=c[c.length-1]||[],e=(d+"").match(Se)||["-",0,0],f=+(60*e[1])+u(e[2]);return 0===f?0:"+"===e[0]?f:-f}function Fb(b,c){var d,e;return c._isUTC?(d=c.clone(),e=(s(b)||h(b)?b.valueOf():tb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):tb(b).local()}function Gb(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Hb(b,c,d){var e,f=this._offset||0;if(!this.isValid())return null!=b?this:NaN;if(null!=b){if("string"==typeof b){if(b=Eb(_d,b),null===b)return this}else Math.abs(b)<16&&!d&&(b=60*b);return!this._isUTC&&c&&(e=Gb(this)),this._offset=b,this._isUTC=!0,null!=e&&this.add(e,"m"),f!==b&&(!c||this._changeInProgress?Xb(this,Sb(b-f,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?f:Gb(this)}function Ib(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Jb(a){return this.utcOffset(0,a)}function Kb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Gb(this),"m")),this}function Lb(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var a=Eb($d,this._i);null!=a?this.utcOffset(a):this.utcOffset(0,!0)}return this}function Mb(a){return!!this.isValid()&&(a=a?tb(a).utcOffset():0,(this.utcOffset()-a)%60===0)}function Nb(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ob(){if(!f(this._isDSTShifted))return this._isDSTShifted;var a={};if(q(a,this),a=qb(a),a._a){var b=a._isUTC?l(a._a):tb(a._a);this._isDSTShifted=this.isValid()&&v(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Pb(){return!!this.isValid()&&!this._isUTC}function Qb(){return!!this.isValid()&&this._isUTC}function Rb(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Sb(a,b){var c,d,e,f=a,h=null;return Bb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:g(a)?(f={},b?f[b]=a:f.milliseconds=a):(h=Te.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:u(h[ge])*c,h:u(h[he])*c,m:u(h[ie])*c,s:u(h[je])*c,ms:u(Cb(1e3*h[ke]))*c}):(h=Ue.exec(a))?(c="-"===h[1]?-1:1,f={y:Tb(h[2],c),M:Tb(h[3],c),w:Tb(h[4],c),d:Tb(h[5],c),h:Tb(h[6],c),m:Tb(h[7],c),s:Tb(h[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Vb(tb(f.from),tb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new Ab(f),Bb(a)&&j(a,"_locale")&&(d._locale=a._locale),d}function Tb(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Ub(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Vb(a,b){var c;return a.isValid()&&b.isValid()?(b=Fb(b,a),a.isBefore(b)?c=Ub(a,b):(c=Ub(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function Wb(a,b){return function(c,d){var e,f;
14576return null===d||isNaN(+d)||(y(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Sb(c,d),Xb(this,e,a),this}}function Xb(b,c,d,e){var f=c._milliseconds,g=Cb(c._days),h=Cb(c._months);b.isValid()&&(e=null==e||e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&Q(b,"Date",P(b,"Date")+g*d),h&&ja(b,P(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Yb(a,b){var c=a.diff(b,"days",!0);return c<-6?"sameElse":c<-1?"lastWeek":c<0?"lastDay":c<1?"sameDay":c<2?"nextDay":c<7?"nextWeek":"sameElse"}function Zb(b,c){var d=b||tb(),e=Fb(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(z(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,tb(d)))}function $b(){return new r(this)}function _b(a,b){var c=s(a)?a:tb(a);return!(!this.isValid()||!c.isValid())&&(b=K(f(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf())}function ac(a,b){var c=s(a)?a:tb(a);return!(!this.isValid()||!c.isValid())&&(b=K(f(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf())}function bc(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function cc(a,b){var c,d=s(a)?a:tb(a);return!(!this.isValid()||!d.isValid())&&(b=K(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf()))}function dc(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function ec(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function fc(a,b,c){var d,e,f,g;return this.isValid()?(d=Fb(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=gc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:t(g)):NaN):NaN}function gc(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return b-f<0?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function hc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ic(){if(!this.isValid())return null;var a=this.clone().utc();return a.year()<0||a.year()>9999?X(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):z(Date.prototype.toISOString)?this.toDate().toISOString():X(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function jc(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var a="moment",b="";this.isLocal()||(a=0===this.utcOffset()?"moment.utc":"moment.parseZone",b="Z");var c="["+a+'("]',d=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",e="-MM-DD[T]HH:mm:ss.SSS",f=b+'[")]';return this.format(c+d+e+f)}function kc(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=X(this,b);return this.localeData().postformat(c)}function lc(a,b){return this.isValid()&&(s(a)&&a.isValid()||tb(a).isValid())?Sb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function mc(a){return this.from(tb(),a)}function nc(a,b){return this.isValid()&&(s(a)&&a.isValid()||tb(a).isValid())?Sb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function oc(a){return this.to(tb(),a)}function pc(a){var b;return void 0===a?this._locale._abbr:(b=bb(a),null!=b&&(this._locale=b),this)}function qc(){return this._locale}function rc(a){switch(a=K(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function sc(a){return a=K(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function tc(){return this._d.valueOf()-6e4*(this._offset||0)}function uc(){return Math.floor(this.valueOf()/1e3)}function vc(){return new Date(this.valueOf())}function wc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function xc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function yc(){return this.isValid()?this.toISOString():null}function zc(){return o(this)}function Ac(){
14577return k({},n(this))}function Bc(){return n(this).overflow}function Cc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Dc(a,b){U(0,[a,a.length],0,b)}function Ec(a){return Ic.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Fc(a){return Ic.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Gc(){return xa(this.year(),1,4)}function Hc(){var a=this.localeData()._week;return xa(this.year(),a.dow,a.doy)}function Ic(a,b,c,d,e){var f;return null==a?wa(this,d,e).year:(f=xa(a,d,e),b>f&&(b=f),Jc.call(this,a,b,c,d,e))}
14577function Jc(a,b,c,d,e){var f=va(a,b,c,d,e),g=ta(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}function Kc(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Lc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Mc(a,b){b[ke]=u(1e3*("0."+a))}function Nc(){return this._isUTC?"UTC":""}function Oc(){return this._isUTC?"Coordinated Universal Time":""}function Pc(a){return tb(1e3*a)}function Qc(){return tb.apply(null,arguments).parseZone()}function Rc(a){return a}function Sc(a,b,c,d){var e=bb(),f=l().set(d,b);return e[c](f,a)}function Tc(a,b,c){if(g(a)&&(b=a,a=void 0),a=a||"",null!=b)return Sc(a,b,c,"month");var d,e=[];for(d=0;d<12;d++)e[d]=Sc(a,d,c,"month");return e}function Uc(a,b,c,d){"boolean"==typeof a?(g(b)&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,g(b)&&(c=b,b=void 0),b=b||"");var e=bb(),f=a?e._week.dow:0;if(null!=c)return Sc(b,(c+f)%7,d,"day");var h,i=[];for(h=0;h<7;h++)i[h]=Sc(b,(h+f)%7,d,"day");return i}function Vc(a,b){return Tc(a,b,"months")}function Wc(a,b){return Tc(a,b,"monthsShort")}function Xc(a,b,c){return Uc(a,b,c,"weekdays")}function Yc(a,b,c){return Uc(a,b,c,"weekdaysShort")}function Zc(a,b,c){return Uc(a,b,c,"weekdaysMin")}function $c(){var a=this._data;return this._milliseconds=df(this._milliseconds),this._days=df(this._days),this._months=df(this._months),a.milliseconds=df(a.milliseconds),a.seconds=df(a.seconds),a.minutes=df(a.minutes),a.hours=df(a.hours),a.months=df(a.months),a.years=df(a.years),this}function _c(a,b,c,d){var e=Sb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function ad(a,b){return _c(this,a,b,1)}function bd(a,b){return _c(this,a,b,-1)}function cd(a){return a<0?Math.floor(a):Math.ceil(a)}function dd(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||f<=0&&g<=0&&h<=0||(f+=864e5*cd(fd(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=t(f/1e3),i.seconds=a%60,b=t(a/60),i.minutes=b%60,c=t(b/60),i.hours=c%24,g+=t(c/24),e=t(ed(g)),h+=e,g-=cd(fd(e)),d=t(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function ed(a){return 4800*a/146097}function fd(a){return 146097*a/4800}function gd(a){if(!this.isValid())return NaN;var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+ed(b),"month"===a?c:c/12;switch(b=this._days+Math.round(fd(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function hd(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*u(this._months/12):NaN}function id(a){return function(){return this.as(a)}}function jd(a){return a=K(a),this.isValid()?this[a+"s"]():NaN}function kd(a){return function(){return this.isValid()?this._data[a]:NaN}}function ld(){return t(this.days()/7)}function md(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function nd(a,b,c){var d=Sb(a).abs(),e=uf(d.as("s")),f=uf(d.as("m")),g=uf(d.as("h")),h=uf(d.as("d")),i=uf(d.as("M")),j=uf(d.as("y")),k=e<=vf.ss&&["s",e]||e<vf.s&&["ss",e]||f<=1&&["m"]||f<vf.m&&["mm",f]||g<=1&&["h"]||g<vf.h&&["hh",g]||h<=1&&["d"]||h<vf.d&&["dd",h]||i<=1&&["M"]||i<vf.M&&["MM",i]||j<=1&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,md.apply(null,k)}function od(a){return void 0===a?uf:"function"==typeof a&&(uf=a,!0)}function pd(a,b){return void 0!==vf[a]&&(void 0===b?vf[a]:(vf[a]=b,"s"===a&&(vf.ss=b-1),!0))}function qd(a){if(!this.isValid())return this.localeData().invalidDate();var b=this.localeData(),c=nd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function rd(){if(!this.isValid())return this.localeData().invalidDate();var a,b,c,d=wf(this._milliseconds)/1e3,e=wf(this._days),f=wf(this._months);a=t(d/60),b=t(a/60),d%=60,a%=60,c=t(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(m<0?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var sd,td;td=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;d<c;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};var ud=td,vd=a.momentProperties=[],wd=!1,xd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var yd;yd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)j(a,b)&&c.push(b);return c};var zd,Ad=yd,Bd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Cd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Dd="Invalid date",Ed="%d",Fd=/\d{1,2}/,Gd={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Hd={},Id={},Jd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}
vendor: 11,591 bytes, line 14577
14577|x|X|zz?|ZZ?|.)/g,Kd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ld={},Md={},Nd=/\d/,Od=/\d\d/,Pd=/\d{3}/,Qd=/\d{4}/,Rd=/[+-]?\d{6}/,Sd=/\d\d?/,Td=/\d\d\d\d?/,Ud=/\d\d\d\d\d\d?/,Vd=/\d{1,3}/,Wd=/\d{1,4}/,Xd=/[+-]?\d{1,6}/,Yd=/\d+/,Zd=/[+-]?\d+/,$d=/Z|[+-]\d\d:?\d\d/gi,_d=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[+-]?\d+(\.\d{1,3})?/,be=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,ce={},de={},ee=0,fe=1,ge=2,he=3,ie=4,je=5,ke=6,le=7,me=8;zd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1};var ne=zd;U("M",["MM",2],"Mo",function(){return this.month()+1}),U("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),U("MMMM",0,0,function(a){return this.localeData().months(this,a)}),J("month","M"),M("month",8),Z("M",Sd),Z("MM",Sd,Od),Z("MMM",function(a,b){return b.monthsShortRegex(a)}),Z("MMMM",function(a,b){return b.monthsRegex(a)}),ba(["M","MM"],function(a,b){b[fe]=u(a)-1}),ba(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[fe]=e:n(c).invalidMonth=a});var oe=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,pe="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),qe="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),re=be,se=be;U("Y",0,0,function(){var a=this.year();return a<=9999?""+a:"+"+a}),U(0,["YY",2],0,function(){return this.year()%100}),U(0,["YYYY",4],0,"year"),U(0,["YYYYY",5],0,"year"),U(0,["YYYYYY",6,!0],0,"year"),J("year","y"),M("year",1),Z("Y",Zd),Z("YY",Sd,Od),Z("YYYY",Wd,Qd),Z("YYYYY",Xd,Rd),Z("YYYYYY",Xd,Rd),ba(["YYYYY","YYYYYY"],ee),ba("YYYY",function(b,c){c[ee]=2===b.length?a.parseTwoDigitYear(b):u(b)}),ba("YY",function(b,c){c[ee]=a.parseTwoDigitYear(b)}),ba("Y",function(a,b){b[ee]=parseInt(a,10)}),a.parseTwoDigitYear=function(a){return u(a)+(u(a)>68?1900:2e3)};var te=O("FullYear",!0);U("w",["ww",2],"wo","week"),U("W",["WW",2],"Wo","isoWeek"),J("week","w"),J("isoWeek","W"),M("week",5),M("isoWeek",5),Z("w",Sd),Z("ww",Sd,Od),Z("W",Sd),Z("WW",Sd,Od),ca(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=u(a)});var ue={dow:0,doy:6};U("d",0,"do","day"),U("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),U("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),U("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),U("e",0,0,"weekday"),U("E",0,0,"isoWeekday"),J("day","d"),J("weekday","e"),J("isoWeekday","E"),M("day",11),M("weekday",11),M("isoWeekday",11),Z("d",Sd),Z("e",Sd),Z("E",Sd),Z("dd",function(a,b){return b.weekdaysMinRegex(a)}),Z("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Z("dddd",function(a,b){return b.weekdaysRegex(a)}),ca(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);null!=e?b.d=e:n(c).invalidWeekday=a}),ca(["d","e","E"],function(a,b,c,d){b[d]=u(a)});var ve="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),we="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),ye=be,ze=be,Ae=be;U("H",["HH",2],0,"hour"),U("h",["hh",2],0,Ra),U("k",["kk",2],0,Sa),U("hmm",0,0,function(){return""+Ra.apply(this)+T(this.minutes(),2)}),U("hmmss",0,0,function(){return""+Ra.apply(this)+T(this.minutes(),2)+T(this.seconds(),2)}),U("Hmm",0,0,function(){return""+this.hours()+T(this.minutes(),2)}),U("Hmmss",0,0,function(){return""+this.hours()+T(this.minutes(),2)+T(this.seconds(),2)}),Ta("a",!0),Ta("A",!1),J("hour","h"),M("hour",13),Z("a",Ua),Z("A",Ua),Z("H",Sd),Z("h",Sd),Z("k",Sd),Z("HH",Sd,Od),Z("hh",Sd,Od),Z("kk",Sd,Od),Z("hmm",Td),Z("hmmss",Ud),Z("Hmm",Td),Z("Hmmss",Ud),ba(["H","HH"],he),ba(["k","kk"],function(a,b,c){var d=u(a);b[he]=24===d?0:d}),ba(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),ba(["h","hh"],function(a,b,c){b[he]=u(a),n(c).bigHour=!0}),ba("hmm",function(a,b,c){var d=a.length-2;b[he]=u(a.substr(0,d)),b[ie]=u(a.substr(d)),n(c).bigHour=!0}),ba("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[he]=u(a.substr(0,d)),b[ie]=u(a.substr(d,2)),b[je]=u(a.substr(e)),n(c).bigHour=!0}),ba("Hmm",function(a,b,c){var d=a.length-2;b[he]=u(a.substr(0,d)),b[ie]=u(a.substr(d))}),ba("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[he]=u(a.substr(0,d)),b[ie]=u(a.substr(d,2)),b[je]=u(a.substr(e))});var Be,Ce=/[ap]\.?m?\.?/i,De=O("Hours",!0),Ee={calendar:Bd,longDateFormat:Cd,invalidDate:Dd,ordinal:Ed,dayOfMonthOrdinalParse:Fd,relativeTime:Gd,months:pe,monthsShort:qe,week:ue,weekdays:ve,weekdaysMin:xe,weekdaysShort:we,meridiemParse:Ce},Fe={},Ge={},He=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ie=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Je=/Z|[+-]\d\d(?::?\d\d)?/,Ke=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Le=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Me=/^\/?Date\((\-?\d+)/i,Ne=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;a.createFromInputFallback=x("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),a.ISO_8601=function(){},a.RFC_2822=function(){};var Oe=x("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=tb.apply(null,arguments);return this.isValid()&&a.isValid()?a<this?this:a:p()}),Pe=x("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=tb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:p()}),Qe=function(){return Date.now?Date.now():+new Date},Re=["year","quarter","month","week","day","hour","minute","second","millisecond"];Db("Z",":"),Db("ZZ",""),Z("Z",_d),Z("ZZ",_d),ba(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Eb(_d,a)});var Se=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var Te=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ue=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Sb.fn=Ab.prototype,Sb.invalid=zb;var Ve=Wb(1,"add"),We=Wb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xe=x("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});U(0,["gg",2],0,function(){return this.weekYear()%100}),U(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Dc("gggg","weekYear"),Dc("ggggg","weekYear"),Dc("GGGG","isoWeekYear"),Dc("GGGGG","isoWeekYear"),J("weekYear","gg"),J("isoWeekYear","GG"),M("weekYear",1),M("isoWeekYear",1),Z("G",Zd),Z("g",Zd),Z("GG",Sd,Od),Z("gg",Sd,Od),Z("GGGG",Wd,Qd),Z("gggg",Wd,Qd),Z("GGGGG",Xd,Rd),Z("ggggg",Xd,Rd),ca(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=u(a)}),ca(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),U("Q",0,"Qo","quarter"),J("quarter","Q"),M("quarter",7),Z("Q",Nd),ba("Q",function(a,b){b[fe]=3*(u(a)-1)}),U("D",["DD",2],"Do","date"),J("date","D"),M("date",9),Z("D",Sd),Z("DD",Sd,Od),Z("Do",function(a,b){return a?b._dayOfMonthOrdinalParse||b._ordinalParse:b._dayOfMonthOrdinalParseLenient}),ba(["D","DD"],ge),ba("Do",function(a,b){b[ge]=u(a.match(Sd)[0],10)});var Ye=O("Date",!0);U("DDD",["DDDD",3],"DDDo","dayOfYear"),J("dayOfYear","DDD"),M("dayOfYear",4),Z("DDD",Vd),Z("DDDD",Pd),ba(["DDD","DDDD"],function(a,b,c){c._dayOfYear=u(a)}),U("m",["mm",2],0,"minute"),J("minute","m"),M("minute",14),Z("m",Sd),Z("mm",Sd,Od),ba(["m","mm"],ie);var Ze=O("Minutes",!1);U("s",["ss",2],0,"second"),J("second","s"),M("second",15),Z("s",Sd),Z("ss",Sd,Od),ba(["s","ss"],je);var $e=O("Seconds",!1);U("S",0,0,function(){return~~(this.millisecond()/100)}),U(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),U(0,["SSS",3],0,"millisecond"),U(0,["SSSS",4],0,function(){return 10*this.millisecond()}),U(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),U(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),U(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),U(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),U(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),J("millisecond","ms"),M("millisecond",16),Z("S",Vd,Nd),Z("SS",Vd,Od),Z("SSS",Vd,Pd);var _e;for(_e="SSSS";_e.length<=9;_e+="S")Z(_e,Yd);for(_e="S";_e.length<=9;_e+="S")ba(_e,Mc);var af=O("Milliseconds",!1);U("z",0,0,"zoneAbbr"),U("zz",0,0,"zoneName");var bf=r.prototype;bf.add=Ve,bf.calendar=Zb,bf.clone=$b,bf.diff=fc,bf.endOf=sc,bf.format=kc,bf.from=lc,bf.fromNow=mc,bf.to=nc,bf.toNow=oc,bf.get=R,bf.invalidAt=Bc,bf.isAfter=_b,bf.isBefore=ac,bf.isBetween=bc,bf.isSame=cc,bf.isSameOrAfter=dc,bf.isSameOrBefore=ec,bf.isValid=zc,bf.lang=Xe,bf.locale=pc,bf.localeData=qc,bf.max=Pe,bf.min=Oe,bf.parsingFlags=Ac,bf.set=S,bf.startOf=rc,bf.subtract=We,bf.toArray=wc,bf.toObject=xc,bf.toDate=vc,bf.toISOString=ic,bf.inspect=jc,bf.toJSON=yc,bf.toString=hc,bf.unix=uc,bf.valueOf=tc,bf.creationData=Cc,bf.year=te,bf.isLeapYear=ra,bf.weekYear=Ec,bf.isoWeekYear=Fc,bf.quarter=bf.quarters=Kc,bf.month=ka,bf.daysInMonth=la,bf.week=bf.weeks=Ba,bf.isoWeek=bf.isoWeeks=Ca,bf.weeksInYear=Hc,bf.isoWeeksInYear=Gc,bf.date=Ye,bf.day=bf.days=Ka,bf.weekday=La,bf.isoWeekday=Ma,bf.dayOfYear=Lc,bf.hour=bf.hours=De,bf.minute=bf.minutes=Ze,bf.second=bf.seconds=$e,bf.millisecond=bf.milliseconds=af,bf.utcOffset=Hb,bf.utc=Jb,bf.local=Kb,bf.parseZone=Lb,bf.hasAlignedHourOffset=Mb,bf.isDST=Nb,bf.isLocal=Pb,bf.isUtcOffset=Qb,bf.isUtc=Rb,bf.isUTC=Rb,bf.zoneAbbr=Nc,bf.zoneName=Oc,bf.dates=x("dates accessor is deprecated. Use date instead.",Ye),bf.months=x("months accessor is deprecated. Use month instead",ka),bf.years=x("years accessor is deprecated. Use year instead",te),bf.zone=x("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Ib),bf.isDSTShifted=x("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ob);var cf=C.prototype;cf.calendar=D,cf.longDateFormat=E,cf.invalidDate=F,cf.ordinal=G,cf.preparse=Rc,cf.postformat=Rc,cf.relativeTime=H,cf.pastFuture=I,cf.set=A,cf.months=fa,cf.monthsShort=ga,cf.monthsParse=ia,cf.monthsRegex=na,cf.monthsShortRegex=ma,cf.week=ya,cf.firstDayOfYear=Aa,cf.firstDayOfWeek=za,cf.weekdays=Fa,cf.weekdaysMin=Ha,cf.weekdaysShort=Ga,cf.weekdaysParse=Ja,cf.weekdaysRegex=Na,cf.weekdaysShortRegex=Oa,cf.weekdaysMinRegex=Pa,cf.isPM=Va,cf.meri
14577diem=Wa,$a("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===u(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=x("moment.lang is deprecated. Use moment.locale instead.",$a),a.langData=x("moment.langData is deprecated. Use moment.localeData instead.",bb);var df=Math.abs,ef=id("ms"),ff=id("s"),gf=id("m"),hf=id("h"),jf=id("d"),kf=id("w"),lf=id("M"),mf=id("y"),nf=kd("milliseconds"),of=kd("seconds"),pf=kd("minutes"),qf=kd("hours"),rf=kd("days"),sf=kd("months"),tf=kd("years"),uf=Math.round,vf={ss:44,s:45,m:45,h:22,d:26,M:11},wf=Math.abs,xf=Ab.prototype;return xf.isValid=yb,xf.abs=$c,xf.add=ad,xf.subtract=bd,xf.as=gd,xf.asMilliseconds=ef,xf.asSeconds=ff,xf.asMinutes=gf,xf.asHours=hf,xf.asDays=jf,xf.asWeeks=kf,xf.asMonths=lf,xf.asYears=mf,xf.valueOf=hd,xf._bubble=dd,xf.get=jd,xf.milliseconds=nf,xf.seconds=of,xf.minutes=pf,xf.hours=qf,xf.days=rf,xf.weeks=ld,xf.months=sf,xf.years=tf,xf.humanize=qd,xf.toISOString=rd,xf.toString=rd,xf.toJSON=rd,xf.locale=pc,xf.localeData=qc,xf.toIsoString=x("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",rd),xf.lang=Xe,U("X",0,0,"unix"),U("x",0,0,"valueOf"),Z("x",Zd),Z("X",ae),ba("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),ba("x",function(a,b,c){c._d=new Date(u(a))}),a.version="2.18.1",b(tb),a.fn=bf,a.min=vb,a.max=wb,a.now=Qe,a.utc=l,a.unix=Pc,a.months=Vc,a.isDate=h,a.locale=$a,a.invalid=p,a.duration=Sb,a.isMoment=s,a.weekdays=Xc,a.parseZone=Qc,a.localeData=bb,a.isDuration=Bb,a.monthsShort=Wc,a.weekdaysMin=Zc,a.defineLocale=_a,a.updateLocale=ab,a.locales=cb,a.weekdaysShort=Yc,a.normalizeUnits=K,a.relativeTimeRounding=od,a.relativeTimeThreshold=pd,a.calendarFormat=Yb,a.prototype=bf,a});
14578//! moment.js locale configuration
14579//! locale : catalan (ca)
14580//! author : Juan G. Hurtado : https://github.com/juanghurtado
14581
14582(function (global, factory) {
14583   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
14584   typeof define === 'function' && define.amd ? define(['moment'], factory) :
14585   factory(global.moment)
14586}(this, function (moment) { 'use strict';
14587
14588
14589    var ca = moment.defineLocale('ca', {
14590        months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
14591        monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
14592        weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
14593        weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
14594        weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
14595        longDateFormat : {
14596            LT : 'H:mm',
14597            LTS : 'LT:ss',
14598            L : 'DD/MM/YYYY',
14599            LL : 'D MMMM YYYY',
14600            LLL : 'D MMMM YYYY LT',
14601            LLLL : 'dddd D MMMM YYYY LT'
14602        },
14603        calendar : {
14604            sameDay : function () {
14605                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
14606            },
14607            nextDay : function () {
14608                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
14609            },
14610            nextWeek : function () {
14611                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
14612            },
14613            lastDay : function () {
14614                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
14615            },
14616            lastWeek : function () {
14617                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
14618            },
14619            sameElse : 'L'
14620        },
14621        relativeTime : {
14622            future : 'en %s',
14623            past : 'fa %s',
14624            s : 'uns segons',
14625            m : 'un minut',
14626            mm : '%d minuts',
14627            h : 'una hora',
14628            hh : '%d hores',
14629            d : 'un dia',
14630            dd : '%d dies',
14631            M : 'un mes',
14632            MM : '%d mesos',
14633            y : 'un any',
14634            yy : '%d anys'
14635        },
14636        ordinalParse: /\d{1,2}(r|n|t|è|a)/,
14637        ordinal : function (number, period) {
14638            var output = (number === 1) ? 'r' :
14639                (number === 2) ? 'n' :
14640                (number === 3) ? 'r' :
14641                (number === 4) ? 't' : 'è';
14642            if (period === 'w' || period === 'W') {
14643                output = 'a';
14644            }
14645            return number + output;
14646        },
14647        week : {
14648            dow : 1, // Monday is the first day of the week.
14649            doy : 4  // The week that contains Jan 4th is the first week of the year.
14650        }
14651    });
14652
14653    return ca;
14654
14655}));
14656//! moment.js locale configuration
14657//! locale : spanish (es)
14658//! author : Julio Napurí : https://github.com/julionc
14659
14660(function (global, factory) {
14661   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
14662   typeof define === 'function' && define.amd ? define(['moment'], factory) :
14663   factory(global.moment)
14664}(this, function (moment) { 'use strict';
14665
14666
14667    var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'),
14668        monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
14669
14670    var es = moment.defineLocale('es', {
14671        months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
14672        monthsShort : function (m, format) {
14673            if (/-MMM-/.test(format)) {
14674                return monthsShort[m.month()];
14675            } else {
14676                return monthsShortDot[m.month()];
14677            }
14678        },
14679        weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
14680        weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
14681        weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'),
14682        longDateFormat : {
14683            LT : 'H:mm',
14684            LTS : 'LT:ss',
14685            L : 'DD/MM/YYYY',
14686            LL : 'D [de] MMMM [de] YYYY',
14687            LLL : 'D [de] MMMM [de] YYYY LT',
14688            LLLL : 'dddd, D [de] MMMM [de] YYYY LT'
14689        },
14690        calendar : {
14691            sameDay : function () {
14692                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
14693            },
14694            nextDay : function () {
14695                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
14696            },
14697            nextWeek : function () {
14698                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
14699            },
14700            lastDay : function () {
14701                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
14702            },
14703            lastWeek : function () {
14704                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
14705            },
14706            sameElse : 'L'
14707        },
14708        relativeTime : {
14709            future : 'en %s',
14710            past : 'hace %s',
14711            s : 'unos segundos',
14712            m : 'un minuto',
14713            mm : '%d minutos',
14714            h : 'una hora',
14715            hh : '%d horas',
14716            d : 'un día',
14717            dd : '%d días',
14718            M : 'un mes',
14719            MM : '%d meses',
14720            y : 'un año',
14721            yy : '%d años'
14722        },
14723        ordinalParse : /\d{1,2}º/,
14724        ordinal : '%dº',
14725        week : {
14726            dow : 1, // Monday is the first day of the week.
14727            doy : 4  // The week that contains Jan 4th is the first week of the year.
14728        }
14729    });
14730
14731    return es;
14732
14733}));
14734//! moment.js locale configuration
14735//! locale : Basque [eu]
14736//! author : Eneko Illarramendi : https://github.com/eillarra
14737
14738;(function (global, factory) {
14739   typeof exports === 'object' && typeof module !== 'undefined'
14740       && typeof require === 'function' ? factory(require('../moment')) :
14741   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
14742   factory(global.moment)
14743}(this, (function (moment) { 'use strict';
14744
14745
14746var eu = moment.defineLocale('eu', {
14747    months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
14748    monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
14749    monthsParseExact : true,
14750    weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
14751    weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
14752    weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
14753    weekdaysParseExact : true,
14754    longDateFormat : {
14755        LT : 'HH:mm',
14756        LTS : 'HH:mm:ss',
14757        L : 'YYYY-MM-DD',
14758        LL : 'YYYY[ko] MMMM[ren] D[a]',
14759        LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
14760        LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
14761        l : 'YYYY-M-D',
14762        ll : 'YYYY[ko] MMM D[a]',
14763        lll : 'YYYY[ko] MMM D[a] HH:mm',
14764        llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
14765    },
14766    calendar : {
14767        sameDay : '[gaur] LT[etan]',
14768        nextDay : '[bihar] LT[etan]',
14769        nextWeek : 'dddd LT[etan]',
14770        lastDay : '[atzo] LT[etan]',
14771        lastWeek : '[aurreko] dddd LT[etan]',
14772        sameElse : 'L'
14773    },
14774    relativeTime : {
14775        future : '%s barru',
14776        past : 'duela %s',
14777        s : 'segundo batzuk',
14778        ss : '%d segundo',
14779        m : 'minutu bat',
14780        mm : '%d minutu',
14781        h : 'ordu bat',
14782        hh : '%d ordu',
14783        d : 'egun bat',
14784        dd : '%d egun',
14785        M : 'hilabete bat',
14786        MM : '%d hilabete',
14787        y : 'urte bat',
14788        yy : '%d urte'
14789    },
14790    dayOfMonthOrdinalParse: /\d{1,2}\./,
14791    ordinal : '%d.',
14792    week : {
14793        dow : 1, // Monday is the first day of the week.
14794        doy : 7  // The week that contains Jan 1st is the first week of the year.
14795    }
14796});
14797
14798return eu;
14799
14800})));
14801//! moment.js locale configuration
14802//! locale : galician (gl)
14803//! author : Juan G. Hurtado : https://github.com/juanghurtado
14804
14805(function (global, factory) {
14806   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
14807   typeof define === 'function' && define.amd ? define(['moment'], factory) :
14808   factory(global.moment)
14809}(this, function (moment) { 'use strict';
14810
14811
14812    var gl = moment.defineLocale('gl', {
14813        months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'),
14814        monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'),
14815        weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'),
14816        weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'),
14817        weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'),
14818        longDateFormat : {
14819            LT : 'H:mm',
14820            LTS : 'LT:ss',
14821            L : 'DD/MM/YYYY',
14822            LL : 'D MMMM YYYY',
14823            LLL : 'D MMMM YYYY LT',
14824            LLLL : 'dddd D MMMM YYYY LT'
14825        },
14826        calendar : {
14827            sameDay : function () {
14828                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
14829            },
14830            nextDay : function () {
14831                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
14832            },
14833            nextWeek : function () {
14834                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
14835            },
14836            lastDay : function () {
14837                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
14838            },
14839            lastWeek : function () {
14840                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
14841            },
14842            sameElse : 'L'
14843        },
14844        relativeTime : {
14845            future : function (str) {
14846                if (str === 'uns segundos') {
14847                    return 'nuns segundos';
14848                }
14849                return 'en ' + str;
14850            },
14851            past : 'hai %s',
14852            s : 'uns segundos',
14853            m : 'un minuto',
14854            mm : '%d minutos',
14855            h : 'unha hora',
14856            hh : '%d horas',
14857            d : 'un día',
14858            dd : '%d días',
14859            M : 'un mes',
14860            MM : '%d meses',
14861            y : 'un ano',
14862            yy : '%d anos'
14863        },
14864        ordinalParse : /\d{1,2}º/,
14865        ordinal : '%dº',
14866        week : {
14867            dow : 1, // Monday is the first day of the week.
14868            doy : 7  // The week that contains Jan 1st is the first week of the year.
14869        }
14870    });
14871
14872    return gl;
14873
14874}));
14875/*
14876 *
14877 * Copyright (c) 2006-2014 Sam Collett (http://www.texotela.co.uk)
14878 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
14879 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
14880 *
14881 * Version 1.4.1
14882 * Demo: http://www.texotela.co.uk/code/jquery/numeric/
14883 *
14884 */
14885(function(factory){if(typeof define === 'function' && define.amd){define(['jquery'], factory);}else{factory(window.jQuery);}}(function($){$.fn.numeric=function(config,callback){if(typeof config==="boolean"){config={decimal:config,negative:true,decimalPlaces:-1}}config=config||{};if(typeof config.negative=="undefined"){config.negative=true}var decimal=config.decimal===false?"":config.decimal||".";var altDecimal=config.altDecimal===false?"": config.altDecimal||decimal;var negative=config.negative===true?true:false;var decimalPlaces=typeof config.decimalPlaces=="undefined"?-1:config.decimalPlaces;callback=typeof callback=="function"?callback:function(){};return this.data("numeric.decimal",decimal).data("numeric.altDecimal",altDecimal).data("numeric.negative",negative).data("numeric.callback",callback).data("numeric.decimalPlaces",decimalPlaces).keypress($.fn.numeric.keypress).keyup($.fn.numeric.keyup).blur($.fn.numeric.blur)};$.fn.numeric.keypress=function(e){var decimal=$.data(this,"numeric.decimal");var negative=$.data(this,"numeric.negative");var decimalPlaces=$.data(this,"numeric.decimalPlaces");var altDecimal=$.data(this,"numeric.altDecimal");var key=e.charCode?e.charCode:e.keyCode?e.keyCode:0;if(key==13&&this.nodeName.toLowerCase()=="input"){return true}else if(key==13){return false}var allow=false;if(e.ctrlKey&&key==97||e.ctrlKey&&key==65){return true}if(e.ctrlKey&&key==120||e.ctrlKey&&key==88){return true}if(e.ctrlKey&&key==99||e.ctrlKey&&key==67){return true}if(e.ctrlKey&&key==122||e.ctrlKey&&key==90){return true}if(e.ctrlKey&&key==118||e.ctrlKey&&key==86||e.shiftKey&&key==45){return true}if(key<48||key>57){var value=$(this).val();if($.inArray("-",value.split(""))!==0&&negative&&key==45&&(value.length===0||parseInt($.fn.getSelectionStart(this),10)===0)){return true}if(decimal&&key==decimal.charCodeAt(0)&&$.inArray(decimal,value.split(""))!=-1){allow=false}if(key!=8&&key!=9&&key!=13&&key!=35&&key!=36&&key!=37&&key!=39&&key!=46){allow=false}else{if(typeof e.charCode!="undefined"){if(e.keyCode==e.which&&e.which!==0){allow=true;if(e.which==46){allow=false}}else if(e.keyCode!==0&&e.charCode===0&&e.which===0){allow=true}}}if(decimal&&key==decimal.charCodeAt(0)||altDecimal&&key==altDecimal.charCodeAt(0)){if($.inArray(decimal,value.split(""))==-1){allow=true}else{allow=false}}}else{allow=true;if(decimal&&decimalPlaces>0){var dot=$.inArray(decimal,$(this).val().split(""));if(dot>=0&&$(this).val().length>dot+decimalPlaces){allow=false}}}return allow};$.fn.numeric.keyup=function(e){var val=$(this).val();if(val&&val.length>0){var carat=$.fn.getSelectionStart(this);var selectionEnd=$.fn.getSelectionEnd(this);var decimal=$.data(this,"numeric.decimal");var negative=$.data(this,"numeric.negative");var decimalPlaces=$.data(this,"numeric.decimalPlaces");var altDecimal=$.data(this,"numeric.altDecimal");if(decimal!==""&&decimal!==null){var dot=$.inArray(decimal,val.split(""));
14885if(dot===0){this.value="0"+val;carat++;selectionEnd++}if(dot==1&&val.charAt(0)=="-"){this.value="-0"+val.substring(1);carat++;selectionEnd++}val=this.value}var validChars=[0,1,2,3,4,5,6,7,8,9,"-",decimal];var length=val.length;for(var i=length-1;i>=0;i--){var ch=val.charAt(i);if(i!==0&&ch=="-"){val=val.substring(0,i)+val.substring(i+1)}else if(i===0&&!negative&&ch=="-"){val=val.substring(1)}var validChar=false;for(var j=0;j<validChars.length;j++){if(ch==validChars[j]){validChar=true;break}}if(!validChar&&ch==altDecimal){val=val.substring(0,i)+decimal+val.substring(i+1);validChar=true;}if(!validChar||ch==" "){val=val.substring(0,i)+val.substring(i+1)}}var firstDecimal=$.inArray(decimal,val.split(""));if(firstDecimal>0){for(var k=length-1;k>firstDecimal;k--){var chch=val.charAt(k);if(chch==decimal){val=val.substring(0,k)+val.substring(k+1)}}}if(decimal&&decimalPlaces>0){var dot=$.inArray(decimal,val.split(""));if(dot>=0){val=val.substring(0,dot+decimalPlaces+1);selectionEnd=Math.min(val.length,selectionEnd)}}this.value=val;$.fn.setSelection(this,[carat,selectionEnd])}};$.fn.numeric.blur=function(){var decimal=$.data(this,"numeric.decimal");var callback=$.data(this,"numeric.callback");var negative=$.data(this,"numeric.negative");var val=this.value;if(val!==""){var re=new RegExp("^" + (negative?"-?":"") + "\\d+$|^" + (negative?"-?":"") + "\\d*" + decimal + "\\d+$");if(!re.exec(val)){callback.apply(this)}}};$.fn.removeNumeric=function(){return this.data("numeric.decimal",null).data("numeric.altDecimal",null).data("numeric.negative",null).data("numeric.callback",null).data("numeric.decimalPlaces",null).unbind("keypress",$.fn.numeric.keypress).unbind("keyup",$.fn.numeric.keyup).unbind("blur",$.fn.numeric.blur)};$.fn.getSelectionStart=function(o){if(o.type==="number"){return undefined}else if(o.createTextRange&&document.selection){var r=document.selection.createRange().duplicate();r.moveEnd("character",o.value.length);if(r.text=="")return o.value.length;return Math.max(0,o.value.lastIndexOf(r.text))}else{try{return o.selectionStart}catch(e){return 0}}};$.fn.getSelectionEnd=function(o){if(o.type==="number"){return undefined}else if(o.createTextRange&&document.selection){var r=document.selection.createRange().duplicate();r.moveStart("character",-o.value.length);return r.text.length}else return o.selectionEnd};$.fn.setSelection=function(o,p){if(typeof p=="number"){p=[p,p]}if(p&&p.constructor==Array&&p.length==2){if(o.type==="number"){o.focus()}else if(o.createTextRange){var r=o.createTextRange();r.collapse(true);r.moveStart("character",p[0]);r.moveEnd("character",p[1]-p[0]);r.select()}else{o.focus();try{if(o.setSelectionRange){o.setSelectionRange(p[0],p[1])}}catch(e){}}}}}));
14886/**
14887 * Load HTML asynchronously
14888 * @namespace Verkami
14889 * @class Async
14890 *
14891 * Input parameters:
14892 * - "data-async-id" (required): Unique ID declared in both action and placeholder items. Example: community
14893 * - "data-async-source" (required): Source endpoint. Example: /endpoint/async/community
14894 * - "data-async-data" (optional): JSON string. This will be send as data in a POST request. Example: { "project_id": 2 }
14895 * - "data-async-trigger" (optional): Space separated JS hooks to launch functionalities
14896 *                                    after content is loaded. Example: utils.squarize modal.open
14897 *
14898 * Output: The endpoint must return rendered HTML, it will be appended to the defined placeholder.
14899 */
14900
14901modulejs.define("Verkami/Async", function () {
14902  var Async = {
14903    spinnerClass: "spinner",
14904    spinnerIconClass: "icon icon--spinner",
14905
14906    init: function () {
14907      this.events();
14908    },
14909
14910    events: function () {
14911      $(document).on("click.vk.async", ".js-async", this, this.getContent);
14912    },
14913
14914    addSpinner: function (placeholder) {
14915      var that = this;
14916      var spinner = that.createSpinner();
14917
14918      placeholder.css({
14919        overflow: "hidden",
14920        position: "relative",
14921        "min-height": 200,
14922      });
14923
14924      spinner.appendTo(placeholder);
14925    },
14926
14927    createSpinner: function () {
14928      var spinner = $("<span/>").addClass("spinner");
14929      var icon = $("<span/>").addClass("icon icon--spinner");
14930
14931      icon.appendTo(spinner);
14932
14933      return spinner;
14934    },
14935
14936    getContent: function (event) {
14937      var that = event.data;
14938      var node = $(this).hasClass("js-async") ? $(this) : $(this).closest(".
14938js-async");
14939      var id = node.data("async-id");
14940      var source = node.data("async-source");
14941      var data = node.data("async-data") || {};
14942      var trigger = node.data("async-trigger");
14943      var placeholder = $(".js-async-placeholder[data-async-id='" + id + "']");
14944      var isLoaded = node.data("async-loaded");
14945
14946      if (isLoaded) return;
14947
14948      // Show spinner
14949      that.addSpinner(placeholder);
14950
14951      $.get(source, data, function (response) {
14952        node.data("async-loaded", true);
14953
14954        // Show content
14955        $(response).appendTo(placeholder);
14956
14957        // Launch triggers
14958        if (trigger) {
14959          var i;
14960          var triggers = trigger.split(" ");
14961
14962          for (i = 0; i < triggers.length; ++i) {
14963            $(document).trigger("trigger.vk." + triggers[i], placeholder); // trigger each passed param
14964          }
14965        }
14966
14967        // Hide spinner
14968        that.removeSpinner(placeholder);
14969      }).fail(function () {
14970        // Hide spinner
14971        that.removeSpinner(placeholder);
14972      });
14973    },
14974
14975    removeSpinner: function (placeholder) {
14976      var spinner = $(".spinner", placeholder);
14977
14978      spinner.fadeOut(function () {
14979        placeholder.css({
14980          overflow: "",
14981          position: "",
14982          "min-height": "",
14983        });
14984
14985        $(this).remove();
14986      });
14987    },
14988  };
14989
14990  Async.init();
14991
14992  return Async;
14993});
14994/**
14995 * DataTransfer
14996 * @namespace Verkami
14997 * @class DataTransfer
14998 *
14999 * Instructions:
15000 * - Trigger must have a "js-pull" class, a "data-pull" attribute with element names separated by
15001 *   comma.
15002 * - Push elements must have the class "js-push-ELEMENT-NAME".
15003 * - Placeholder elements must have the class "js-placeholder-ELEMENT-NAME".
15004 * - If push content is empty, you can set a default content to avoid showing an empty string
15005 *   by setting "data-placeholder-empty" attribute in the "js-placeholder-ELEMENT-NAME" item
15006 *
15007 * Note 1: dataTransfer is getting the value if is a form element, and the inner HTML if is not
15008 *
15009 * Note 2: If there more than one element with same push name, an specific ID like a timestamp must
15010 *         be set as a "data-pull-id" in the trigger element, and as a "data-push-id" in the push
15011 *         element.
15012 *
15013 * Note 3: If you don't want to trigger the dataTransfer on click, just avoid .js-pull class and use
15014 *         DataTransfer.transfer(object).
15015 */
15016
15017var name = "Verkami/DataTransfer";
15018
15019modulejs.define(name, function() {
15020  var DataTransfer = {
15021    triggers: [],
15022    pushPrefix: "js-push-",
15023    placeholderPrefix: "js-placeholder-",
15024
15025    init: function() {
15026      var that = this;
15027      that.triggers = $(".js-pull");
15028
15029      that.triggers.on("click.dataTransfer", function() {
15030        that.transfer($(this).data());
15031      });
15032    },
15033
15034    refresh: function() {
15035      var that = this;
15036      that.triggers = $(".js-pull");
15037
15038      // Update dataPullId
15039      that.triggers.each(function() {
15040        $(this).data("pull-id", $(this).attr("data-pull-id"));
15041      });
15042
15043      that.triggers.off("click.dataTransfer").on("click.dataTransfer", function() {
15044        that.transfer($(this).data());
15045      });
15046    },
15047
15048    transfer: function(settings) {
15049      var that = this;
15050      var content = "";
15051      var dataId = settings.pullId;
15052      var dataLocale = settings.pullLocale;
15053      var pullNodes = settings.pull.split(",");
15054      var pushNode = [];
15055      var placeholderNode = [];
15056
15057      $.each(pullNodes, function(i, element) {
15058        pushNode = $("." + that.pushPrefix + element);
15059        placeholderNode = $("." + that.placeholderPrefix + element);
15060
15061        if (pushNode.length && placeholderNode.length) {
15062          if (dataId) {
15063            if (dataLocale) {
15064              pushNode = pushNode.filter("[data-push-id='" + dataId + "_" + dataLocale + "']");
15065              placeholderNode = placeholderNode.filter("[data-pull-id='" + dataId + "_" + dataLocale + "']");
15066            } else {
15067              pushNode = pushNode.filter("[data-push-id='" + dataId + "']");
15068              placeholderNode = placeholderNode.filter("[data-pull-id='" + dataId + "']");
15069            }
15070          }
15071
15072          content = pushNode.is(":input") ? pushNode.val() : pushNode.html();
15073
15074          /**
15075           * Since frontend has not provided any way to i18n-ized JS strings we
15076           * use here 2 data attribs to provide basic interpolation:
15077           * - `data-placeholder-template` for non-empty fields where %{count} will be replaced by their value
15078           * - `data-placeholder-empty` for empty fields.
15079           * */
15080          if (content.length && placeholderNode.is("[data-placeholder-template]")) {
15081            var template = placeholderNode.attr("data-placeholder-template");
15082            content = template.replace(/%\{count\}/, content);
15083          }
15084          if (!content.length && placeholderNode.is("[data-placeholder-empty]")) {
15085            content = placeholderNode.attr("data-placeholder-empty");
15086          }
15087          placeholderNode.html(content);
15088        }
15089      });
15090    }
15091  };
15092
15093  DataTransfer.init();
15094
15095  return DataTransfer;
15096});
15097/**
15098* DropCap
15099* @namespace Verkami
15100* @class DropCap
15101*/
15102
15103var name = 'Verkami/DropCap';
15104
15105modulejs.define(name, function() {
15106  var DropCap = {
15107    wrapper: [],
15108    className: 'drop-cap',
15109
15110    init: function() {
15111      var that = this;
15112      that.wrapper = $('.js-drop-cap');
15113
15114      if (that.wrapper.length) {
15115        var dropCapCandidates = that.wrapper.children('p');
15116        var hasImage = 0;
15117        var hasBlockquoteClose = 0;
15118
15119        dropCapCandidates.each(function() {
15120          hasImage = $(this).children('img').length;
15121          hasBlockquoteClose = $(this).prev('blockquote').length;
15122
15123          if (!hasImage) {
15124            if (!hasBlockquoteClose) {
15125              $(this).addClass(that.className);
15126            }
15127
15128            return false;
15129          }
15130        });
15131      }
15132    }
15133  };
15134
15135  DropCap.init();
15136
15137  return DropCap;
15138});
15139/**
15140* Loading
15141* @namespace Verkami
15142* @class Loading
15143*/
15144
15145var name = 'Verkami/Loading';
15146
15147modulejs.define(name, function() {
15148  var Loading = {
15149    iconClass: 'icon icon--spinner',
15150    spinnerClass: 'loading__spinner',
15151    wrapperClass: 'loading',
15152
15153    enable: function(wrapper) {
15154      var that = this;
15155      var loading = $('<div>', { class: that.spinnerClass });
15156      
15157      // Add relative position to loading wrapper
15158      wrapper.addClass(that.wrapperClass);
15159
15160      // Add spinner icon to the loading layer
15161      $('<span/>', { class: that.iconClass }).appendTo(loading);
15162
15163      // Append the loading layer to the wrapper and show it
15164      loading.appendTo(wrapper).fadeIn();
15165    },
15166
15167    disable: function(wrapper) {
15168      var that = this;
15169      var loading = $('.' + that.spinnerClass, wrapper);
15170      
15171      // Remove relative position of loading wrapper
15172      wrapper.removeClass(that.wrapperClass);
15173
15174      // Hide the loading layer and remove it from the DOM
15175      loading.fadeOut(function() {
15176        $(this).remove();
15177      });
15178    }
15179  };
15180
15181  return Loading;
15182});
15183/**
15184* Scroll
15185* @namespace Verkami
15186* @class Scroll
15187*/
15188
15189var name = "Verkami/Scroll";
15190var deps = [
15191  "Verkami/Settings"
15192];
15193
15194modulejs.define(name, deps, function(Settings) {
15195  var Scroll = {
15196    init: function () {
15197      this.smooth.init();
15198    },
15199
15200    position: function () {
15201      var position = $(window).scrollTop();
15202
15203      return position;
15204    },
15205
15206    // Smooth scroll for internal anchors
15207    smooth: {
15208      init: function () {
15209        var that = this;
15210
15211        // All anchor links items
15212        var scrollableItems = $("a[href^=\"#\"]");
15213
15214        // Bind click handler to menu items so we can get a fancy scroll animation
15215        scrollableItems.on("click", function (e) {
15216          e.preventDefault();
15217
15218          var target = $(this).attr("href");
15219
15220          if ($(target).length) {
15221            that.doScroll($(target));
15222          }
15223        });
15224      },
15225
15226      doScroll: function (target, extraOffset, customContainer) {
15227        if (target.length || target === "reset") {
15228          var easeOutExpo = function (x, t, b, c, d) {
15229            return t === d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b;
15230          };
15231          var container = customContainer ? customContainer : $("html, body");
15232          var offsetTop = target === "reset" ? 0 : target.offset().top;
15233          var newPosition;
15234
15235          if (extraOffset) {
15236            newPosition = offsetTop - extraOffset;
15237          } else {
15238            newPosition = offsetTop;
15239          }
15240
15241          // @todo: Is it possible to remove speed and easing? They are already set in Verkami/Settings
15242          container.stop().animate({ scrollTop: newPosition }, Settings.speed, easeOutExpo);
15243        } else {
15244          return false;
15245        }
15246      },
15247    }
15248  };
15249
15250  Scroll.init();
15251
15252  return Scroll;
15253});
15254/**
15255 * Settings
15256 * @namespace Verkami
15257 * @class Settings
15258 */
15259
15260var name = "Verkami/Settings";
15261
15262modulejs.define(name, function () {
15263  var Settings = {
15264    delay: 1000,
15265    language: $("meta[name='language']").prop("content"),
15266    speed: 300,
15267    instantSpeed: 0,
15268
15269    init: function () {
15270      var that = this;
15271
15272      // Setting up the default animation speeds
15273      $.extend($.fx.speeds, {
15274        _default: that.speed,
15275        fast: that.speed / 2,
15276        slow: that.speed * 2,
15277        slower: that.speed * 4,
15278      });
15279
15280      // Extending easing functionality and setting up the default easing function
15281      $.extend($.easing, {
15282        _default: "easeOutExpo",
15283        easeOutExpo: function (x, t, b, c, d) {
15284          return t == d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b;
15285        },
15286        easeInOutCubic: function (x, t, b, c, d) {
15287          if ((t /= d / 2) < 1) return (c / 2) * t * t * t + b;
15288          return (c / 2) * ((t -= 2) * t * t + 2) + b;
15289        },
15290      });
15291    },
15292
15293    beta: {
15294      tokenizationAvailable: function () {
15295        return true;
15296      },
15297    },
15298    sliders: {
15299      delay: 4000,
15300    },
15301  };
15302
15303  Settings.init();
15304
15305  return Settings;
15306});
15307/**
15308 * Utils
15309 * @namespace Verkami
15310 * @class Utils
15311 */
15312
15313var deps = ["Verkami/Settings"];
15314
15315modulejs.define("Verkami/Utils", deps, function (Settings) {
15316  var Utils = {
15317    isMobile: false,
15318    isTablet: false,
15319    isDesktop: false,
15320
15321    init: function () {
15322      var that = this;
15323      var timeout;
15324
15325      that.ajaxSettings();
15326      that.setDeviceFlag();
15327      that.externalLinks.init();
15328      that.getSVG();
15329      that.buttonsAsLinks();
15330      that.squarize();
15331      that.widerize();
15332      that.captchaPositionFixer();
15333
15334      $(window).resize(function () {
15335        that.setDeviceFlag();
15336
15337        clearTimeout(timeout);
15338        timeout = setTimeout(function () {
15339          that.squarize();
15340          that.widerize();
15341        }, Settings.speed);
15342      });
15343
15344      that.triggers();
15345    },
15346
15347    triggers: function () {
15348      var that = this;
15349
15350      $(document).on("trigger.vk.utils.squarize", function (e, wrapper) {
15351        that.squarize(wrapper);
15352      });
15353    },
15354
15355    /**
15356     * Set common headers/properties for all jQuery AJAX requests
15357     * @class ajaxSettings
15358     */
15359    ajaxSettings: function () {
15360      var that = this;
15361      var csrfToken = $('meta[name="csrf-token"]').prop("content");
15362
15363      $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
15364        // Unique ID for each ajax request
15365
15366        if (options["url"] == "/user_session") {
15367          var tokens = $('input[name="authenticity_token"]')
15368            .map(function () {
15369              return this.value;
15370            })
15371            .get()
15372            .join();
15373          console.log("Sending CSRF token: " + csrfToken);
15374          console.log("Available CSRF tokens: " + tokens);
15375        }
15376        var ajaxID = that.uuid();
15377        jqXHR.setRequestHeader("X-Verkami-AjaxID", ajaxID);
15378        jqXHR.verkami = { ajaxID: ajaxID };
15379
15380        if (csrfToken) {
15381          jqXHR.setRequestHeader("X-CSRF-Token", csrfToken);
15382        }
15383      });
15384    },
15385
15386    /**
15387     * Return a pseudo UUID v4, useful for IDs
15388     * @class uuid
15389     */
15390    uuid: function () {
15391      var u = new Date().getTime().toString(16) + Math.random().toString(16).substring(2) + "0000000000000000";
15392      return u.substr(0, 8) + "-" + u.substr(8, 4) + "-4000-8" + u.substr(12, 3) + "-" + u.substr(15, 12);
15393    },
15394
15395    caseInsensitiveEqual: function (a, b) {
15396      return typeof a === "string" && typeof b === "string"
15397        ? a.localeCompare(b, undefined, { sensitivity: "accent" }) === 0
15398        : a === b;
15399    },
15400
15401    /**
15402     * Returns the callback functionality after a specific delay
15403     * @class delayedCallback
15404     * @params
15405     *    callback: function to call after the delay
15406     *    ms: time applied to the delay (milliseconds)
15407     */
15408    delayedCallback: function (callback, ms) {
15409      let timer = 0;
15410
15411      return function (...args) {
15412        clearTimeout(timer);
15413        timer = setTimeout(callback.bind(this, ...args), ms || 0);
15414      };
15415    },
15416
15417    /**
15418     * Set [target: _blank] to external links
15419     * @class externalLinks
15420     */
15421    externalLinks: {
15422      init: function () {
15423        var that = this;
15424        var links = $("a").filter(function () {
15425          return this.hostname && this.hostname !== location.hostname;
15426        });
15427
15428        that.changeTarget(links);
15429
15430        that.events();
15431      },
15432
15433      changeTarget: function (links) {
15434        links.attr("target", "_blank");
15435      },
15436
15437      events: function () {
15438        $("body").on("click.ExternalLinks", ".js-external-links a", function (e) {
15439          e.preventDefault();
15440
15441          window.open($(this).prop("href"), "_blank");
15442        });
15443      },
15444    },
15445
15446    /**
15447     * Get SVG from img tag
15448     * @class getSVG
15449     */
15450    getSVG: function () {
15451      var svgNodes = $(".js-svg");
15452
15453      if (svgNodes.length) {
15454        svgNodes.each(function () {
15455          var svgNode = $(this);
15456          var svgURL = svgNode.attr("src");
15457
15458          $.get(
15459            svgURL,
15460            function (data) {
15461              var svg = $(data).find("svg");
15462
15463              svgNode.replaceWith(svg);
15464            },
15465            "xml"
15466          );
15467        });
15468      }
15469    },
15470
15471    buttonsAsLinks: function () {
15472      var buttonsAsLinks = $(".js-button-link");
15473
15474      if (buttonsAsLinks.length) {
15475        console.log("heyeyydheydhe hohohoho *");
15476        buttonsAsLinks.each(function () {
15477          var node = $(this);
15478          console.log("heyeyydheydhe hohohoho KOKPKFDWEKFPOEW*");
15479          var url = node.attr("data-link");
15480
15481          node.on("click", function (e) {
15482            e.preventDefault();
15483            console.log("**************************");
15484            console.log(url);
15485            window.location.href = url;
15486          });
15487        });
15488      }
15489    },
15490
15491    normalizeDiacritics: function (string) {
15492      // https://www.wikiwand.com/en/Combining_Diacritical_Marks
15493      var combiningDiacriticalMarksBlock = /[\u0300-\u036f]/g;
15494      return string.normalize("NFD").replace(combiningDiacriticalMarksBlock, "");
15495    },
15496
15497    safeString: function (string) {
15498      // .text() uses the DOM method .createTextNode() and therefor does not interpret the string as HTML.
15499      // cf. https://jsbin.com/pohefecucu/edit?html,js,output
15500      return $("<div/>").text(string).html();
15501    },
15502
15503    /**
15504     * Get viewport size
15505     * @class getViewportSize
15506     * @parameter dimension[width,height]
15507     */
15508    getViewportSize: function (dimension) {
15509      var size;
15510
15511      if (dimension === "width") {
15512        size = $(window).width();
15513        return size;
15514      } else if (dimension === "height") {
15515        size = $(window).height();
15516        return size;
15517      } else {
15518        size = {
15519          width: $(window).width(),
15520          height: $(window).height(),
15521        };
15522        return size;
15523      }
15524    },
15525
15526    /**
15527     * Get URL hash
15528     * @class hash
15529     */
15530    hash: {
15531      get: function () {
15532        var hash = decodeURIComponent(window.location.hash.substring(1));
15533
15534        return hash;
15535      },
15536
15537      pick: function (name) {
15538        var hash = this.get();
15539        var sURLVariables = hash.replace("?", "&").split("&");
15540        var sParameterName;
15541        var i;
15542
15543        for (i = 0; i < sURLVariables.length; i++) {
15544          sParameterName = sURLVariables[i].split("=");
15545
15546          if (sParameterName[0] === name) {
15547            return sParameterName[1] === undefined ? true : sParameterName[1];
15548          }
15549        }
15550      },
15551    },
15552
15553    /**
15554     * Preload images
15555     * @class preloadImages
15556     */
15557    preloadImages: function (items) {
15558      var item = [];
15559      var itemPath = "";
15560
15561      items.each(function () {
15562        item = $(this);
15563        itemPath = item.data("preload-image");
15564
15565        $("<img />").attr("src", itemPath);
15566
15567        item.css("background-image", "url(" + itemPath + ")");
15568      });
15569    },
15570
15571    /**
15572     * Redirect URL
15573     * @class redirect
15574     */
15575    redirect: function (redirectPath) {
15576      // The redirectPath may be sometimes and encoded URI
15577      // (eg. Facebook Login 'origin' parameter must be encoded in order to be returned)
15578      // Decoded it to be sure we are redirecting correctly
15579      redirectPath = decodeURIComponent(redirectPath);
15580      var redirectBasePath = redirectPath.substr(0, redirectPath.indexOf("#"));
15581      var currentPath = document.location.pathname;
15582
15583      if (redirectPath) {
15584        document.location.assign(redirectPath);
15585
15586        // Force reload if the redirect URL is the same as the current one
15587        if (currentPath === redirectBasePath) {
15588          location.reload(true);
15589        }
15590      } else {
15591        return false;
15592      }
15593    },
15594
15595    /**
15596     * Disable Responsive
15597     * @class responsiveDisable
15598     */
15599    responsiveDisable: {
15600      nodes: [],
15601      cookie: "",
15602      cookieName: "cookie_responsive",
15603      meta: "width=1085, initial-scale=0.1, user-scalable=0",
15604      metaFinal: "width=1085, initial-scale=0.1",
15605
15606      init: function () {
15607        var that = this;
15608        var node = [];
15609        that.nodes = $(".js-responsive-disable");
15610        that.cookie = Cookies.get(that.cookieName);
15611
15612        // Disable responsive if cookie is previously set
15613        if ($("body").hasClass("js-responsive-disable-cookie") && that.cookie) {
15614          that.addMeta();
15615        }
15616
15617        that.nodes.each(function () {
15618          node = $(this);
15619
15620          // Disable responsive directly. Add click event if the element is a trigger.
15621          if (node.is("body")) {
15622            that.addMeta();
15623          } else {
15624            node.on("click", function (e) {
15625              e.preventDefault();
15626
15627              Cookies.set(that.cookieName, "true", {
15628                expires: 365,
15629              });
15630
15631              location.reload();
15632            });
15633          }
15634        });
15635      },
15636
15637      addMeta: function () {
15638        var that = this;
15639        Utils.isDesktop = true;
15640        Utils.isMobile = false;
15641        Utils.isTablet = false;
15642
15643        $('meta[name="viewport"]').attr("content", that.meta);
15644
15645        setTimeout(function () {
15646          $('meta[name="viewport"]').attr("content", that.metaFinal);
15647        }, 300);
15648      },
15649    },
15650
15651    /**
15652     * Check screen's width to set the device behavior
15653     * @class setDeviceFlag
15654     */
15655    setDeviceFlag: function () {
15656      var that = this;
15657      var viewportWidth = that.getViewportSize("width");
15658
15659      if (viewportWidth < 768) {
15660        that.isDesktop = false;
15661        that.isMobile = true;
15662        that.isTablet = false;
15663
15664        that.responsiveDisable.init();
15665      } else if (viewportWidth < 1025) {
15666        that.isDesktop = false;
15667        that.isMobile = false;
15668        that.isTablet = true;
15669      } else {
15670        that.isDesktop = true;
15671        that.isMobile = false;
15672        that.isTablet = false;
15673      }
15674    },
15675
15676    /**
15677     * Squarize an element setting its height equal to its width
15678     * @class squarize
15679     */
15680    squarize: function (wrapper) {
15681      var squares = [];
15682
15683      if (wrapper) {
15684        squares = $(".js-squarize", wrapper);
15685      } else {
15686        squares = $(".js-squarize");
15687      }
15688
15689      if (squares.length) {
15690        var square;
15691        var squareHeight;
15692
15693        squares.each(function () {
15694          square = $(this);
15695          squareHeight = square.outerWidth();
15696
15697          square.height(squareHeight);
15698        });
15699      }
15700    },
15701
15702    widerize: function () {
15703      var collection = $(".js-widerize");
15704
15705      if (collection.length) {
15706        var item;
15707        var isPortrait;
15708        var height;
15709
15710        collection.each(function () {
15711          item = $(this);
15712          isPortrait = item.attr("data-widerize-portrait") != undefined;
15713          height = isPortrait ? Math.round((item.outerWidth() / 9) * 16) : Math.round((item.outerWidth() / 16) * 9);
15714
15715          item.height(height);
15716        });
15717      }
15718    },
15719
15720    /**
15721     * cf. https://github.com/verkami/verkami/issues/3228#issuecomment-561206607
15722     */
15723    captchaPositionFixer: function () {
15724      var that = this;
15725      if (!that.isMobile) return false;
15726
15727      console.log("[CAPTCHA] Setting up captcha overlay CSS fixer");
15728      setInterval(function () {
15729        var reCaptchaIframe = $("iframe[title='recaptcha challenge']");
15730        if (reCaptchaIframe) {
15731          var reCaptchaOverlay = reCaptchaIframe.parent();
15732          reCaptchaOverlay.css("position", "fixed");
15733        }
15734      }, 2000);
15735    },
15736  };
15737
15738  Utils.init();
15739
15740  return Utils;
15741});
15742/**
15743 * Autocomplete
15744 * @namespace Verkami
15745 * @class Autocomplete
15746 */
15747
15748var name = "Verkami/Autocomplete";
15749var deps = ["Verkami/Settings"];
15750
15751modulejs.define(name, deps, function(Settings) {
15752  var Autocomplete = {
15753    nodes: [],
15754    timeout: null,
15755    minlength: 3,
15756
15757    init: function() {
15758      var that = this;
15759      that.nodes = $(".js-autocomplete");
15760
15761      that.nodes.each(function() {
15762        that.setup($(this));
15763      });
15764    },
15765
15766    setup: function(node) {
15767      var that = this;
15768
15769      var input = $("input[type='text']", node);
15770      input.data("last-accepted-value", input.val());
15771
15772      input.attr("autocomplete", "off");
15773
15774      input.on("blur", function() {
15775        input.val(input.data("last-accepted-value"));
15776        that.hideResults($(this));
15777      });
15778
15779      input.on("focus", function() {
15780        that.manageCurrentValue($(this));
15781      });
15782
15783      input.on("keyup", function(e) {
15784        switch (e.which) {
15785        case 37: // left
15786          return;
15787
15788        case 38: // up
15789          return;
15790
15791        case 39: // right
15792          return;
15793
15794        case 40: // down
15795          return;
15796
15797        case 13: // enter
15798          return;
15799        }
15800        that.manageCurrentValue($(this));
15801      });
15802    },
15803
15804    manageCurrentValue: function(input) {
15805      var that = this;
15806      var text = input.val().toLowerCase();
15807      var autocomplete = input.parents(".js-autocomplete");
15808      var instructions = autocomplete.data("autocomplete-instructions");
15809      if (text.length >= that.minlength) {
15810        that.requestAutocomplete(input);
15811      } else {
15812        clearTimeout(that.timeout);
15813        that.showResults(input, [
15814          {
15815            message: instructions
15816          }
15817        ]);
15818      }
15819    },
15820
15821    requestAutocomplete: function(input) {
15822      console.log("requestAutocomplete 0");
15823      var that = this;
15824      var text = input.val().toLowerCase();
15825      var autocomplete = input.parents(".js-autocomplete");
15826      var source = autocomplete.data("autocomplete-source");
15827      var noResults = autocomplete.data("autocomplete-no-results");
15828
15829      var data = {
15830        term: text
15831      };
15832
15833      $(".js-autocomplete-data", autocomplete).each(function() {
15834        var name = $(this).attr("name");
15835        var value = $(this).attr("value");
15836        console.log("requestAutocomplete 1 " + name + " " + value);
15837
15838        data[name] = value;
15839      });
15840
15841      console.log("requestAutocomplete 2");
15842
15843      clearTimeout(that.timeout);
15844
15845      that.timeout = setTimeout(function() {
15846        // Show spinner
15847        console.log("requestAutocomplete 3");
15848        $("<div/>")
15849          .addClass("icon icon--spinner--white")
15850          .appendTo(autocomplete)
15851          .fadeIn();
15852
15853        $.ajax({
15854          type: "GET",
15855          url: source,
15856          data: data,
15857          dataType: "json",
15858          error: function(_response, _status, error) {
15859            console.log("requestAutocomplete ERROR " + _response.verkami.ajaxID);
15860
15861            if (text == input.val().toLowerCase()) {
15862              that.showResults(input, [
15863                {
15864                  message: error
15865                }
15866              ]);
15867
15868              setTimeout(function() {
15869                that.hideResults(input);
15870              }, Settings.speed * 10);
15871            }
15872          },
15873
15874          success: function(results, _status, jqXHR) {
15875            console.log("requestAutocomplete 3_1 " + jqXHR.verkami.ajaxID);
15876            // Check if the user has changed the autocomplete text since we started the process
15877            if (text == input.val().toLowerCase()) {
15878              // Check if the user has changed the autocomplete text since we started the process
15879              console.log("requestAutocomplete 3_1_1 " + jqXHR.verkami.ajaxID);
15880              if (!results.length) {
15881                results = [
15882                  {
15883                    message: noResults
15884                  }
15885                ];
15886                //setTimeout(function () {
15887                //  that.hideResults(input);
15888                //}, Settings.speed * 10);
15889              }
15890              console.log("requestAutocomplete 3_1_1 showResults " + jqXHR.verkami.ajaxID);
15891              that.showResults(input, results);
15892            }
15893            console.log("requestAutocomplete 3_1b " + jqXHR.verkami.ajaxID);
15894          },
15895
15896          complete: function(jqXHR) {
15897            console.log("requestAutocomplete 3_2 " + jqXHR.verkami.ajaxID);
15898            $(".icon--spinner--white", autocomplete).fadeOut(function() {
15899              console.log("requestAutocomplete 3_2_1 " + jqXHR.verkami.ajaxID);
15900              $(this).remove();
15901            });
15902          }
15903        });
15904      }, Settings.delay);
15905    },
15906
15907    hideResults: function(input) {
15908      console.log("hideResults 1");
15909      var autocomplete = input.parents(".js-autocomplete");
15910
15911      $(".dropdown__box", autocomplete).fadeOut("fast", function() {
15912        console.log("hideResults 1_1");
15913        $(this).remove();
15914      });
15915      console.log("hideResults 1b");
15916    },
15917
15918    showResults: function(input, results) {
15919      console.log("showResults 0");
15920
15921      var that = this;
15922      var autocomplete = input.parents(".js-autocomplete");
15923      var resultList = [];
15924      var autocompleteBox = $("<div>", {
15925        class: "dropdown__box"
15926      });
15927      var autocompleteList = $("<ul>", {
15928        class: "dropdown__list"
15929      }).appendTo(autocompleteBox);
15930      var usePropertyAsLink = autocomplete.data("autocomplete-target");
15931      console.log("showResults 1");
15932      input.off("keydown.autocomplete");
15933      console.log("showResults 2");
15934      console.log("showResults 2_1 hideResults");
15935      that.hideResults(input);
15936      console.log("showResults 2_1_1 hideResults done");
15937      console.log("showResults 3");
15938      autocomplete.addClass("dropdown");
15939
15940      $(results).each(function(index, result) {
15941        console.log("showResults 4 /" + index);
15942
15943        resultList = $("<li>", {
15944          class: "dropdown__list__item"
15945        });
15946        if (result.message) {
15947          console.log("showResults 4_1 /" + index);
15948          that.setupResultAsMessage(result, resultList);
15949        } else {
15950          if (usePropertyAsLink) {
15951            console.log("showResults 4_2 /" + index);
15952            that.setupResultAsLink(result, resultList, usePropertyAsLink);
15953          } else {
15954            console.log("showResults 4_3 /" + index);
15955            that.setupResultAsPush(result, resultList);
15956          }
15957        }
15958        console.log("showResults 4b");
15959
15960        autocompleteList.append(resultList);
15961        console.log("showResults 4c");
15962      });
15963      console.log("showResults 5");
15964
15965      autocompleteBox.appendTo(autocomplete).fadeIn("fast");
15966      console.log("showResults 6");
15967      input.on("keydown.autocomplete", function(e) {
15968        var items = $(this)
15969          .siblings(".dropdown__box")
15970          .find(".dropdown__list__item");
15971        var hoverItem = $(".dropdown__list__item--hover", autocomplete);
15972
15973        switch (e.which) {
15974        case 38: // up
15975          if (hoverItem.length) {
15976            if (hoverItem.prev().length) {
15977              hoverItem
15978                .removeClass("dropdown__list__item--hover")
15979                .prev()
15980                .addClass("dropdown__list__item--hover");
15981              that.moveTo(hoverItem.prev());
15982            }
15983          }
15984
15985          break;
15986
15987        case 40: // down
15988          if (hoverItem.length) {
15989            if (hoverItem.next().length) {
15990              hoverItem
15991                .removeClass("dropdown__list__item--hover")
15992                .next()
15993                .addClass("dropdown__list__item--hover");
15994              that.moveTo(hoverItem.next());
15995            }
15996          } else {
15997            items.first().addClass("dropdown__list__item--hover");
15998            that.moveTo(items.first());
15999          }
16000
16001          break;
16002
16003        case 13: // enter
16004          if (hoverItem.length) {
16005            if (usePropertyAsLink) {
16006              window.location.href = $("a", hoverItem).attr("href");
16007            } else {
16008              e.stopPropagation();
16009
16010              // Copy option to input
16011              that.selectResult($("a", hoverItem));
16012
16013              // Hide dropdown
16014              $(this).blur();
16015            }
16016          }
16017
16018          break;
16019
16020        default:
16021          return; // exit this handler for other keys
16022        }
16023
16024        e.preventDefault(); // prevent the default action (scroll / move caret)
16025      });
16026    },
16027
16028    selectResult: function(trigger) {
16029      console.log("selectResult 0");
16030
16031      var autocomplete = trigger.closest(".js-autocomplete");
16032      var text = trigger.text();
16033      var data = trigger.data("autocomplete-data");
16034      var textTarget = $("input[type=\"text\"]", autocomplete);
16035      var dataTargets = $("input[data-autocomplete-pull]", autocomplete);
16036
16037      // Update input value
16038      console.log("selectResult 1 " + text);
16039      textTarget.val(text);
16040      textTarget.data("last-accepted-value", text);
16041      console.log("selectResult 2 " + text);
16042      // Fill in other inputs with there is complementary data
16043      if (dataTargets.length) {
16044        console.log("selectResult 3 ");
16045        var dataTarget = [];
16046        var dataTargetName = "";
16047        var dataTargetNameLength = 0;
16048        var dataTargetValue = "";
16049
16050        dataTargets.each(function() {
16051          console.log("selectResult 3_1 ");
16052          dataTarget = $(this);
16053          dataTargetName = dataTarget.data("autocomplete-pull").split(".");
16054          console.log("selectResult 3_2 " + dataTargetName);
16055          dataTargetNameLength = dataTargetName.length;
16056          dataTargetValue = data[dataTargetName[0]];
16057
16058          if (dataTargetNameLength > 1) {
16059            for (var i = 1; i < dataTargetNameLength; i++) {
16060              dataTargetValue = dataTargetValue[dataTargetName[i]];
16061            }
16062          }
16063
16064          dataTarget.val(dataTargetValue);
16065        });
16066      }
16067      console.log("selectResult 3b");
16068    },
16069
16070    moveTo: function(item) {
16071      if (item.length) {
16072        var itemHeight = item.outerHeight();
16073        var itemOffset = item.position().top;
16074        var boxHeight = item.parent().outerHeight();
16075        var scrollPosition = item.parent().scrollTop();
16076        var easeOutExpo = function(x, t, b, c, d) {
16077          return t === d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b;
16078        };
16079
16080        if (boxHeight < itemOffset + itemHeight) {
16081          scrollPosition = itemOffset + itemHeight + item.parent().scrollTop() - boxHeight;
16082        } else if (item.parent().scrollTop() > 0 && itemOffset < 0) {
16083          scrollPosition = item.parent().scrollTop() + itemOffset;
16084        }
16085
16086        item
16087          .parent()
16088          .stop()
16089          .animate(
16090            {
16091              scrollTop: scrollPosition
16092            },
16093            Settings.speed / 2,
16094            easeOutExpo
16095          );
16096      }
16097    },
16098
16099    setupResultAsLink: function(result, list, property) {
16100      $("<a>")
16101        .attr({
16102          title: result.name,
16103          href: result[property]
16104        })
16105        .text(result.name)
16106        .appendTo(list);
16107    },
16108
16109    setupResultAsPush: function(result, list) {
16110      var that = this;
16111      $("<a>")
16112        .attr({
16113          title: result.name,
16114          href: "#"
16115        })
16116        .text(result.name)
16117        .addClass("js-autocomplete-push")
16118        .data("autocomplete-data", result)
16119        .appendTo(list)
16120        .on("click", function(e) {
16121          e.preventDefault();
16122          console.log("setupResultAsPush 1");
16123          console.log("setupResultAsPush result " + result.name);
16124          that.selectResult($(this));
16125        });
16126    },
16127
16128    setupResultAsMessage: function(result, list) {
16129      $("<span>")
16130        .text(result.message)
16131        .appendTo(list);
16132    }
16133  };
16134
16135  Autocomplete.init();
16136
16137  return Autocomplete;
16138});
16139/**
16140* Bar
16141* @namespace Verkami
16142* @class Bar
16143*/
16144
16145var name = "Verkami/Bar";
16146var deps = [
16147  "Verkami/Settings"
16148];
16149
16150modulejs.define(name, deps, function(Settings) {
16151  var Bar = {
16152    nodes: [],
16153    hiddenClass: "bar--hidden",
16154
16155    init: function() {
16156      var that = this;
16157      that.nodes = $(".js-bar");
16158      var barsToShowAfter = that.nodes.filter(function () {
16159        return $(this).data("bar-show-after");
16160      });
16161
16162      barsToShowAfter.each(function() {
16163        that.setupShowAfter($(this));
16164      });
16165    },
16166
16167    getHeight: function() {
16168      var that = this;
16169      var totalHeight = 0;
16170
16171      that.nodes.each(function() {
16172        totalHeight += $(this).outerHeight();
16173      });
16174
16175      return totalHeight;
16176    },
16177
16178    setupShowAfter: function(node) {
16179      var that = this;
16180      var offset = 0;
16181      var target = $(node.data("bar-show-after"));
16182
16183      if (target.length) {
16184        setTimeout(function() {
16185          offset = target.offset().top;
16186
16187          node.data("bar-show-after-offset", offset);
16188
16189          $(document).on("scroll.Bar", function() {
16190            if ($(window).scrollTop() >= parseInt(offset)) {
16191              node.removeClass(that.hiddenClass);
16192            } else {
16193              node.addClass(that.hiddenClass);
16194            }
16195          });
16196        }, Settings.speed);
16197      }
16198    }
16199  };
16200
16201  Bar.init();
16202
16203  return Bar;
16204});
16205/**
16206* ColorPicker
16207* @namespace Verkami
16208* @class ColorPicker
16209*/
16210
16211var name = 'Verkami/ColorPicker';
16212
16213modulejs.define(name, function() {
16214  var ColorPicker = {
16215    nodes: [],
16216
16217    init: function() {
16218      var that = this;
16219      that.nodes = $('.js-color-picker');
16220
16221      if (that.nodes.length) {
16222        // @todo: Make colorpicker plugin a dependency
16223        that.nodes.colorpicker({
16224          component: $('.js-color-picker-trigger'),
16225          format: 'hex'
16226        });
16227      }
16228    }
16229  };
16230
16231  ColorPicker.init();
16232
16233  return ColorPicker;
16234});
16235/**
16236* Dropdown
16237* @namespace Verkami
16238* @class Dropdown
16239*/
16240
16241var name = 'Verkami/Dropdown';
16242var deps = [
16243  'Verkami/Utils'
16244];
16245
16246modulejs.define(name, deps, function(Utils) {
16247  var Dropdown = {
16248    nodes: [],
16249    triggers: [],
16250    asideTriggerActiveClass: 'dropdown__list__item--active',
16251    asideVisibleClass: 'dropdown--aside-visible',
16252
16253    init: function() {
16254      var that = this;
16255      that.nodes = $('.js-dropdown');
16256
16257      if (that.nodes.length) {
16258        that.triggers = $('.js-dropdown-trigger');
16259        var node = [];
16260        var dropdownList = [];
16261        var dropdownAsides = [];
16262        var dropdownAside = [];
16263
16264        that.nodes.each(function() {
16265          node = $(this);
16266          dropdownAsides = $('.js-dropdown-aside', node);
16267
16268          if (!Utils.isMobile && dropdownAsides.length) {
16269            dropdownList = $('.js-dropdown-list', node);
16270
16271            dropdownList.menuAim({
16272              activate: function(trigger) {
16273                that.showAside($(trigger));
16274              },
16275              deactivate: function(trigger) {
16276                that.hideAside($(trigger));
16277              }
16278            });
16279          }
16280        });
16281
16282        // Show the dropdown
16283        that.triggers.on('click', function(e) {
16284          e.stopPropagation();
16285
16286          that.show($(this));
16287        });
16288      }
16289    },
16290
16291    hide: function(dropdownBox) {
16292      dropdownBox.fadeOut('fast');
16293
16294      $('html').off('click');
16295
16296      if (Utils.isMobile) {
16297        $('body').css('overflow', 'auto');
16298      }
16299    },
16300
16301    hideAside: function(trigger) {
16302      var that = this;
16303      var aside = $('.js-dropdown-aside', trigger);
16304
16305      if (aside.length) {
16306        var dropdown = aside.parents('.js-dropdown');
16307
16308        dropdown.removeClass(that.asideVisibleClass);
16309        trigger.removeClass(that.asideTriggerActiveClass);
16310        aside.hide();
16311      }
16312    },
16313
16314    show: function(trigger) {
16315      var that = this;
16316      var dropdown = trigger.parents('.js-dropdown');
16317      var dropdownBox = $('.js-dropdown-box', dropdown);
16318      var dropdownBoxes = $('.js-dropdown-box', that.nodes);
16319
16320      if (dropdownBox.is(':visible')) {
16321        dropdownBoxes.fadeOut('fast');
16322
16323        return;
16324      }
16325
16326      dropdownBoxes.fadeOut('fast');
16327      dropdownBox.fadeIn('fast');
16328
16329      $('html').on('click', function(e) {
16330        that.hide(dropdownBox);
16331      });
16332
16333      if (Utils.isMobile) {
16334        $('body').css('overflow', 'hidden');
16335      }
16336    },
16337
16338    showAside: function(trigger) {
16339      var that = this;
16340      var aside = $('.js-dropdown-aside', trigger);
16341
16342      if (aside.length) {
16343        var dropdown = aside.parents('.js-dropdown');
16344
16345        dropdown.addClass(that.asideVisibleClass);
16346        trigger.addClass(that.asideTriggerActiveClass);
16347        aside.show();
16348      }
16349    }
16350  };
16351
16352  Dropdown.init();
16353
16354  return Dropdown;
16355});
16356/**
16357* Fak
16358* @namespace Verkami
16359* @class Fak
16360*/
16361
16362var name = 'Verkami/Fak';
16363var deps = [
16364  'Verkami/Scroll',
16365  'Verkami/Settings',
16366  'Verkami/Utils'
16367];
16368
16369modulejs.define(name, deps, function(Scroll, Settings, Utils) {
16370  var Fak = {
16371    nodes: [],
16372    visibleClass: 'title--visible',
16373
16374    init: function() {
16375      var that = this;
16376      that.nodes = $('.js-fak');
16377
16378      if (that.nodes.length) {
16379        var answers = [];
16380        var questions = [];
16381
16382        that.nodes.each(function() {
16383          answers = $('.answer', this);
16384          questions = $('.title', this);
16385
16386          // Hide all answers by default
16387          answers.hide();
16388
16389          // Toggle question on click
16390          questions.on('click', function() {
16391            that.toggle($(this));
16392          });
16393        });
16394
16395        // Check if there is any question anchored to the URL, and show it
16396        that.checkHash();
16397      }
16398    },
16399
16400    checkHash: function() {
16401      var that = this;
16402      var hash = Utils.hash.get();
16403
16404      // If there is any question anchored, open it and scroll down to it.
16405      if (hash) {
16406        hashQuestion = $('#' + hash);
16407
16408        if (hashQuestion.length) {
16409          setTimeout(function() {
16410            var title = hashQuestion.children('.title');
16411
16412            // Show all the answer parents in which the hashQuestion is anidated.
16413            title.parentsUntil(that.nodes, '.answer').toggleClass(that.visibleClass).slideToggle();
16414            that.toggle(title);
16415          }, Settings.speed * 4);
16416
16417          setTimeout(function() {
16418            Scroll.smooth.doScroll(hashQuestion, 200);
16419          }, Settings.speed * 6);
16420        }
16421      }
16422    },
16423
16424    toggle: function(trigger) {
16425      var that = this;
16426
16427      if (Utils.isMobile) {
16428        trigger.toggleClass(that.visibleClass).next('.answer').toggle();
16429      } else {
16430        trigger.toggleClass(that.visibleClass).next('.answer').slideToggle();
16431      }
16432    }
16433  };
16434
16435  Fak.init();
16436
16437  return Fak;
16438});
16439/**
16440* Faq
16441* @namespace Verkami
16442* @class Faq
16443*/
16444
16445var name = 'Verkami/Faq';
16446var deps = [
16447  'Verkami/Utils'
16448];
16449
16450modulejs.define(name, deps, function(Utils) {
16451  var Faq = {
16452    nodes: [],
16453    visibleClass: 'faq__item__question--visible',
16454
16455    init: function() {
16456      var that = this;
16457      that.nodes = $('.js-faq');
16458
16459      if (that.nodes.length) {
16460        var answers = [];
16461        var questions = [];
16462
16463        that.nodes.each(function() {
16464          answers = $('.js-faq-answer', this);
16465          questions = $('.js-faq-question', this);
16466
16467          // Hide all answers by default
16468          answers.hide();
16469
16470          // Toggle question on click
16471          questions.on('click', function() {
16472            that.toggle($(this), questions);
16473          });
16474        });
16475      }
16476    },
16477
16478    toggle: function(trigger, questions) {
16479      var that = this;
16480
16481      if (Utils.isMobile) {
16482        trigger.toggleClass(that.visibleClass).next('.js-faq-answer').toggle();
16483      } else {
16484        trigger.toggleClass(that.visibleClass).next('.js-faq-answer').slideToggle();
16485      }
16486    }
16487  };
16488
16489  Faq.init();
16490
16491  return Faq;
16492});
16493/**
16494 * Form
16495 * @namespace Verkami
16496 * @class Form
16497 */
16498
16499var name = "Verkami/Form";
16500var deps = ["Verkami/Modal", "Verkami/Scroll", "Verkami/Settings", "Verkami/Utils"];
16501
16502modulejs.define(name, deps, function (Modal, Scroll, Settings, Utils) {
16503  var Form = {
16504    init: function () {
16505      var that = this;
16506      that.characterCounter.init();
16507      that.emptyCheck.init();
16508      that.numeric.init();
16509      that.select.init();
16510      that.submit.init();
16511      that.textfield.init();
16512      that.validate.init();
16513
16514      setTimeout(function () {
16515        that.scrollToErrors();
16516      }, Settings.speed);
16517
16518      // Clear errors once use the form field
16519      $("body").on("change paste keyup", ".form-item__error", function () {
16520        $(this)
16521          .removeClass("form-item__error")
16522          .siblings(".form-item__error-message")
16523          .slideUp(function () {
16524            $(this).remove();
16525          });
16526      });
16527    },
16528
16529    characterCounter: {
16530      nodes: [],
16531      cssClass: "form-textarea__counter",
16532      cssClassExceeded: "form-textarea__counter--exceeded",
16533
16534      init: function () {
16535        var that = this;
16536        that.setupNewNodes();
16537      },
16538
16539      setupNewNodes: function () {
16540        var that = this;
16541        that.nodes = $(".js-counter");
16542
16543        //Select nodes that haven't been setup yet
16544        var newNodes = that.nodes.filter(function () {
16545          return !$(this).data("moduleFormCharacterCounterSetupDone");
16546        });
16547
16548        if (newNodes.length) {
16549          autosize(newNodes);
16550
16551          newNodes.each(function () {
16552            that.setCounter($(this));
16553          });
16554
16555          newNodes.data("moduleFormCharacterCounterSetupDone", true);
16556        }
16557      },
16558
16559      setCounter: function (node) {
16560        var that = this;
16561        var counter = node;
16562        var limit = parseInt(counter.attr("data-counter-limit"));
16563        var cssClass = counter.attr("data-counter-class") || that.cssClass;
16564        var cssClassExceeded = counter.attr("data-counter-class-exceeded") || that.cssClassExceeded;
16565
16566        // Plugin only allows '%1' as the placeholder
16567        var counterLabel = counter.attr("data-counter-label").replace("%{chars}", "%1");
16568
16569        node.characterCounter({
16570          block: true,
16571          limit: limit,
16572          counterWrapper: "div",
16573          counterCssClass: cssClass,
16574          counterFormat: counterLabel,
16575          counterExceededCssClass: cssClassExceeded,
16576        });
16577      },
16578    },
16579
16580    emptyCheck: {
16581      emptyCheckNodes: [],
16582      errorClass: "form-item__error",
16583      submitLoadingClass: "button--loading",
16584
16585      init: function () {
16586        var that = this;
16587        that.emptyCheckNodes = $(".js-empty-check");
16588
16589        that.events();
16590      },
16591
16592      events: function () {
16593        var that = this;
16594
16595        // Validate on submit
16596        $(".js-empty-check-submit", that.emptyCheckNodes).on("click", function (e) {
16597          var emptyCheckSubmit = $(this);
16598          var emptyCheck = emptyCheckSubmit.parents(".js-empty-check");
16599          var emptyCheckInputs = $(".js-empty-check-input", emptyCheck).filter(function () {
16600            return $(this).is(":visible") === true;
16601          });
16602          var emptyCheckGroups = $(".js-empty-check-group", emptyCheck).filter(function () {
16603            return $(this).is(":visible") === true;
16604          });
16605
16606          if (emptyCheckInputs.length) {
16607            that.checkInputs(emptyCheckInputs, e);
16608          }
16609
16610          if (emptyCheckGroups.length) {
16611            that.checkGroups(emptyCheckGroups, emptyCheckSubmit, e);
16612          }
16613        });
16614      },
16615
16616      checkGroups: function (emptyCheckGroups, emptyCheckSubmit, e) {
16617        var that = this;
16618        var groupInputs = [];
16619        var groupInputsLength = 0;
16620        var groupInput = [];
16621        var groupInputValue = "";
16622        var groupModalTriggerId = {};
16623
16624        emptyCheckGroups.each(function () {
16625          groupInputs = $("input:checkbox, input:radio", this);
16626          groupInputsLength = groupInputs.length;
16627
16628          groupInputs.each(function (i) {
16629            groupInput = $(this);
16630            groupInputValue = groupInput.is(":checked");
16631            groupModalTriggerId = {
16632              modalTrigger: groupInput.data("empty-check-modal-trigger"),
16633            };
16634
16635            if (!groupInputValue && i + 1 == groupInputsLength) {
16636              e.stopImmediatePropagation();
16637              e.preventDefault();
16638
16639              if (emptyCheckSubmit.hasClass("js-submit")) {
16640                Form.submit.defaultState(emptyCheckSubmit);
16641              }
16642
16643              if (groupModalTriggerId.length) {
16644                Modal.show(modalTriggerId);
16645              }
16646
16647              if (groupInputs.closest(".form-item").hasClass(that.errorClass)) {
16648                groupInputs.closest(".form-item").removeClass(that.errorClass);
16649
16650                setTimeout(function () {
16651                  groupInputs.closest(".form-item").addClass(that.errorClass);
16652                }, Settings.speed);
16653              } else {
16654                groupInputs.closest(".form-item").addClass(that.errorClass);
16655              }
16656
16657              groupInputs.one("change", function () {
16658                groupInputs.closest(".form-item").removeClass(that.errorClass);
16659              });
16660
16661              return false;
16662            } else if (groupInputValue) {
16663              groupInputs.closest(".form-item").removeClass(that.errorClass);
16664
16665              return false;
16666            }
16667          });
16668        });
16669      },
16670
16671      checkInputs: function (emptyCheckInputs, e) {
16672        var that = this;
16673        var inputValue = "";
16674        var modalData = {};
16675
16676        emptyCheckInputs.each(function () {
16677          var input = $(this);
16678          inputValue = input.val();
16679          modalData = {
16680            modalTrigger: input.data("empty-check-modal-trigger"),
16681          };
16682
16683          if (!inputValue) {
16684            e.stopImmediatePropagation();
16685            e.preventDefault();
16686
16687            Modal.show(modalData);
16688
16689            if (input.hasClass(that.errorClass)) {
16690              input.removeClass(that.errorClass);
16691
16692              setTimeout(function () {
16693                input.addClass(that.errorClass);
16694              }, Settings.speed);
16695            } else {
16696              input.addClass(that.errorClass);
16697            }
16698
16699            input.one("keyup", function () {
16700              $(this).removeClass(that.errorClass);
16701            });
16702          } else {
16703            input.removeClass(that.errorClass);
16704          }
16705        });
16706      },
16707    },
16708
16709    showInputErrors: function (inputMapping, errors, form, submit) {
16710      submit = typeof submit !== "undefined" ? submit : $(".js-submit", form);
16711
16712      $.each(errors, function (_index, error) {
16713        let errorNode = {};
16714        let input = {};
16715
16716        for (let name in error) {
16717          if (error.hasOwnProperty(name) && inputMapping[name]) {
16718            input = $(`input[name="${inputMapping[name]}"]`, form);
16719
16720            // Create the error message placeholder and fill it
16721            errorNode = $("<div>", {
16722              class: "form-item__error-message",
16723            }).html(error[name]);
16724
16725            // Append each error to its input
16726            errorNode.appendTo(input.closest('[class*="form-item"]'));
16727
16728            // Remove error message if user is typing
16729            input.one("keyup", function () {
16730              Form.error("hide", $(this));
16731
16732              $(this)
16733                .closest('[class*="form-item"]')
16734                .find(".form-item__error-message")
16735                .slideUp("fast", function () {
16736                  $(this).remove();
16737                });
16738              submit.prop("disabled", false);
16739            });
16740
16741            // Highlight the error
16742            Form.error("show", input, true);
16743          }
16744        }
16745      });
16746    },
16747
16748    error: function (action, nodes, removeErrorOnInput) {
16749      var errorClass = "form-item--error";
16750      var formItemClass = "form-item";
16751      var node = [];
16752      var wrapper = [];
16753
16754      nodes.each(function () {
16755        node = $(this);
16756        wrapper = node.closest('[class*="' + formItemClass + '"]');
16757
16758        if (wrapper.length) {
16759          switch (action) {
16760            case "hide":
16761              wrapper.removeClass(errorClass);
16762              break;
16763            case "show":
16764              wrapper.removeClass(errorClass);
16765
16766              setTimeout(function () {
16767                wrapper.addClass(errorClass);
16768
16769                node.one("keyup", function () {
16770                  wrapper.removeClass(errorClass);
16771                });
16772                node.one("click", function () {
16773                  wrapper.removeClass(errorClass);
16774                });
16775              }, Settings.speed);
16776              break;
16777          }
16778        }
16779      });
16780    },
16781
16782    reset: function (form) {
16783      var that = this;
16784      var inputs = $(":input", form);
16785
16786      // Hide errors
16787      that.error("hide", inputs);
16788
16789      // Reset and clean inputs
16790      inputs.each(function () {
16791        if ($(this).hasClass("js-non-resettable")) {
16792          return true;
16793        } else {
16794          switch (this.type) {
16795            case "password":
16796            case "text":
16797            case "textarea":
16798            case "date":
16799            case "number":
16800            case "tel":
16801            case "email":
16802              $(this).val("");
16803              break;
16804            case "select-one":
16805              $(this).find("option:eq(0)").prop("selected", true);
16806              Form.select.refresh($(this));
16807              break;
16808            case "checkbox":
16809            case "radio":
16810              this.checked = false;
16811              break;
16812          }
16813        }
16814      });
16815    },
16816
16817    numeric: {
16818      nodes: [],
16819
16820      init: function () {
16821        var that = this;
16822        var node = [];
16823        var decimalSeparator = "";
16824        that.nodes = $(".js-numeric");
16825
16826        if (that.nodes.length) {
16827          that.nodes.each(function () {
16828            node = $(this);
16829            decimalSeparator = node.attr("data-numeric-decimal-separator");
16830
16831            if (decimalSeparator) {
16832              node.numeric({
16833                decimal: decimalSeparator,
16834                decimalPlaces: 2,
16835              });
16836            } else {
16837              node.numeric();
16838            }
16839          });
16840        }
16841      },
16842    },
16843
16844    select: {
16845      nodes: [],
16846
16847      init: function () {
16848        var that = this;
16849        that.nodes = $(".js-select");
16850
16851        if (that.nodes.length && !Utils.isMobile) {
16852          $("select", that.nodes).fancySelect({
16853            includeBlank: true,
16854          });
16855        }
16856      },
16857
16858      refresh: function (nodes) {
16859        var node = [];
16860
16861        if (nodes.length && !Utils.isMobile) {
16862          nodes.each(function () {
16863            node = $(this);
16864
16865            if (node.hasClass("fancified")) {
16866              node.removeClass("fancified");
16867              node.siblings().remove();
16868              node.unwrap(".fancy-select");
16869            }
16870
16871            node.fancySelect({
16872              includeBlank: true,
16873            });
16874          });
16875        }
16876      },
16877    },
16878
16879    scrollToErrors: function () {
16880      var error = $(".form-item__error").first();
16881      var errorTop = 0;
16882      var errorBottom = 0;
16883      var viewportTop = 0;
16884      var viewportBottom = 0;
16885      var isVisible = 0;
16886
16887      if (error.length) {
16888        errorTop = error.offset().top;
16889        errorBottom = error.offset().top + error.outerHeight();
16890        viewportTop = $(window).scrollTop();
16891        viewportBottom = viewportTop + $(window).height();
16892        isVisible = viewportBottom > errorTop && viewportTop < errorBottom;
16893
16894        if (!isVisible) {
16895          error.removeClass("form-item__error");
16896
16897          Scroll.smooth.doScroll(error, 200);
16898
16899          setTimeout(function () {
16900            error.addClass("form-item__error");
16901          }, Settings.speed * 2);
16902        }
16903      }
16904    },
16905
16906    submit: {
16907      nodes: [],
16908      submitErrorClass: "button--error",
16909      submitLoadingClass: "button--loading",
16910      submitSuccessClass: "button--success",
16911
16912      init: function () {
16913        const that = this;
16914        that.nodes = $(".js-submit");
16915
16916        if (that.nodes.length) {
16917          that.nodes.on("click", function () {
16918            that.loadingState($(this));
16919          });
16920        }
16921      },
16922
16923      defaultState: function (target) {
16924        const that = this;
16925        const submitDefaultText = target.attr("data-submit-default-text");
16926
16927        if (submitDefaultText) {
16928          if (target.is("input")) {
16929            target.val(submitDefaultText);
16930          } else {
16931            target.html(submitDefaultText);
16932          }
16933        }
16934
16935        target.removeClass(`${that.submitLoadingClass} ${that.submitSuccessClass}`).attr("disabled", false);
16936      },
16937
16938      disabledState: function (target) {
16939        const that = this;
16940        const submitDefaultText = target.attr("data-submit-default-text");
16941
16942        if (submitDefaultText) {
16943          if (target.is("input")) {
16944            target.val(submitDefaultText);
16945          } else {
16946            target.html(submitDefaultText);
16947          }
16948        }
16949
16950        target.removeClass(`${that.submitLoadingClass} ${that.submitSuccessClass}`).attr("disabled", true);
16951      },
16952
16953      errorState: function (target) {
16954        const that = this;
16955        const submitDefaultText = target.attr("data-submit-default-text");
16956        const submitErrorText = target.attr("data-submit-error-text");
16957
16958        if (submitErrorText) {
16959          if (target.is("input")) {
16960            target.val(submitErrorText);
16961          } else {
16962            target.html(submitErrorText);
16963          }
16964        }
16965
16966        target.removeClass(that.submitLoadingClass).addClass(that.submitErrorClass);
16967
16968        setTimeout(function () {
16969          target.removeClass(that.submitErrorClass);
16970
16971          if (submitDefaultText) {
16972            if (target.is("input")) {
16973              target.val(submitDefaultText);
16974            } else {
16975              target.html(submitDefaultText);
16976            }
16977          }
16978        }, Settings.speed * 12);
16979      },
16980
16981      loadingState: function (target) {
16982        const that = this;
16983        let submitDefaultText = "";
16984        const submitLoadingText = target.attr("data-submit-text");
16985
16986        if (submitLoadingText) {
16987          // Get default text
16988          if (target.is("input")) {
16989            submitDefaultText = target.val();
16990          } else {
16991            submitDefaultText = target.html();
16992          }
16993
16994          // Save default text in a new attribute
16995          target.attr("data-submit-default-text", submitDefaultText);
16996
16997          if (target.is("input")) {
16998            target.val(submitLoadingText);
16999          } else {
17000            target.html(submitLoadingText);
17001          }
17002        }
17003
17004        target.blur().addClass(that.submitLoadingClass);
17005      },
17006
17007      successState: function (target) {
17008        const that = this;
17009        const submitSuccessText = target.attr("data-submit-success-text");
17010        const keepSuccess = Boolean(target.attr("data-submit-keep-success"));
17011
17012        if (submitSuccessText) {
17013          if (target.is("input")) {
17014            target.val(submitSuccessText);
17015          } else {
17016            target.html(submitSuccessText);
17017          }
17018        }
17019
17020        target.removeClass(that.submitLoadingClass).addClass(that.submitSuccessClass);
17021
17022        if (!keepSuccess) {
17023          setTimeout(function () {
17024            that.defaultState(target);
17025          }, Settings.speed * 12);
17026        }
17027      },
17028    },
17029
17030    textfield: {
17031      nodes: [],
17032
17033      init: function () {
17034        var that = this;
17035        var node = [];
17036        that.nodes = $(".js-textfield");
17037
17038        if (that.nodes.length) {
17039          that.nodes.each(function () {
17040            node = $(this);
17041
17042            autosize(node);
17043
17044            node.on("trigger.vk.textfield.autosize", function () {
17045              trigger.vk.textfield.autosize($(this));
17046            });
17047          });
17048        }
17049      },
17050    },
17051
17052    validate: {
17053      errorClass: "form-item--error",
17054      urls: [],
17055
17056      init: function () {
17057        var that = this;
17058        var isValid = false;
17059        that.urls = $(".js-validate-url");
17060
17061        that.urls.on("blur", function () {
17062          var input = $(this);
17063          var wrapper = input.parents(".form-item");
17064          isValid = that.url(input.val());
17065
17066          if (isValid) {
17067            wrapper.removeClass(that.errorClass);
17068          } else {
17069            wrapper.addClass(that.errorClass);
17070          }
17071        });
17072      },
17073
17074      email: function (value) {
17075        var regExp = /^[A-Z0-9._%+-]+@([A-Z0-9-]+\.)+[A-Z]{2,25}$/i;
17076        var isValid = regExp.test(value);
17077
17078        return isValid;
17079      },
17080
17081      url: function (value) {
17082        var regExp =
17083          /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
17084        var isValid = regExp.test(value);
17085
17086        return isValid;
17087      },
17088    },
17089  };
17090
17091  Form.init();
17092
17093  return Form;
17094});
17095/**
17096 * Modal
17097 * @namespace Verkami
17098 * @class Modal
17099 */
17100
17101var deps = ["Verkami/DataTransfer", "Verkami/Password", "Verkami/Settings", "Verkami/Utils", "Verkami/Captcha"];
17102
17103modulejs.define("Verkami/Modal", deps, function (DataTransfer, Password, Settings, Utils, Captcha) {
17104  var Modal = {
17105    nodes: [],
17106    closes: [],
17107    triggers: [],
17108    visibleClass: "modal--visible",
17109    bodyVisibleClass: "modal-visible",
17110
17111    init: function () {
17112      var that = this;
17113      that.nodes = $(".js-modal");
17114
17115      if (that.nodes.length) {
17116        that.closes = $(".js-modal-close");
17117        that.triggers = $(".js-modal-trigger");
17118
17119        // Initialize callbacks
17120        that._callbacks();
17121
17122        // Close modal trigger
17123        that.closes.on("click.vk.modal.close", function (e) {
17124          var modalId = $(this).closest(".js-modal").data("modal-id");
17125          var jumpToModal = $(this).hasClass("js-modal-trigger");
17126          var noPropagate = $(this).attr("data-modal-no-propagate");
17127
17128          if (noPropagate) {
17129            e.stopImmediatePropagation();
17130          }
17131          e.preventDefault();
17132
17133          that.hide(modalId, jumpToModal);
17134        });
17135
17136        // Open modal trigger
17137        that.triggers.on("click.vk.modal.open", function (e) {
17138          var modalTrigger = $(this);
17139          var modalData = modalTrigger.data();
17140          var noPropagate = modalTrigger.attr("data-modal-no-propagate");
17141
17142          if (noPropagate) {
17143            e.stopImmediatePropagation();
17144          }
17145          e.preventDefault();
17146
17147          that.show(modalData);
17148        });
17149
17150        // Autoshow modals controller
17151        that.autoTrigger();
17152      }
17153    },
17154
17155    // @todo This method should be refactored to adopt the Module#setupNewNodes
17156    // idiom that is used in Share, Follow and Cards.
17157    refresh: function () {
17158      var that = this;
17159      that.nodes = $(".js-modal");
17160      that.closes = $(".js-modal-close");
17161      that.triggers = $(".js-modal-trigger");
17162
17163      that.closes.off("click.vk.modal.close").on("click.vk.modal.close", function (e) {
17164        var modalId = $(this).parents(".js-modal").data("modal-id");
17165        var jumpToModal = $(this).hasClass("js-modal-trigger");
17166        var noPropagate = $(this).attr("data-modal-no-propagate");
17167
17168        if (noPropagate) {
17169          e.stopImmediatePropagation();
17170        }
17171        e.stopPropagation();
17172        e.preventDefault();
17173
17174        that.hide(modalId, jumpToModal);
17175      });
17176
17177      that.triggers.off("click.vk.modal.open").on("click.vk.modal.open", function (e) {
17178        var modalTrigger = $(this);
17179        var modalId = modalTrigger.attr("data-modal-trigger");
17180        var modalData = modalTrigger.data();
17181        var modal = $(".js-modal").filter(function () {
17182          return $(this).attr("data-modal-id") === modalId;
17183        });
17184
17185        var noPropagate = modalTrigger.attr("data-modal-no-propagate");
17186
17187        if (noPropagate) {
17188          e.stopImmediatePropagation();
17189        }
17190        e.preventDefault();
17191
17192        modal.data("modalId", modalId);
17193        modalTrigger.data("modalTrigger", modalId);
17194
17195        that.show(modalData);
17196      });
17197      Captcha.setupNewNodes();
17198    },
17199
17200    _callbacks: function () {
17201      var that = this;
17202      var modalId = "";
17203
17204      $(document).on("trigger.vk.modal.close", ".js-modal", function () {
17205        modalId = $(this).attr("data-modal-id");
17206
17207        that.hide(modalId);
17208      });
17209
17210      $(document).on("trigger.vk.modal.setup", ".js-modal", function () {
17211        modalId = $(this).attr("data-modal-id");
17212
17213        that.setup(modalId);
17214      });
17215    },
17216
17217    // A modal is shown getting its ID from the URL hash
17218    //
17219    // Usage:
17220    // ------
17221    //
17222    // [URL]#modal=[NAME]
17223    // Where [NAME] is the modal ID, defined in data-modal-id attribute inside the modal template.
17224    autoTrigger: function () {
17225      var that = this;
17226      var modalData = {
17227        modalTrigger: Utils.hash.pick("modal"),
17228      };
17229
17230      setTimeout(function () {
17231        that.show(modalData);
17232      }, Settings.speed);
17233    },
17234
17235    custom: {
17236      init: function (modalData, callback) {
17237        var that = this;
17238
17239        switch (modalData.modalTrigger) {
17240          case "auth_dialog":
17241            that.auth(modalData, callback);
17242            break;
17243          case (modalData.modalTrigger.match("^blogs_preview") || {}
17243).input:
17244            that.blogPreview(modalData, callback);
17245            break;
17246          case (modalData.modalTrigger.match("^embed") || {}).input:
17247            $(document).trigger({
17248              type: "trigger.vk.widget.getIframe",
17249              modalData: modalData,
17250            });
17251
17252            callback.resolve(true);
17253            break;
17254          case (modalData.modalTrigger.match("^payments_paypal_backer_failed") || {}).input:
17255            that.paymentPayPalError(modalData, callback);
17256            break;
17257          case (modalData.modalTrigger.match("^pledges_process") || {}).input:
17258            that.pledge(modalData, callback);
17259            break;
17260          case "translation_missing":
17261            that.translationMissing(modalData, callback);
17262            break;
17263          default:
17264            callback.resolve(true);
17265            return true;
17266        }
17267      },
17268
17269      auth: function (modalData, callback) {
17270        var modal = Modal.get(modalData.modalTrigger);
17271
17272        // Save custom redirect if modal trigger sent it
17273        $(".js-login, .js-signup, .js-auth-facebook, .js-auth-google", modal).attr("data-auth-redirect", modalData.authRedirect);
17274
17275        // Refresh password visibility toggles
17276        Password.init();
17277
17278        // Refresh auth forms
17279        $(document).trigger("trigger.vk.user.setup");
17280
17281        callback.resolve(true);
17282      },
17283
17284      blogPreview: function (modalData, callback) {
17285        var modal = Modal.get(modalData.modalTrigger);
17286        var trigger = $('.js-modal-trigger[data-modal-trigger="' + modalData.modalTrigger + '"]');
17287        var editor = trigger.closest("form").find(".js-editor");
17288        var previewCallback = $.Deferred();
17289
17290        // Load spinner
17291        var loading = $("<div/>").addClass("modal-loading");
17292
17293        // @todo: Check if it's possible to avoid the speed attribute
17294        loading.appendTo("body").fadeIn(Settings.speed, function () {
17295          $("body").addClass("modal-visible");
17296        });
17297
17298        $.when(previewCallback).done(function (response) {
17299          if (response) {
17300            DataTransfer.transfer(trigger.data());
17301
17302            var images = $(".js-modal-content", modal).find("img");
17303            var imagesCount = images.length;
17304            var imagesLoaded = 0;
17305
17306            if (imagesCount) {
17307              images.each(function () {
17308                $(this).on("load", function () {
17309                  imagesLoaded = imagesLoaded + 1;
17310
17311                  if (imagesLoaded === imagesCount) {
17312                    loading.fadeOut();
17313
17314                    callback.resolve(true);
17315                  }
17316                });
17317              });
17318            } else {
17319              loading.fadeOut();
17320
17321              callback.resolve(true);
17322            }
17323          }
17324        });
17325
17326        // Get Editor preview
17327        editor.trigger("trigger.vk.editor.getPreview", {
17328          delay: true,
17329          callback: previewCallback,
17330        });
17331      },
17332
17333      paymentPayPalError: function (modalData, callback) {
17334        var modal = Modal.get(modalData.modalTrigger);
17335        var errorsPlaceholder = $(".js-paypal-failed-errors", modal);
17336
17337        errorsPlaceholder.html(modalData.pledgePaymentRetryErrorContent);
17338
17339        callback.resolve(true);
17340      },
17341
17342      pledge: function (modalData, callback) {
17343        var modal = Modal.get(modalData.modalTrigger);
17344        var pledgeNode = modal.hasClass("js-pledge") ? modal : $(".js-pledge", modal);
17345        var modalHeight = $(".modal__box__inner", modal).outerHeight();
17346        var viewportHeight = Utils.getViewportSize("height");
17347        var modalVerticalGutter = 0;
17348        var modalMaxHeight = 0;
17349
17350        if (Utils.isDesktop) {
17351          modalVerticalGutter = 30;
17352          modalMaxHeight = viewportHeight - modalVerticalGutter * 2;
17353        } else {
17354          modalVerticalGutter = 60;
17355          var pledgeAsideHeight = $(".js-pledge-aside", modal).outerHeight();
17356          modalMaxHeight = viewportHeight - pledgeAsideHeight - modalVerticalGutter - modalVerticalGutter / 2;
17357        }
17358
17359        // Refresh auth forms
17360        $(document).trigger("trigger.vk.user.setup");
17361
17362        // Refresh password visibility toggles
17363        Password.init();
17364
17365        if (modalHeight > modalMaxHeight) {
17366          $(".js-pledge-content", pledgeNode).outerHeight(modalMaxHeight);
17367        } else {
17368          $(".js-pledge-content", pledgeNode).outerHeight(modalHeight);
17369        }
17370
17371        callback.resolve(true);
17372      },
17373
17374      translationMissing: function (modalData, callback) {
17375        var modal = Modal.get(modalData.modalTrigger);
17376        var localesWrapper = $(".js-locale-missing-languages", modal);
17377        var localeNames = "";
17378
17379        // Split locale names by comma if there are several
17380        if (modalData.localesMissing.length > 1) {
17381          localeNames = modalData.localesMissing.join(", ");
17382        } else {
17383          localeNames = modalData.localesMissing;
17384        }
17385
17386        // Print locale names in the modal placeholder
17387        localesWrapper.html(localeNames);
17388
17389        callback.resolve(true);
17390      },
17391    },
17392
17393    get: function (modalId) {
17394      var that = this;
17395
17396      var modal = that.nodes.filter(function () {
17397        return $(this).data("modal-id") === modalId;
17398      });
17399
17400      return modal;
17401    },
17402
17403    getAsync: function (modal, modalId, modalAsync) {
17404      var that = this;
17405      var loading = $("<div/>").addClass("modal-loading");
17406
17407      loading.appendTo("body").fadeIn(function () {
17408        that.setupBody();
17409      });
17410
17411      $.ajax({
17412        type: "GET",
17413
17414        url: modalAsync,
17415        dataType: "html",
17416        error: function () {
17417          loading.fadeOut(function () {
17418            that.setupBody(true);
17419          });
17420        },
17421        success: function (response) {
17422          var callback = $.Deferred();
17423          var modalData = {
17424            modalTrigger: modalId,
17425          };
17426
17427          $(".js-modal-content", modal).html(response);
17428
17429          that.refresh();
17430
17431          $.when(callback).done(function () {
17432            that.setup(modalId);
17433
17434            $(window).resize(function () {
17435              that.setup(modalId);
17436            });
17437
17438            modal.addClass(that.visibleClass);
17439
17440            modal.trigger("hook.vk.modal.open", [modalData]);
17441
17442            setTimeout(function () {
17443              loading.fadeOut();
17444            }, Settings.speed);
17445          });
17446
17447          that.custom.init(modalData, callback);
17448        },
17449      });
17450    },
17451
17452    hide: function (modalId, jumpToModal) {
17453      var that = this;
17454      var modal = that.get(modalId);
17455
17456      if (!jumpToModal && $("." + that.visibleClass).length === 1) {
17457        that.setupBody(true);
17458      }
17459
17460      modal.removeClass(that.visibleClass);
17461    },
17462
17463    loading: {
17464      timeout: null,
17465      visibleClass: "modal__loading--visible",
17466
17467      hide: function (node) {
17468        var that = this;
17469
17470        clearTimeout(that.timeout);
17471
17472        node.removeClass(that.visibleClass);
17473      },
17474
17475      show: function (node) {
17476        var that = this;
17477
17478        clearTimeout(that.timeout);
17479
17480        that.timeout = setTimeout(function () {
17481          node.addClass(that.visibleClass);
17482        }, Settings.speed);
17483      },
17484    },
17485
17486    moveToBodyEnd: function (modalId) {
17487      var that = this;
17488      var modal = that.get(modalId);
17489      var isBodyChild = modal.parent().is("body");
17490
17491      if (!isBodyChild) {
17492        $("body").append(modal.detach());
17493      }
17494    },
17495
17496    setup: function (modalId) {
17497      var that = this;
17498      var modalBox = [];
17499      var modalBoxInner = [];
17500      var viewportHeight = Utils.getViewportSize("height");
17501      var nodes = modalId ? that.get(modalId) : that.nodes;
17502      var modalTopGutter = 0;
17503      var modalBottomGutter = 0;
17504      var modalHeight = 0;
17505      var modalOffset = 0;
17506      var modalVerticalGutter = 0;
17507      var modalMaxHeight = 0;
17508      var scrollHeight = 0;
17509      var scrollTraveled = 0;
17510      var scrollableOpacity = 0;
17511
17512      nodes.each(function () {
17513        modalBox = $(".modal__box", $(this));
17514        modalBoxInner = $(".modal__box__inner", modalBox);
17515        modalTopGutter = 30;
17516
17517        // Reset old Modal-setup changes
17518        modalBox.css("margin-top", 0);
17519        modalBoxInner.css("height", "auto");
17520
17521        if (Utils.isMobile) {
17522          modalHeight = modalBox.outerHeight();
17523          modalBottomGutter = 10;
17524
17525          if ($(this).hasClass("modal--closable") || $(this).hasClass("modal--closable--full")) {
17526            modalTopGutter = 54;
17527          } else {
17528            modalTopGutter = 10;
17529          }
17530
17531          modalMaxHeight = viewportHeight - modalTopGutter - modalBottomGutter;
17532
17533          // console.log('viewportHeight', viewportHeight);
17534          // console.log('modalHeight', modalHeight);
17535          // console.log('modalMaxHeight', modalMaxHeight);
17536          // console.log('modalTopGutter', modalTopGutter);
17537          // console.log('modalBottomGutter', modalBottomGutter);
17538
17539          if (modalHeight > modalMaxHeight) {
17540            modalBoxInner.outerHeight(modalMaxHeight);
17541            modalBox.css("margin-top", modalTopGutter);
17542
17543            // Show scrollable gradient
17544            $(this).addClass("modal--scrollable");
17545
17546            $(".modal__box__scrollable", modalBox).css("opacity", 1);
17547
17548            // Fade out scrollable gradient while scrolling down
17549            modalBoxInner.off("scroll.vk.modal").on("scroll.vk.modal", function () {
17550              scrollHeight = modalBoxInner[0].scrollHeight - modalMaxHeight;
17551              scrollTraveled = (modalBoxInner[0].scrollTop * 100) / scrollHeight;
17552              scrollableOpacity = (100 - scrollTraveled) / 100;
17553
17554              $(".modal__box__scrollable", modalBox).css("opacity", scrollableOpacity);
17555            });
17556          } else {
17557            modalOffset = (viewportHeight - modalHeight) / 2;
17558            // Hide scrollable gradient
17559            $(this).removeClass("modal--scrollable");
17560
17561            // Fade out scrollable gradient while scrolling down
17562            modalBoxInner.off("scroll.vk.modal");
17563
17564            modalBoxInner.outerHeight(modalHeight);
17565            modalBox.css("margin-top", modalOffset);
17566          }
17567        } else {
17568          if (typeof modalBox.data("modal-height") !== "undefined") {
17569            modalHeight = modalBox.data("modal-height");
17570          } else {
17571            modalHeight = modalBox.outerHeight();
17572            modalBox.data("modal-height", modalHeight);
17573          }
17574
17575          modalOffset = (viewportHeight - modalHeight) / 2;
17576
17577          if (Utils.isTablet) {
17578            modalTopGutter = 60;
17579            modalBottomGutter = 30;
17580            modalMaxHeight = viewportHeight - modalTopGutter - modalBottomGutter;
17581          } else {
17582            modalVerticalGutter = 30;
17583            modalMaxHeight = viewportHeight - modalVerticalGutter * 2;
17584          }
17585
17586          if (modalHeight > modalMaxHeight) {
17587            modalOffset = (viewportHeight - modalMaxHeight) / 4;
17588            modalBoxInner.outerHeight(modalMaxHeight);
17589            modalBox.css("margin-top", modalTopGutter);
17590
17591            // Show scrollable gradient
17592            $(this).addClass("modal--scrollable");
17593
17594            $(".modal__box__scrollable", modalBox).css("opacity", 1);
17595
17596            // Fade out scrollable gradient while scrolling down
17597            modalBoxInner.off("scroll.vk.modal").on("scroll.vk.modal", function () {
17598              scrollHeight = modalBoxInner[0].scrollHeight - modalMaxHeight;
17599              scrollTraveled = (modalBoxInner[0].scrollTop * 100) / scrollHeight;
17600              scrollableOpacity = (100 - scrollTraveled) / 100;
17601
17602              $(".modal__box__scrollable", modalBox).css("opacity", scrollableOpacity);
17603            });
17604          } else {
17605            // Hide scrollable gradient
17606            $(this).removeClass("modal--scrollable");
17607
17608            // Fade out scrollable gradient while scrolling down
17609            modalBoxInner.off("scroll.vk.modal");
17610
17611            modalBoxInner.outerHeight(modalHeight);
17612            modalBox.css("margin-top", modalOffset);
17613          }
17614        }
17615      });
17616    },
17617
17618    setupBody: function (remove) {
17619      var that = this;
17620      var body = $("body");
17621
17622      if (remove) {
17623        body.removeClass(that.bodyVisibleClass);
17624      } else {
17625        body.addClass(that.bodyVisibleClass);
17626      }
17627    },
17628
17629    show: function (modalData) {
17630      var that = this;
17631      var modalId = modalData.modalTrigger;
17632      var modal = that.get(modalId);
17633      var modalAsync = modal.data("modal-async");
17634
17635      if (modalAsync) {
17636        that.getAsync(modal, modalId, modalAsync);
17637        return;
17638      }
17639
17640      if (modal.length) {
17641        var callback = $.Deferred();
17642
17643        $.when(callback).done(function () {
17644          that.setup(modalId);
17645
17646          $(window).resize(function () {
17647            that.setup(modalId);
17648          });
17649
17650          modal.trigger("hook.vk.modal.open", [modalData]);
17651
17652          setTimeout(function () {
17653            that.setupBody();
17654            modal.addClass(that.visibleClass);
17655          }, Settings.speed);
17656        });
17657
17658        that.custom.init(modalData, callback);
17659      }
17660    },
17661  };
17662
17663  Modal.init();
17664
17665  return Modal;
17666});
17667/**
17668* PopUp
17669* @namespace Verkami
17670* @class PopUp
17671*/
17672
17673var name = 'Verkami/PopUp';
17674
17675modulejs.define(name, function() {
17676  var PopUp = {
17677    popupNodes: [],
17678
17679    init: function() {
17680      var that = this;
17681      that.popupNodes = $('.js-popup');
17682
17683      if (that.popupNodes.length) {
17684        var popupSize;
17685
17686        $.each(that.popupNodes, function(index, val) {
17687          popupSize = {
17688            width: $(this).data('popup-width'),
17689            height: $(this).data('popup-height')
17690          };
17691
17692          $(this).on('click', function(e) {
17693            e.preventDefault();
17694
17695            window.open(
17696              $(this).attr('href'),
17697              'title',
17698              'width=' + popupSize.width + ',height=' + popupSize.height
17699            );
17700          });
17701        });
17702      }
17703    }
17704  };
17705
17706  PopUp.init();
17707
17708  return PopUp;
17709});
17710/**
17711* ReadMore
17712* @namespace Verkami
17713* @class ReadMore
17714*/
17715
17716var name = 'Verkami/ReadMore';
17717var deps = [
17718  'Verkami/Settings'
17719];
17720
17721modulejs.define(name, deps, function(Settings) {
17722  var ReadMore = {
17723    nodes: [],
17724
17725    init: function() {
17726      var that = this;
17727      that.nodes = $('.js-read-more');
17728
17729      if (that.nodes.length) {
17730        that.nodes.each(function() {
17731          that.setup($(this));
17732        });
17733      }
17734    },
17735
17736    expand: function(trigger) {
17737      var that = this;
17738      var node = trigger.parents('.js-read-more');
17739      var nodeHeight = parseInt(node.attr('data-read-more-height'));
17740
17741      node.attr('aria-expanded', 'true');
17742      node.css({
17743        'max-height': nodeHeight,
17744        'overflow': 'auto'
17745      });
17746
17747      trigger.hide();
17748    },
17749
17750    getBackground: function(node) {
17751      var that = this;
17752
17753      // Is current element's background color set?
17754      var color = node.css('background-color');
17755
17756      if ((color !== 'rgba(0, 0, 0, 0)') && (color !== 'transparent')) {
17757        return color;
17758      }
17759
17760      // If not: are you at the body element?
17761      if (node.is('body')) {
17762        return node.css('background-color');
17763      } else {
17764        return that.getBackground(node.parent());
17765      }
17766    },
17767
17768    setup: function(node) {
17769      var that = this;
17770
17771      if (!node.hasClass('js-read-more')) {
17772        node = $('.js-read-more', node);
17773      }
17774
17775      if (node.length) {
17776        var isExpanded = (node.attr('aria-expanded') === 'true');
17777        var maxRows = parseInt(node.attr('data-read-more-rows'));
17778        var nodeHeight = node.outerHeight();
17779        var rowHeight = parseInt(node.css('line-height'));
17780        var maxHeight = rowHeight * maxRows + 1; // Hack: Firefox could add decimals and increment the height in 1px
17781        var trigger = $('.js-read-more-trigger', node);
17782        var triggerTop = maxHeight - rowHeight;
17783        var triggerBg = that.getBackground(node);
17784
17785        if (isExpanded && nodeHeight > maxHeight) {
17786          node.attr('data-read-more-height', nodeHeight);
17787          node.attr('aria-expanded', 'false');
17788          node.css({
17789            'position': 'relative',
17790            'max-height': maxHeight,
17791            'overflow': 'hidden',
17792            'transition': 'max-height ' + Settings.speed / 1000 + 's'
17793          });
17794
17795          trigger.css({
17796            'display': 'block',
17797            'background-color': triggerBg,
17798            'padding-left': 4,
17799            'position': 'absolute',
17800            'top': triggerTop,
17801            'right': 0
17802          });
17803
17804          node.on('click', '.js-read-more-trigger', function() {
17805            that.expand($(this));
17806          });
17807        } else if (!isExpanded) {
17808          node.attr('aria-expanded', 'true');
17809
17810          node.css({
17811            'max-height': 'none',
17812            'overflow': 'auto'
17813          });
17814
17815          trigger.hide();
17816
17817          that.setup(node);
17818        }
17819      }
17820    }
17821  };
17822
17823  ReadMore.init();
17824
17825  return ReadMore;
17826});
17827/**
17828 * Share
17829 * @namespace Verkami
17830 * @class Share
17831 */
17832
17833var name = "Verkami/Share";
17834var deps = [
17835  "Verkami/Settings",
17836  "Verkami/Utils"
17837];
17838
17839modulejs.define(name, deps, function (Settings, Utils) {
17840  var Share = {
17841    nodes: [],
17842    listVisibleClass: "share__list--visible",
17843    timeout: null,
17844
17845    init: function () {
17846      var that = this;
17847      that.setupNewNodes();
17848    },
17849
17850    setupNewNodes: function () {
17851      var that = this;
17852      that.nodes = $(".js-share");
17853
17854      //Select nodes that haven't been setup yet
17855      var newNodes = that.nodes.filter(function () {
17856        return !$(this).data("moduleShareSetupDone");
17857      });
17858
17859      if (newNodes.length) {
17860        newNodes.each(function () {
17861          that.copyUrl.init($(this));
17862        });
17863
17864        that.events(newNodes);
17865
17866        newNodes.data("moduleShareSetupDone", true);
17867      }
17868    },
17869
17870    copyUrl: {
17871      feedbackDelay: 4000,
17872
17873      init: function (node) {
17874        var that = this;
17875        var shareCopyUrl = $(".js-share-copy-url", node);
17876        var feedback = $(".js-share-copy-url-feedback", node);
17877
17878        if (shareCopyUrl.length) {
17879          that.copy(shareCopyUrl, feedback);
17880        }
17881      },
17882
17883      copy: function (shareCopyUrl, feedback) {
17884        var that = this;
17885
17886        new Clipboard(shareCopyUrl[0], {
17887          text: function (trigger) {
17888            feedback.fadeIn().delay(that.feedbackDelay).fadeOut();
17889            return $(trigger).attr("href");
17890          }
17891        });
17892      }
17893    },
17894
17895    events: function (nodes) {
17896      var that = this;
17897
17898      // Prevent refresh page after copying the url
17899      nodes.on("click.Share", ".js-share-copy-url", function (e) {
17900        e.preventDefault();
17901      });
17902
17903      // Toggle share list
17904      if (!Utils.isMobile && !Utils.isTablet) {
17905        nodes.on("mouseenter.Share", function () {
17906          that.toggle("show", $(this));
17907        });
17908
17909        nodes.on("mouseleave.Share", function () {
17910          that.toggle("hide", $(this));
17911        });
17912      }
17913    },
17914
17915    toggle: function (action, node) {
17916      var that = this;
17917      var list = $(".js-share-list", node);
17918
17919      if (action === "show") {
17920        clearTimeout(that.timeout);
17921
17922        // Show the share node
17923        list.addClass(that.listVisibleClass);
17924
17925        // Hide other share nodes
17926        that.nodes.not(node).find(".js-share-list").removeClass(that.listVisibleClass);
17927      } else if (action === "hide") {
17928        // Hide the share node after a little delay
17929        that.timeout = setTimeout(function () {
17930          list.removeClass(that.listVisibleClass);
17931        }, Settings.speed);
17932      }
17933    }
17934  };
17935
17936  Share.init();
17937
17938  return Share;
17939});
17940/**
17941 * Sticky
17942 * @namespace Verkami
17943 * @class Sticky
17944 */
17945
17946var name = "Verkami/Sticky";
17947var deps = ["Verkami/Scroll", "Verkami/Settings", "Verkami/Utils"];
17948
17949modulejs.define(name, deps, function (Scroll, Settings, Utils) {
17950  var Sticky = {
17951    nodes: [],
17952    nodesMobile: [],
17953    activeClass: "bar--sticky",
17954
17955    init: function () {
17956      var that = this;
17957      that.nodes = $(".js-sticky");
17958      that.nodesMobile = $(".js-sticky-mobile");
17959      var node = [];
17960      var nodeMobile = [];
17961
17962      setTimeout(function () {
17963        // Run sticky nodes
17964        if (that.nodes.length && !Utils.isMobile && !Utils.isTablet) {
17965          that.nodes.attr("data-sticky", 0);
17966
17967          that.nodes.each(function () {
17968            node = $(this);
17969
17970            that.stick(node, that.nodes);
17971          });
17972
17973          $(document).on("scroll", function () {
17974            that.nodes.each(function () {
17975              node = $(this);
17976
17977              that.stick(node, that.nodes);
17978            });
17979          });
17980        }
17981
17982        // Run sticky nodes in mobile
17983        if (that.nodesMobile.length && Utils.isMobile) {
17984          that.nodesMobile.attr("data-sticky", 0);
17985
17986          that.nodesMobile.each(function () {
17987            nodeMobile = $(this);
17988
17989            that.stick(nodeMobile, that.nodesMobile);
17990          });
17991
17992          $(document).on("scroll", function () {
17993            that.nodesMobile.each(function () {
17994              nodeMobile = $(this);
17995
17996              that.stick(nodeMobile, that.nodesMobile);
17997            });
17998          });
17999        }
18000      }, Settings.speed * 2);
18001    },
18002
18003    getOffset: function () {
18004      var that = this;
18005      var nodes = [];
18006      var offset = 0;
18007
18008      if (Utils.isMobile || Utils.isTablet) {
18009        nodes = that.nodesMobile.filter(function () {
18010          return parseInt($(this).attr("data-sticky")) === 1;
18011        });
18012      } else {
18013        nodes = that.nodes.filter(function () {
18014          return parseInt($(this).attr("data-sticky")) === 1;
18015        });
18016      }
18017
18018      nodes.each(function () {
18019        offset += $(this).outerHeight();
18020      });
18021
18022      return offset;
18023    },
18024
18025    stick: function (node, nodes) {
18026      var that = this;
18027      var scrollPosition = Scroll.position();
18028      var stickyHeight = node.outerHeight();
18029      var stickyOffset = 0;
18030      var nextElement = node.nextAll(":visible").first();
18031      var nextElementTopPadding = 0;
18032      var isStuck = false;
18033      var stickyOthersHeight = 0;
18034      var activeClass = node.data("sticky-class") || that.activeClass;
18035
18036      if (!nextElement.length) {
18037        nextElement = node.parent();
18038      }
18039
18040      if (nextElement.attr("data-sticky-padding") === undefined) {
18041        nextElement.attr("data-sticky-padding", parseInt(nextElement.css("padding-top")));
18042      }
18043
18044      if (!node.attr("data-sticky-offset")) {
18045        if (Utils.isMobile) {
18046          node.attr("data-sticky-offset", node.offset().top + stickyHeight);
18047        } else {
18048          node.attr("data-sticky-offset", node.offset().top);
18049        }
18050      }
18051
18052      nextElementTopPadding = parseInt(nextElement.attr("data-sticky-padding"));
18053      stickyOffset = node.attr("data-sticky-offset");
18054
18055      nodes.not(node).each(function () {
18056        isStuck = parseInt($(this).attr("data-sticky"));
18057
18058        if (isStuck) {
18059          stickyOthersHeight += $(this).outerHeight();
18060        }
18061      });
18062
18063      if (scrollPosition >= stickyOffset - stickyOthersHeight) {
18064        if (!parseInt(node.attr("data-sticky"))) {
18065          if (node.data("sticky-lock-width")) {
18066            node.css("width", node.outerWidth());
18067          }
18068          if (Utils.isMobile) {
18069            node.css("bottom", stickyOthersHeight);
18070          } else {
18071            node.css("top", stickyOthersHeight);
18072          }
18073
18074          node.attr("data-sticky", 1).addClass(activeClass);
18075          nextElement.css("padding-top", nextElementTopPadding + stickyHeight);
18076        }
18077      } else {
18078        if (parseInt(node.attr("data-sticky"))) {
18079          if (node.data("sticky-lock-width")) {
18080            node.css("width", "");
18081          }
18082          node.attr("data-sticky", 0).removeClass(activeClass).css("top", "auto");
18083          nextElement.css("padding-top", nextElementTopPadding);
18084        }
18085      }
18086    },
18087  };
18088
18089  Sticky.init();
18090
18091  return Sticky;
18092});
18093/**
18094 * Switch Content (same as Toggle but using radio buttons and 2 possible contents, hidden and shown)
18095 * @namespace Verkami
18096 * @class Switcher
18097 */
18098
18099var name = "Verkami/Switcher";
18100var deps = ["Verkami/Settings"];
18101
18102modulejs.define(name, deps, function (Settings) {
18103  const Switcher = {
18104    nodes: [],
18105
18106    init: function () {
18107      const that = this;
18108      that.nodes = $(".js-switcher");
18109
18110      if (that.nodes.length) {
18111        that.nodes.each(function () {
18112          that.setup($(this));
18113        });
18114      }
18115    },
18116
18117    setup: function (node) {
18118      const that = this;
18119
18120      if (!node.hasClass("js-switcher")) {
18121        node = $(".js-switcher", node);
18122      }
18123
18124      if (node.length) {
18125        const onContent = $(".js-switcher-content[data-switcher-on]", node);
18126        const offContent = $(".js-switcher-content[data-switcher-off]", node);
18127
18128        // Let's determine the content that should be shown by default
18129        const checkedToggleValue = $(".js-switcher-toggle:checked", node).val();
18130        const shouldDisplayContent = !!+checkedToggleValue;
18131        if (shouldDisplayContent) {
18132          offContent.hide();
18133        } else {
18134          onContent.hide();
18135        }
18136
18137        node.on("change.switcher", ".js-switcher-toggle", function (e) {
18138          const node = $(this).closest(".js-switcher");
18139          const action = Boolean(parseInt(this.value));
18140
18141          that.switch(node, action);
18142        });
18143      }
18144    },
18145
18146    switch: function (node, show) {
18147      const offContent = $(".js-switcher-content[data-switcher-off]", node);
18148      const onContent = $(".js-switcher-content[data-switcher-on]", node);
18149
18150      if (show) {
18151        onContent.slideDown();
18152        offContent.slideUp();
18153      } else {
18154        offContent.slideDown();
18155        onContent.slideUp();
18156      }
18157    },
18158  };
18159
18160  Switcher.init();
18161
18162  return Switcher;
18163});
18164/**
18165 * Tabs
18166 * @namespace Verkami
18167 * @class Tabs
18168 */
18169
18170var name = "Verkami/Tabs";
18171var deps = [
18172  "Verkami/Carousel",
18173  "Verkami/Utils"
18174];
18175
18176modulejs.define(name, deps, function (Carousel, Utils) {
18177  var Tabs = {
18178    nodes: [],
18179    triggerActiveClass: "tabs__item--active",
18180
18181    init: function () {
18182      var that = this;
18183      that.nodes = $(".js-tabs");
18184
18185      if (that.nodes.length) {
18186        that.nodes.each(function () {
18187          that.setup($(this));
18188        });
18189      }
18190
18191      that.callbacks();
18192
18193      that.events();
18194    },
18195
18196    callbacks: function () {
18197      var that = this;
18198
18199      $(document).on("trigger.vk.tabs.setup", ".js-tabs", function () {
18200        that.setup($(this));
18201      });
18202    },
18203
18204    events: function () {
18205      var that = this;
18206
18207      // Toggle tab contents by clicking a trigger
18208      $(document).on("click.vk.tabs.toggle", ".js-tabs-trigger", function () {
18209        var trigger = $(this);
18210        var node = trigger.closest(".js-tabs");
18211        var triggers = $(".js-tabs-trigger", node);
18212        var contents = $(".js-tabs-content", node);
18213        var i = triggers.index(trigger);
18214
18215        if (!trigger.hasClass(that.triggerActiveClass)) {
18216          that.toggleContents(contents, i);
18217          that.toggleTriggers(trigger);
18218        }
18219      });
18220    },
18221
18222    setup: function (node) {
18223      var that = this;
18224      var triggers = $(".js-tabs-trigger", node);
18225      var contents = $(".js-tabs-content", node);
18226      var trigger = [];
18227      var triggerActive = [];
18228      var triggerActiveMobile = [];
18229      var isActive;
18230      var activeIndex = "unknown";
18231
18232      // Check for specific active tab in mobile devices
18233      if (Utils.isMobile && !Utils.hash.get()) {
18234        triggerActiveMobile = triggers.filter(function () {
18235          return $(this).data("tabs-active-mobile");
18236        });
18237
18238        if (triggerActiveMobile.length) {
18239          activeIndex = triggers.index(triggerActiveMobile);
18240
18241          triggers.removeClass(that.triggerActiveClass);
18242          triggerActiveMobile.addClass(that.triggerActiveClass);
18243
18244          triggerActive = triggerActiveMobile;
18245        }
18246      }
18247
18248      // If active trigger is not previusly defined, find it by class
18249      if (!triggerActive.length) {
18250        triggers.each(function (index, el) {
18251          trigger = $(this);
18252          isActive = trigger.hasClass(that.triggerActiveClass);
18253
18254          if (isActive) {
18255            activeIndex = triggers.index(trigger);
18256            return true;
18257          }
18258        });
18259      }
18260
18261      if (activeIndex == "unknown") {
18262        triggers.first().addClass(that.triggerActiveClass);
18263
18264        contents.slice(1).hide();
18265      } else {
18266        contents.not(":eq(" + activeIndex + ")").hide();
18267      }
18268
18269      // Emit a callback to be used if needed in other components
18270      node.trigger("hook.vk.tabs.ready");
18271    },
18272
18273    toggleContents: function (contents, activeIndex) {
18274      if (Utils.isMobile) {
18275        contents.hide().eq(activeIndex).show();
18276      } else {
18277        contents.slideUp().eq(activeIndex).slideDown();
18278      }
18279
18280      // Emit a special event to use it as a callback
18281      contents.eq(activeIndex).trigger("hook.vk.tabs.show", [activeIndex]);
18282    },
18283
18284    toggleTriggers: function (activeTrigger) {
18285      var that = this;
18286
18287      activeTrigger.siblings().removeClass(that.triggerActiveClass);
18288      activeTrigger.addClass(that.triggerActiveClass);
18289    }
18290  };
18291
18292  Tabs.init();
18293
18294  return Tabs;
18295});
18296/**
18297 * Toggle Content
18298 * @namespace Verkami
18299 * @class Toggle
18300 */
18301
18302var name = "Verkami/Toggle";
18303var deps = ["Verkami/Settings"];
18304
18305modulejs.define(name, deps, function (Settings) {
18306  const Toggle = {
18307    nodes: [],
18308
18309    init: function () {
18310      const that = this;
18311      that.setupNewNodes();
18312    },
18313
18314    setupNewNodes: function () {
18315      var that = this;
18316      that.nodes = $(".js-toggle");
18317
18318      var newNodes = that.nodes.filter(function () {
18319        return !$(this).data("moduleToggleSetupDone");
18320      });
18321
18322      if (newNodes.length) {
18323        newNodes.each(function () {
18324          that.setup($(this));
18325        });
18326        newNodes.data("moduleToggleSetupDone", true);
18327      }
18328    },
18329
18330    toggle: function (node) {
18331      const content = $(".js-toggle-content", node).first();
18332      const isExpanded = node.attr("data-toggle-expanded") === "true";
18333      const triggerCollapse = $(".js-toggle-trigger-collapse", node).first();
18334      const triggerExpand = $(".js-toggle-trigger-expand", node).first();
18335
18336      if (isExpanded) {
18337        node.attr("data-toggle-expanded", "false");
18338        content.attr("aria-expanded", "false");
18339        triggerCollapse.hide();
18340        triggerExpand.show();
18341        content.slideUp();
18342      } else {
18343        node.attr("data-toggle-expanded", "true");
18344        content.attr("aria-expanded", "true");
18345        triggerCollapse.show();
18346        triggerExpand.hide();
18347        content.slideDown();
18348      }
18349    },
18350
18351    setup: function (node) {
18352      const that = this;
18353
18354      if (!node.hasClass("js-toggle")) {
18355        node = $(".js-toggle", node).first();
18356      }
18357
18358      if (node.length) {
18359        node.off("click.toggle", ".js-toggle-trigger:first").on("click.toggle", ".js-toggle-trigger:first", function (e) {
18360          e.preventDefault();
18361          that.toggle(node);
18362        });
18363      }
18364    },
18365  };
18366
18367  Toggle.init();
18368
18369  return Toggle;
18370});
18371/**
18372* Url
18373* @namespace Verkami
18374* @class Url
18375*/
18376
18377var name = 'Verkami/Url';
18378
18379modulejs.define(name, function() {
18380  var Url = {
18381    nodes: [],
18382
18383    init: function() {
18384      var that = this;
18385      var name = '';
18386      var source = '';
18387      that.nodes = $('.js-url');
18388
18389      if (that.nodes.length) {
18390        that.nodes.on('click', function() {
18391          name = $(this).attr('data-url-name');
18392          source = $(this).attr('data-url-source');
18393
18394          if (source) {
18395            that.update({ page: name }, source);
18396          }
18397        });
18398      }
18399    },
18400
18401    update: function(name, source) {
18402      history.pushState(name, null, source);
18403    }
18404  };
18405
18406  Url.init();
18407
18408  return Url;
18409});
18410/**
18411 * Video
18412 * @namespace Verkami
18413 * @class Video
18414 */
18415
18416modulejs.define("Verkami/Video", function () {
18417  var Video = {
18418    nodes: [],
18419    ratio: 1.77777777778, // 16:9 by default, set `data-video-ratio` to use another
18420    events: {
18421      resize: "resize.vk.video",
18422    },
18423
18424    init: function () {
18425      var that = this;
18426      that.nodes = $(".js-video");
18427
18428      if (that.nodes.length) {
18429        that.initialize(that.nodes);
18430      }
18431    },
18432
18433    initialize: function (nodes) {
18434      var that = this;
18435      var node = [];
18436      nodes = nodes.filter(function () {
18437        return !$(this).attr("data-video-initialized");
18438      });
18439
18440      if (nodes.length) {
18441        nodes.each(function () {
18442          node = $(this);
18443
18444          if (node.is(":visible")) {
18445            that.setSize(node);
18446          }
18447        });
18448
18449        $(window).on(that.events.resize, function () {
18450          nodes.each(function () {
18451            node = $(this);
18452
18453            if (node.is(":visible")) {
18454              that.setSize(node);
18455            }
18456          });
18457        });
18458      }
18459    },
18460
18461    setSize: function (video) {
18462      var that = this;
18463      var videoRatio = video.data("video-ratio") ? video.data("video-ratio") : that.ratio;
18464      var currentHeight = 0;
18465      var currentWidth = 0;
18466      var currentRatio = 0;
18467      var adjustedSize = 0;
18468
18469      // Reset former values
18470      video.css({
18471        height: "",
18472        "max-width": "",
18473      });
18474
18475      // Calculate current Size and Ratio
18476      currentHeight = video.height();
18477      currentWidth = video.width();
18478      currentRatio = currentWidth / currentHeight;
18479
18480      if (videoRatio < currentRatio && isFinite(currentRatio)) {
18481        adjustedSize = parseInt(currentHeight * videoRatio);
18482
18483        // Adjust width to the desired ratio
18484        video.css("max-width", adjustedSize);
18485      } else {
18486        adjustedSize = parseInt(currentWidth / videoRatio);
18487
18488        // Adjust height to the desired ratio
18489        video.height(adjustedSize);
18490      }
18491
18492      video.attr("data-video-initialized", "true");
18493    },
18494  };
18495
18496  Video.init();
18497
18498  return Video;
18499});
18500/**
18501 * Auth
18502 * @namespace Verkami
18503 * @class Auth
18504 */
18505
18506modulejs.define(
18507  "Verkami/Auth",
18508  ["Verkami/Form", "Verkami/Settings", "Verkami/Utils"],
18509  function (Form, Settings, Utils) {
18510    const Auth = {
18511      authLayer: [],
18512
18513      init: function () {
18514        const that = this;
18515        that.authLayer = $(".js-auth");
18516
18517        sessionStorage.removeItem("auth-email");
18518        sessionStorage.removeItem("auth-gmail");
18519        sessionStorage.removeItem("auth-layer-previous");
18520        sessionStorage.setItem("auth-layer", "email");
18521
18522        that.setupBackLink();
18523
18524        that._events();
18525      },
18526
18527      _events: function () {
18528        const that = this;
18529
18530        that.authLayer.on("input.auth.email", ".js-auth-email-field", function () {
18531          if (Form.validate.email($(this).val())) {
18532            $(".js-auth-email-form .js-submit").prop("disabled", false);
18533          } else {
18534            $(".js-auth-email-form .js-submit").prop("disabled", true);
18535          }
18536        });
18537
18538        that.authLayer.on("submit.auth.verifyEmail", ".js-auth-email-form", function (e) {
18539          e.preventDefault();
18540          that.verifyEmail();
18541        });
18542
18543        that.authLayer.on("submit.auth.login", ".js-auth-login-form", function (e) {
18544          e.preventDefault();
18545          that.login();
18546        });
18547
18548        that.authLayer.on("click.auth.recoverPassword", ".js-auth-password-recovery", function (e) {
18549          const endpoint = $(this).prop("href");
18550
18551          e.preventDefault();
18552          that.recoverPassword(endpoint);
18553        });
18554
18555        that.authLayer.on("submit.auth.signup", ".js-auth-signup-form", function (e) {
18556          e.preventDefault();
18557          that.signup();
18558        });
18559
18560        that.authLayer.on("click.auth.trigger", ".js-auth-trigger", function () {
18561          const layer = $(this).data("auth-layer");
18562
18563          that.toggleLayer(layer);
18564        });
18565      },
18566
18567      fillEmailPlaceholders: function (layerName) {
18568        const that = this;
18569        const email = sessionStorage.getItem("auth-email");
18570        const layer = $(`.js-auth-layer[data-auth-layer='${layerName}']`, that.authLayer);
18571
18572        $(".js-auth-email-placeholder", layer).html(email);
18573      },
18574
18575      gmailChecking: function (email) {
18576        const that = this;
18577        const domainList = ["gmail.com"];
18578
18579        // Extract full domain from the email address
18580        const domain = email.substring(email.lastIndexOf("@") + 1);
18581
18582        // Check if the domain is present in the array of valid domains
18583        const isGmail = domainList.includes(domain);
18584
18585        if (isGmail) {
18586          $(".js-auth-gmail-only", that.authLayer).show();
18587        } else {
18588          $(".js-auth-gmail-only", that.authLayer).hide();
18589        }
18590      },
18591
18592      login: function () {
18593        const that = this;
18594        const form = $(".js-auth-login-form", that.authLayer);
18595        const submit = $(".js-submit", form);
18596        const endpoint = form.prop("action");
18597        let redirectPath = form.attr("data-auth-redirect");
18598        let errorMessage = form.attr("data-error-message");
18599        const formData = form.serializeArray();
18600        const formValues = formData.reduce(function (obj, item) {
18601          obj[item.name] = item.value;
18602          return obj;
18603        }, {});
18604
18605        // Add email address to the form data
18606        formValues["user_session[login]"] = sessionStorage.getItem("auth-email");
18607
18608        $.ajax({
18609          type: "POST",
18610          url: endpoint,
18611          data: formValues,
18612          dataType: "json",
18613          error: function () {
18614            Form.submit.errorState(submit);
18615          },
18616          success: function (response) {
18617            if (response.logged) {
18618              Form.submit.successState(submit);
18619
18620              // Go to the custom redirect URL
18621              redirectPath = redirectPath || response.redirect;
18622
18623              if (redirectPath) {
18624                Utils.redirect(redirectPath);
18625              } else {
18626                $(document).trigger("trigger.vk.auth.loggedIn");
18627              }
18628            } else {
18629              const formNames = {
18630                password: "user_session[password]",
18631              };
18632              errors = [
18633                {
18634                  password: errorMessage,
18635                },
18636              ];
18637              Form.showInputErrors(formNames, errors, form);
18638              Form.submit.errorState(submit);
18639
18640              // Show password error
18641              Form.error("show", $(".js-auth-login-password", form), true);
18642            }
18643          },
18644        });
18645      },
18646
18647      recoverPassword: function (endpoint) {
18648        const that = this;
18649        const email = sessionStorage.getItem("auth-email");
18650
18651        $.ajax({
18652          type: "POST",
18653          url: endpoint,
18654          data: {
18655            user: {
18656              email,
18657            },
18658          },
18659          dataType: "json",
18660          success: function () {
18661            that.toggleLayer("password-recovery");
18662          },
18663        });
18664      },
18665
18666      setupBackLink: function (oldLayer, layer) {
18667        const backLink = $(".js-auth-back");
18668
18669        if (["email", "password-recovery"].includes(layer) || !layer) {
18670          backLink.hide();
18671          sessionStorage.removeItem("auth-layer-previous");
18672        } else {
18673          backLink.show();
18674          backLink.attr("data-auth-layer", oldLayer);
18675        }
18676      },
18677
18678      setupPasswordLayer: function () {
18679        const that = this;
18680        const email = sessionStorage.getItem("auth-email");
18681
18682        // Check if it's a gmail account to show the Google button
18683        that.gmailChecking(email);
18684
18685        // Show user's email in specific placeholders
18686        that.fillEmailPlaceholders("password");
18687      },
18688
18689      setupSignupLayer: function () {
18690        const that = this;
18691        const email = sessionStorage.getItem("auth-email");
18692
18693        // Copy email address from the first step
18694        $(".js-auth-signup-email", that.authLayer).val(email);
18695      },
18696
18697      signup: async function () {
18698        const that = this;
18699        const formNames = {
18700          email: "user[email]",
18701          email_confirmation: "user[email_confirmation]",
18702          name: "user[name]",
18703          password: "user[password]",
18704          newsletter: "user[wants_newsletter]",
18705          terms_agreement: "user[terms_agreement]",
18706        };
18707        const form = $(".js-auth-signup-form", that.authLayer);
18708        const captchaKey = form.attr("data-captcha-key");
18709        const submit = $(".js-submit", form);
18710        const endpoint = form.prop("action");
18711        let redirectPath = form.attr("data-auth-redirect");
18712        const formData = form.serializeArray();
18713
18714        // Validate Form
18715        const formValues = formData.reduce(function (obj, item) {
18716          obj[item.name] = item.value;
18717          return obj;
18718        }, {});
18719
18720        const usernameCheck = formValues[formNames.name].length;
18721        const passwordCheck = formValues[formNames.password].length;
18722        const termsCheck = Boolean(parseInt(formValues[formNames.terms_agreement]));
18723
18724        if (!usernameCheck) {
18725          Form.error("show", $(`input[name="${formNames.name}"]`, form, true));
18726        }
18727
18728        if (!passwordCheck) {
18729          Form.error("show", $(`input[name="${formNames.password}"]`, form, true));
18730        }
18731
18732        if (!termsCheck) {
18733          Form.error("show", $(`input[name="${formNames.terms_agreement}"]`, form, true));
18734        }
18735
18736        if (!usernameCheck || !passwordCheck || !termsCheck) {
18737          Form.submit.errorState(submit);
18738          return;
18739        }
18740
18741        // Execute captcha if it's enabled
18742        if (captchaKey) {
18743          const token = await grecaptcha.execute(captchaKey, { action: "signup" });
18744
18745          formData.push(
18746            {
18747              name: "g-recaptcha-response",
18748              value: token,
18749            },
18750            {
18751              name: "g-recaptcha-version",
18752              value: "v3",
18753            }
18754          );
18755        }
18756
18757        // Send signup form to the backend
18758        $.ajax({
18759          type: "POST",
18760          url: endpoint,
18761          data: formData,
18762          dataType: "json",
18763          error: function () {
18764            Form.submit.errorState(submit);
18765          },
18766          success: function (response) {
18767            if (response.signup) {
18768              // Show success feedback in submit button
18769              Form.submit.successState(submit);
18770
18771              // Go to the custom redirect URL
18772              redirectPath = redirectPath || response.redirect;
18773
18774              if (redirectPath) {
18775                Utils.redirect(redirectPath);
18776              } else {
18777                $(document).trigger("trigger.vk.auth.signedUp");
18778              }
18779            } else {
18780              // Remove old error messages
18781              $('input[name^="user["]', form)
18782                .closest('[class*="form-item"]')
18783                .find(".form-item__error-message")
18784                .remove();
18785
18786              Form.showInputErrors(formNames, response.errors, form);
18787
18788              // Show error feedback in submit button
18789              Form.submit.errorState(submit);
18790            }
18791          },
18792        });
18793      },
18794
18795      toggleLayer: function (layer) {
18796        const that = this;
18797        const oldLayer = sessionStorage.getItem("auth-layer");
18798
18799        // Do nothing if the new layer is the same as the current one
18800        if (oldLayer === layer) return;
18801
18802        // Setup a few things depending on the new layer
18803        switch (layer) {
18804          case "password":
18805            that.setupPasswordLayer();
18806            break;
18807          case "signup":
18808            that.setupSignupLayer();
18809            break;
18810        }
18811
18812        $(`.js-auth-layer[data-auth-layer='${oldLayer}']`, that.authLayer).fadeOut(Settings.speed, function () {
18813          // Show/hide the back link depending on the step, and change its target
18814          that.setupBackLink(oldLayer, layer);
18815
18816          // Show/hide the captcha legal text depending on the step
18817          that.toggleCaptcha(layer);
18818
18819          $(`.js-auth-layer[data-auth-layer='${layer}']`, that.authLayer).fadeIn(Settings.speed);
18820        });
18821
18822        // Save current and previous layers locally
18823        sessionStorage.setItem("auth-layer-previous", oldLayer);
18824        sessionStorage.setItem("auth-layer", layer);
18825      },
18826
18827      toggleCaptcha: function (layer) {
18828        const that = this;
18829        const captcha = $(".js-auth-captcha", that.authLayer);
18830
18831        if (layer === "email") {
18832          captcha.fadeIn();
18833        } else {
18834          captcha.fadeOut();
18835        }
18836      },
18837
18838      verifyEmail: function () {
18839        const that = this;
18840        const email = $(".js-auth-email-field").val();
18841        const endpoint = $(".js-auth-email-form").prop("action");
18842        const form = $(".js-auth-email-form", that.authLayer);
18843        const submit = $(".js-submit", form);
18844
18845        const formNames = {
18846          email: "user[login]",
18847        };
18848
18849        $.ajax({
18850          type: "POST",
18851          url: endpoint,
18852          data: {
18853            user: {
18854              email,
18855            },
18856          },
18857          dataType: "json",
18858          error: function () {
18859            Form.submit.errorState($(".js-auth-email-form .js-submit"));
18860          },
18861          success: function (response) {
18862            if (response.errors.length === 0) {
18863              Form.submit.successState($(".js-auth-email-form .js-submit"));
18864
18865              sessionStorage.setItem("auth-email", email);
18866
18867              if (Utils.caseInsensitiveEqual(response.user, email)) {
18868                that.toggleLayer("password");
18869              } else {
18870                that.toggleLayer("signup");
18871              }
18872            } else {
18873              $('input[name^="user["]', form)
18874                .closest('[class*="form-item"]')
18875                .find(".form-item__error-message")
18876                .remove();
18877
18878              Form.showInputErrors(formNames, response.errors, form);
18879
18880              Form.submit.errorState(submit);
18881            }
18882          },
18883        });
18884      },
18885    };
18886
18887    Auth.init();
18888
18889    return Auth;
18890  }
18891);
18892/**
18893* Avatar
18894* @namespace Verkami
18895* @class Avatar
18896*/
18897
18898var name = 'Verkami/Avatar';
18899var deps = [
18900  'Verkami/Form',
18901  'Verkami/Settings'
18902];
18903
18904modulejs.define(name, deps, function(Form, Settings) {
18905  var Avatar = {
18906    nodes: [],
18907    csrfToken: '',
18908
18909    init: function() {
18910      var that = this;
18911      that.nodes = $('.js-avatar');
18912
18913      if (that.nodes.length) {
18914        that.csrfToken = $('meta[name="csrf-token"]').prop('content');
18915
18916        that.nodes.each(function(i) {
18917          that.create($(this), i);
18918        });
18919      }
18920    },
18921
18922    create: function(avatarModule, i) {
18923      var that = this;
18924      var avatarModal = $(this).hasClass('js-modal') ? avatarModule : avatarModule.closest('.js-modal');
18925      var avatarPlaceholders = $('.' + avatarModule.data('avatar-placeholder'));
18926      var avatarSize = parseInt(avatarModule.data('avatar-size'));
18927      var avatarTarget = avatarModule.prop('action');
18928      var avatarTrigger = $('.js-avatar-trigger', avatarModule);
18929      var ajaxHeaders = (that.csrfToken) ? { 'X_CSRF_TOKEN': that.csrfToken } : {};
18930
18931      avatarModule.prop('id', 'avatarModule' + i);
18932
18933      avatarTrigger.on('click', function(e) {
18934        // Make sure that the form isn't actually being sent.
18935        e.preventDefault();
18936        e.stopPropagation();
18937      });
18938
18939      avatarModule.dropzone({
18940        acceptedFiles: '.jpg, .png, .jpeg',
18941        headers: ajaxHeaders,
18942        hiddenInputContainer: '#avatarModule' + i,
18943        maxFilesize: 10,
18944        previewTemplate: '<div class="dz-preview dz-file-preview"><img data-dz-thumbnail /></div>',
18945        previewsContainer: '#avatarModule' + i + ' .js-avatar-preview',
18946        thumbnailWidth: avatarSize,
18947        thumbnailHeight: avatarSize,
18948        uploadMultiple: false,
18949        url: avatarTarget,
18950        clickable: '#avatarModule' + i + ' .js-avatar-trigger',
18951
18952        addedfile: function(data) {
18953          Form.submit.loadingState(avatarTrigger);
18954
18955          $('.js-avatar-cancel', avatarModule).css('visibility', 'hidden');
18956
18957          $('.js-modal-close', avatarModule).one('click.avatarCancel', function() {
18958            if (data.status != "success") {
18959              avatarModule[0].dropzone.removeAllFiles(true);
18960
18961              avatarPlaceholders.each(function() {
18962                $(this).prop('src', $(this).data('avatar-old'));
18963              });
18964            }
18965          });
18966        },
18967
18968        complete: function(data) {
18969          if (data.status == 'success') {
18970            Form.submit.successState(avatarTrigger);
18971
18972            $('.js-modal-close', avatarModule).off('click.avatarCancel');
18973
18974            setTimeout(function() {
18975              avatarModule[0].dropzone.removeAllFiles(true);
18976
18977              avatarModal.trigger('trigger.vk.modal.close');
18978            }, Settings.speed * 10);
18979          } else {
18980            Form.submit.errorState(avatarTrigger);
18981          }
18982
18983          $('.js-avatar-cancel', avatarModule).css('visibility', 'visible');
18984        },
18985
18986        thumbnail: function(data, dataUrl) {
18987          var avatarPlaceholder = [];
18988          var avatarOld = '';
18989
18990          avatarPlaceholders.each(function() {
18991            avatarPlaceholder = $(this);
18992
18993            if (avatarPlaceholder.is('img')) {
18994              avatarOld = avatarPlaceholder.attr('src');
18995              avatarPlaceholder.data('avatar-old', avatarOld).attr('src', dataUrl);
18996            } else {
18997              avatarOld = avatarPlaceholder.css('background-image');
18998              avatarPlaceholder.data('avatar-old', avatarOld).css('background-image', 'url(' + dataUrl + ')');
18999            }
19000          });
19001        }
19002      });
19003    },
19004
19005    refresh: function(imageSrc) {
19006      var avatarPlaceholders = $('.js-avatar-profile-placeholder');
19007      var avatarPlaceholder = [];
19008      var avatarOld = '';
19009
19010      avatarPlaceholders.each(function() {
19011        avatarPlaceholder = $(this);
19012
19013        if (avatarPlaceholder.is('img')) {
19014          avatarOld = avatarPlaceholder.attr('src');
19015          avatarPlaceholder.data('avatar-old', avatarOld).attr('src', imageSrc);
19016        } else {
19017          avatarOld = avatarPlaceholder.css('background-image');
19018          avatarPlaceholder.data('avatar-old', avatarOld).css('background-image', 'url(' + imageSrc + ')');
19019        }
19020      });
19021    }
19022  };
19023
19024  Avatar.init();
19025
19026  return Avatar;
19027});
19028/**
19029* Backers
19030* @namespace Verkami
19031* @class Backers
19032*/
19033
19034var name = 'Verkami/Backers';
19035
19036modulejs.define(name, function() {
19037  var Backers = {
19038    input: [],
19039    output: [],
19040    ratio: 0,
19041
19042    init: function() {
19043      var that = this;
19044      that.input = $('.js-backers-avg-input');
19045
19046      if (that.input.length) {
19047        that.output = $('.js-backers-avg-output');
19048        that.ratio = parseInt(that.output.data('avg-contribution'));
19049
19050        // Calculate backers on load
19051        that.calculate();
19052
19053        // Calculate backers every time user types something
19054        that.input.on('change paste keyup', function() {
19055          that.calculate();
19056        });
19057      }
19058    },
19059
19060    calculate: function() {
19061      var that = this;
19062      var goal = parseInt(that.input.val());
19063      var backers = parseInt(goal / that.ratio);
19064
19065      if (backers > 0) {
19066        that.output.val(backers);
19067      } else {
19068        that.output.val('');
19069      }
19070    }
19071  };
19072
19073  Backers.init();
19074
19075  return Backers;
19076});
19077/**
19078* BlogBar
19079* @namespace Verkami
19080* @class BlogBar
19081*/
19082
19083var name = 'Verkami/BlogBar';
19084var deps = [
19085  'Verkami/Scroll'
19086];
19087
19088modulejs.define(name, deps, function(Scroll) {
19089  var BlogBar = {
19090    node: [],
19091    visibleClass: 'blog-bar--visible',
19092    post: [],
19093    postOffset: null,
19094
19095    init: function() {
19096      var that = this;
19097      that.node = $('.js-blog-bar');
19098
19099      if (that.node.length) {
19100        that.post = $('.js-blog-post');
19101        that.postOffset = that.post.offset().top;
19102
19103        that.toggle();
19104
19105        $(window).scroll(function() {
19106          that.toggle();
19107        });
19108      }
19109    },
19110
19111    toggle: function() {
19112      var that = this;
19113
19114      var scrollPosition = Scroll.position();
19115
19116      if (scrollPosition > that.postOffset) {
19117        that.node.addClass(that.visibleClass);
19118      } else {
19119        that.node.removeClass(that.visibleClass);
19120      }
19121    }
19122  };
19123
19124  BlogBar.init();
19125
19126  return BlogBar;
19127});
19128/**
19129* BlogNavigation
19130* @namespace Verkami
19131* @class BlogNavigation
19132*/
19133
19134var name = 'Verkami/BlogNavigation';
19135
19136modulejs.define(name, function() {
19137  var BlogNavigation = {
19138    nodes: [],
19139
19140    init: function() {
19141      var that = this;
19142      that.nodes = $('.js-blog-nav');
19143
19144      if (that.nodes.length) {
19145        var links = [];
19146        var link = [];
19147        var separator = [];
19148        var linkWidth = 0;
19149        var separatorWidth = 0;
19150        var wrapperWidth = 0;
19151
19152        that.nodes.each(function() {
19153          links = $('.js-blog-nav-link', $(this));
19154
19155          links.each(function() {
19156            link = $(this);
19157            separator = link.siblings('.js-blog-nav-separator');
19158            
19159            // Get widths
19160            linkWidth = link.width();
19161            separatorWidth = separator.width();
19162            wrapperWidth = linkWidth + separatorWidth;
19163
19164            // Set width
19165            link.parent().width(wrapperWidth);
19166          });
19167        });
19168      }
19169    }
19170  };
19171
19172  BlogNavigation.init();
19173
19174  return BlogNavigation;
19175});
19176/**
19177 * Captcha
19178 * @namespace Verkami
19179 * @class Captcha
19180 */
19181
19182var name = "Verkami/Captcha";
19183
19184modulejs.define(name, function() {
19185  var Captcha = {
19186    nodeSelector: ".js-recaptcha",
19187    containerSelector: ".captcha-container",
19188    nodes: [],
19189    content: [],
19190    trigger: [],
19191
19192    init: function() {
19193      var that = this;
19194      that.setupNewNodes();
19195    },
19196    setupNewNodes: function() {
19197      var that = this;
19198      that.nodes = $(that.nodeSelector);
19199
19200      var newNodes = that.nodes.filter(function() {
19201        return !$(this).data("moduleCaptchaSetupDone");
19202      });
19203
19204      if (newNodes.length && !captchaUnavailable) {
19205        console.log("[CAPTCHA] New captcha nodes detected");
19206
19207        var captchaUnavailable = typeof grecaptcha === "undefined" || typeof grecaptcha.render === "undefined";
19208        if (captchaUnavailable) {
19209          console.log("[CAPTCHA] Captcha library is not available yet.");
19210        } else {
19211          newNodes.each(function(_index, node) {
19212            console.log("[CAPTCHA]   Processing captcha node...");
19213
19214            $(node).on("click", function(e) {
19215              var widgetId = $(this).data("moduleCaptchaWidgetID");
19216              e.preventDefault();
19217              console.log("[CAPTCHA] Resetting " + widgetId);
19218              grecaptcha.reset(widgetId);
19219              console.log("[CAPTCHA] Executing " + widgetId);
19220              grecaptcha.execute(widgetId);
19221            });
19222
19223            var container = $(node)
19224              .closest(".js-modal")
19225              .find(".captcha-holder")[0];
19226            var widgetId = grecaptcha.render(container, {
19227              sitekey: $(node).data("sitekey"),
19228              size: "invisible",
19229              callback: function(token) {
19230                that.submitCallback(token, node);
19231              }
19232            });
19233
19234            $(node).data("moduleCaptchaWidgetID", widgetId);
19235            console.log("[CAPTCHA]   ...setup done with id " + widgetId);
19236          });
19237          newNodes.data("moduleCaptchaSetupDone", true);
19238        }
19239      }
19240    },
19241    submitCallback: function(_token, node) {
19242      var validatedEvent = "captcha.vk.validated";
19243      var widgetId = $(node).data("moduleCaptchaWidgetID");
19244      console.log("[CAPTCHA] Processing submitCallback ID#" + widgetId+ " triggering " + validatedEvent);
19245      $(node).trigger(validatedEvent);
19246    }
19247  };
19248  return Captcha;
19249});
19250/**
19251 * Cards
19252 * @namespace Verkami
19253 * @class Cards
19254 */
19255
19256var name = "Verkami/Cards";
19257var deps = [
19258  "Verkami/Carousel",
19259  "Verkami/Settings",
19260  "Verkami/Utils"
19261];
19262
19263modulejs.define(name, deps, function (Carousel, Settings, Utils) {
19264  var Cards = {
19265    nodes: [],
19266
19267    init: function () {
19268      var that = this;
19269      that.setupNewNodes();
19270      if (that.nodes.length) {
19271        $(window).resize(function () {
19272          setTimeout(function () {
19273            that.setHeight.init();
19274          }, Settings.speed);
19275        });
19276      }
19277    },
19278
19279    setupNewNodes: function () {
19280      var that = this;
19281      that.nodes = $(".js-card");
19282
19283      var newNodes = that.nodes.filter(function () {
19284        return !$(this).data("moduleCardsSetupDone");
19285      });
19286
19287      if (newNodes.length) {
19288        newNodes.each(function () {
19289          that.excerpt.init($(this));
19290          that.review.init($(this));
19291        });
19292        newNodes.data("moduleCardsSetupDone", true);
19293        that.setHeight.init();
19294      }
19295    },
19296
19297
19298    excerpt: {
19299      init: function (card) {
19300        var that = this;
19301        var triggers = $(".js-card-excerpt-show", card);
19302
19303        if (triggers.length) {
19304          triggers.on("click", function () {
19305            that.showExcerpt($(this));
19306          });
19307        }
19308      },
19309
19310      showExcerpt: function (trigger) {
19311        trigger.fadeOut().closest(".js-card").find(".js-card-excerpt").slideDown();
19312      }
19313    },
19314
19315    review: {
19316      triggerVisibleClass: "card__review--visible",
19317
19318      init: function (card) {
19319        var that = this;
19320        var review = $(".js-review", card);
19321
19322        if (review.length && (Utils.isMobile || Utils.isTablet)) {
19323          var triggerShow = $(".js-review-show", card);
19324          var triggerHide = $(".js-review-hide", card);
19325
19326          triggerShow.on("click", function (e) {
19327            e.preventDefault();
19328            review.addClass(that.triggerVisibleClass);
19329          });
19330
19331          triggerHide.on("click", function (e) {
19332            review.removeClass(that.triggerVisibleClass);
19333          });
19334        }
19335      }
19336    },
19337
19338    setHeight: {
19339      init: function () {
19340        var that = this;
19341        var group = null;
19342        var cardsInGroup = [];
19343        var isHidden = false;
19344        var cardsPerRow = 3;
19345        var cardsInRow = [];
19346
19347        $(".js-cards").each(function () {
19348          group = $(this);
19349          cardsInGroup = $(".js-card", group);
19350
19351          if (cardsInGroup.length) {
19352            isHidden = !group.is(":visible");
19353
19354            if (isHidden) {
19355              group.show();
19356            }
19357
19358            $(".js-card-tags", cardsInGroup).removeAttr("style");
19359
19360            if (group.hasClass("js-carousel")) {
19361              that.setRowHeight(cardsInGroup);
19362            } else if (!Utils.isMobile) {
19363              if (Utils.isTablet) {
19364                cardsPerRow = 2;
19365              }
19366
19367              for (var i = 0; i < cardsInGroup.length; i += cardsPerRow) {
19368                cardsInRow = cardsInGroup.slice(i, i + cardsPerRow);
19369                that.setRowHeight(cardsInRow);
19370              }
19371            }
19372
19373            if (isHidden) {
19374              group.hide();
19375            }
19376          }
19377        });
19378      },
19379
19380      setRowHeight: function (cards) {
19381        var card;
19382        var difference = 0;
19383        var maxHeight = 0;
19384        var tagsInitialMargin = 0;
19385
19386        // Get tallest card's height
19387        cards.each(function () {
19388          card = $(this);
19389          if (card.outerHeight() > maxHeight) {
19390            maxHeight = card.outerHeight();
19391          }
19392        });
19393
19394        // Add the height difference to smaller cards, then all will have the same height
19395        cards.each(function () {
19396          card = $(this);
19397          if (card.outerHeight() < maxHeight) {
19398            tagsInitialMargin = parseInt($(".js-card-tags", card).css("margin-top"));
19399            difference = maxHeight - card.outerHeight() + tagsInitialMargin + "px";
19400            $(".js-card-tags", card).css("margin-top", difference);
19401          }
19402        });
19403      }
19404    }
19405  };
19406
19407  Cards.init();
19408
19409  return Cards;
19410});
19411/**
19412 * Carousel
19413 * @namespace Verkami
19414 * @class Carousel
19415 */
19416
19417var name = "Verkami/Carousel";
19418var deps = ["Verkami/Settings", "Verkami/Utils"];
19419
19420modulejs.define(name, deps, function (Settings, Utils) {
19421  var Carousel = {
19422    carousel: [],
19423    slideshow: [],
19424    carouselMedia: [],
19425    carouselRewards: [],
19426    carouselStats: [],
19427
19428    init: async function () {
19429      var that = this;
19430      that.carousel = $(".js-carousel");
19431      that.slideshow = $(".js-home-slideshow");
19432      that.carouselMedia = $(".js-carousel-media");
19433      that.carouselRewards = $(".js-carousel-rewards");
19434      that.carouselStats = $(".js-carousel-stats");
19435
19436      that.setupFlickity();
19437
19438      if (that.carousel.length) {
19439        that.carousel.each(function () {
19440          var carousel = $(this);
19441
19442          // This data attribute is optional, it shows a linked plus icon when the carousel ends
19443          var target = carousel.data("carousel-target");
19444          var link = target
19445            ? '<a class="carousel__more" href="' + target + '"><span class="carousel__more__icon"></span></a>'
19446            : "";
19447
19448          carousel.on("ready.flickity", function () {
19449            carousel.append(link);
19450          });
19451
19452          carousel.flickity({
19453            autoPlay: false,
19454            arrowShape:
19455              "M100,46.0502528 L100,54.0502528 L14.285,54.05 L50,90.0588744 L44.1074435,96 L1.92185743,53.4687275 C1.36520756,53.1296066 0.897900066,52.658349 0.563506539,52.098526 L0.418771097,51.9512258 L0.458351735,51.9112208 C0.16565554,51.3553323 8.2282208e-17,50.722138 0,50.0502528 C-8.54815162e-17,49.3522432 0.178788065,48.6959919 0.493067616,48.1247953 L0.418771097,48.0487742 L0.761583529,47.7018614 C1.00238436,47.3703724 1.29283986,47.0772883 1.62202636,46.8335328 L44.1074435,4 L50,9.94112562 L14.186,46.05 L100,46.0502528 Z",
19456            dragThreshold: 10,
19457            freeScroll: Utils.isMobile || Utils.isTablet,
19458            groupCells: true,
19459            pageDots: false,
19460          });
19461
19462          // If using Tabs, recalculate Carousel's height after changing the tab
19463          if (carousel.hasClass("js-tabs-content") || carousel.closest(".js-tabs-content").length) {
19464            carousel.one("hook.vk.tabs.show", function () {
19465              $(this).flickity("resize");
19466            });
19467          }
19468        });
19469      }
19470
19471      if (that.carouselMedia.length) {
19472        that.carouselMedia.flickity({
19473          autoPlay: Settings.sliders.delay,
19474          dragThreshold: 10,
19475          freeScroll: Utils.isMobile || Utils.isTablet,
19476          fade: true,
19477          prevNextButtons: false,
19478        });
19479      }
19480
19481      if (that.carouselRewards.length && Utils.isMobile) {
19482        that.carouselRewards.flickity({
19483          autoPlay: false,
19484          dragThreshold: 10,
19485          freeScroll: Utils.isMobile || Utils.isTablet,
19486          imagesLoaded: true,
19487          pageDots: false,
19488          prevNextButtons: false,
19489          contain: true,
19490        });
19491      }
19492
19493      if (that.carouselStats.length) {
19494        that.carouselStats.flickity({
19495          autoPlay: Settings.sliders.delay,
19496          dragThreshold: 10,
19497          freeScroll: Utils.isMobile || Utils.isTablet,
19498          fade: true,
19499          prevNextButtons: false,
19500        });
19501      }
19502
19503      if (that.slideshow.length) {
19504        that.slideshow.flickity({
19505          arrowShape:
19506            "M28.7187079,1.21482578e-13 L31.2058209,1.43593539 L3.167,50 L31.2058209,98.5640646 L28.7187079,100 L-1.67332814e-12,50.2577388 L0.446,50 L-5.22248911e-13,49.7422612 L28.7187079,1.21482578e-13 Z",
19507          autoPlay: Settings.sliders.delay,
19508          contain: true,
19509          fade: true,
19510          pageDots: false,
19511          wrapAround: true,
19512        });
19513      }
19514    },
19515
19516    setupFlickity: function () {
19517      Flickity.prototype._createResizeClass = function () {
19518        this.element.classList.add("flickity-resize");
19519      };
19520
19521      Flickity.createMethods.push("_createResizeClass");
19522
19523      var resize = Flickity.prototype.resize;
19524      Flickity.prototype.resize = function () {
19525        this.element.classList.remove("flickity-resize");
19526        resize.call(this);
19527        this.element.classList.add("flickity-resize");
19528      };
19529    },
19530  };
19531
19532  Carousel.init();
19533
19534  return Carousel;
19535});
19536/**
19537 * Checkout
19538 * @namespace Verkami
19539 * @class Checkout
19540 */
19541
19542modulejs.define("Verkami/Checkout", ["Verkami/Form", "Verkami/Settings", "Verkami/Utils"], function (Form, Settings, Utils) {
19543  const Checkout = {
19544    checkoutLayer: [],
19545
19546    init: function () {
19547      const that = this;
19548      this.checkoutLayer = $(".js-checkout");
19549
19550      if (!this.checkoutLayer.length) return;
19551
19552      that._events();
19553      that._hooks();
19554      that.setupCart();
19555      that.setLayerFromURL();
19556      that.checkPaymentError();
19557      //that.checkDefaultPaymentMethod();
19558    },
19559
19560    _events: function () {
19561      const that = this;
19562
19563      that.checkoutLayer.on("click.checkout.toggleLayer", ".js-checkout-toggle-layer", function () {
19564        const layer = $(this).data("checkout-layer");
19565
19566        that.toggleLayer(layer);
19567      });
19568
19569      that.checkoutLayer.on("change.fs.checkout.shippingZone", ".js-checkout-shipping-zone", async function (e) {
19570        let cart = that.getCart();
19571        const shippingZone = that.getShippingZone();
19572
19573        if (shippingZone) {
19574          cart.shipping_zone = shippingZone.id;
19575
19576          // Show loader
19577          that.enableLoader();
19578
19579          // Update addons list
19580          await that.getAddonsList(cart);
19581
19582          // Reset addons in cart
19583          cart = that.resetAddons(cart);
19584
19585          // Update cart
19586          await that.saveCart(cart, true);
19587
19588          // Update shipping label in Totals
19589          that.updateShippingZoneName(shippingZone.name);
19590
19591          // Hide loader
19592          that.disableLoader();
19593        }
19594      });
19595
19596      that.checkoutLayer.on("click.checkout.addon.add", ".js-checkout-addon-add", async function (e) {
19597        const addon = $(this).closest(".js-checkout-addon");
19598        const id = parseInt(addon.attr("data-checkout-addon-id"));
19599
19600        await that.updateAddon(addon, id, 1);
19601        that.toggleAddonSelector(addon, 1);
19602      });
19603
19604      that.checkoutLayer.on("click.checkout.addon.remove", ".js-checkout-addon-remove", async function (e) {
19605        const addon = $(this).closest(".js-checkout-addon");
19606        const id = parseInt(addon.attr("data-checkout-addon-id"));
19607
19608        await that.removeAddon(id);
19609        that.toggleAddonSelector(addon, 0);
19610      });
19611
19612      that.checkoutLayer.on("click.checkout.addon.decrease", ".js-checkout-addon-decrease", async function (e) {
19613        const addon = $(this).closest(".js-checkout-addon");
19614        const id = parseInt(addon.attr("data-checkout-addon-id"));
19615        const quantity = parseInt($(".js-checkout-addon-value", addon).val()) - 1;
19616
19617        if (quantity === 0) {
19618          await that.removeAddon(id);
19619          that.toggleAddonSelector(addon, 0);
19620        } else {
19621          await that.updateAddon(addon, id, quantity);
19622        }
19623      });
19624
19625      that.checkoutLayer.on("click.checkout.addon.increase", ".js-checkout-addon-increase", async function (e) {
19626        const addon = $(this).closest(".js-checkout-addon");
19627        const id = parseInt(addon.attr("data-checkout-addon-id"));
19628        const quantity = parseInt($(".js-checkout-addon-value", addon).val()) + 1;
19629
19630        await that.updateAddon(addon, id, quantity);
19631      });
19632
19633      that.checkoutLayer.on(
19634        "keyup.checkout.bonus",
19635        ".js-checkout-bonus",
19636        Utils.delayedCallback(function (e) {
19637          that.updateBonus($(this).val());
19638        }, Settings.speed * 4)
19639      );
19640
19641      // Avoid non-integer numbers in free pledge input
19642      that.checkoutLayer.on("keypress.checkout.bonus paste.checkout.bonus", ".js-checkout-bonus", function (e) {
19643        if (String.fromCharCode(e.keyCode).match(/[^0-9]/g)) return false;
19644      });
19645
19646      // Show/hide cart on mobile devices
19647      that.checkoutLayer.on("click.checkout.cart.toggle", ".js-checkout-cart-toggle", function (e) {
19648        that.toggleCart();
19649      });
19650
19651      that.checkoutLayer.on("change.checkout.payment.getForm", ".js-checkout-payment-type", function () {
19652        const paymentEndpoint = $(this).attr("data-checkout-payment-endpoint");
19653        const paymentType = $(this).attr("data-checkout-payment-type");
19654
19655        that.getPaymentForm(paymentEndpoint, paymentType);
19656      });
19657
19658      that.checkoutLayer.on("click.checkout.payment.pledge", ".js-checkout-payment-submit", function (e) {
19659        /*
19660            Payment types can have an additional check that overrides the regular type.
19661            An example is the untokenized "redsys" type, which has a checkbox to save the card token after the payment,
19662            this checkbox will always override its main type (redsys) if checked.
19663          */
19664        const paymentInput = $(".js-checkout-payment-type:checked", that.checkoutLayer);
19665        const additionalInput = $(".js-checkout-payment-type-additional", paymentInput.parent());
19666        const additionalType = additionalInput.length && additionalInput.is(":checked") ? additionalInput.attr("data-checkout-payment-type") : false;
19667        const paymentType = additionalType || paymentInput.attr("data-checkout-payment-type");
19668
19669        e.preventDefault();
19670
19671        that.pledge(paymentType);
19672      });
19673    },
19674
19675    _hooks: function () {
19676      const that = this;
19677
19678      this.checkoutLayer.on("checkout.cartBreakdown.loaded", function (e, cartBreakdown) {
19679        that.updateTotal(cartBreakdown);
19680        that.updateAddonsLimitations(cartBreakdown);
19681      });
19682
19683      $(document).on("trigger.vk.auth.loggedIn", function (e) {
19684        that.toggleLayer("payment");
19685      });
19686
19687      $(document).on("trigger.vk.auth.signedUp", function (e) {
19688        that.toggleLayer("payment");
19689      });
19690    },
19691
19692    checkDefaultPaymentMethod: function () {
19693      console.log("[CHECKOUT] Checking default payment method");
19694      const that = this;
19695      const defaultMethod = $(".js-checkout-payment-type", that.checkoutLayer).first();
19696      defaultMethod.prop("checked", true);
19697      defaultMethod.trigger("change.checkout.payment.getForm");
19698    },
19699
19700    checkCartExtras: function () {
19701      const that = this;
19702      const extrasWrapper = $(".js-checkout-cart-extras", that.checkoutLayer);
19703      const addonsWrapper = $(".js-checkout-cart-addons", that.checkoutLayer);
19704      const bonusWrapper = $(".js-checkout-cart-bonus", that.checkoutLayer);
19705      const cart = that.getCart();
19706      const hasAddons = Boolean(cart.addons && cart.addons.length);
19707      const hasBonus = Boolean(cart.bonus && cart.bonus >= 0);
19708      const hasExtras = hasAddons || hasBonus;
19709
19710      if (hasExtras) {
19711        extrasWrapper.fadeIn();
19712      } else {
19713        extrasWrapper.fadeOut();
19714      }
19715
19716      if (hasAddons) {
19717        addonsWrapper.fadeIn();
19718      } else {
19719        addonsWrapper.fadeOut();
19720      }
19721
19722      if (hasBonus) {
19723        bonusWrapper.fadeIn();
19724      } else {
19725        bonusWrapper.fadeOut();
19726      }
19727    },
19728
19729    checkPaymentError: function () {
19730      const errorBox = $(".js-checkout-error", this.checkoutLayer);
19731      const searchParams = new URLSearchParams(window.location.search);
19732      const errorType = searchParams.has("checkout[error]") ? searchParams.get("checkout[error]") : undefined;
19733
19734      if (errorType === "redsys") {
19735        errorBox.show();
19736      } else {
19737        errorBox.hide();
19738      }
19739    },
19740
19741    disableLoader: function () {
19742      const that = this;
19743      const loader = $(".js-checkout-loading", that.checkoutLayer);
19744
19745      loader.removeClass("checkout__loading--active");
19746    },
19747
19748    enableLoader: function () {
19749      const that = this;
19750      const loader = $(".js-checkout-loading", that.checkoutLayer);
19751
19752      loader.addClass("checkout__loading--active");
19753    },
19754
19755    getAddonsBreakdown: async function (cart) {
19756      const that = this;
19757      const addonsPlaceholder = $(".js-checkout-cart-addons", that.checkoutLayer);
19758      const endpoint = addonsPlaceholder.attr("data-checkout-addons-breakdown-endpoint");
19759      let result;
19760
19761      try {
19762        result = await $.ajax({
19763          type: "POST",
19764          url: endpoint,
19765          data: cart,
19766          dataType: "html",
19767          success: function (response) {
19768            that.checkoutLayer.trigger("checkout.addonsBreakdown.loaded", response);
19769          },
19770        });
19771
19772        if (result) {
19773          addonsPlaceholder.html(result);
19774        } else {
19775          addonsPlaceholder.html();
19776        }
19777      } catch (error) {
19778        console.error(error);
19779      }
19780    },
19781
19782    getAddonsList: async function (cart) {
19783      const that = this;
19784      const addonsPlaceholder = $(".js-checkout-addons", that.checkoutLayer);
19785      const endpoint = addonsPlaceholder.attr("data-checkout-addons-endpoint");
19786      let result;
19787
19788      try {
19789        result = await $.ajax({
19790          type: "POST",
19791          url: endpoint,
19792          data: cart,
19793          dataType: "html",
19794          success: function (response) {
19795            that.checkoutLayer.trigger("checkout.addons.loaded", response);
19796          },
19797        });
19798
19799        if (result) {
19800          addonsPlaceholder.html(result);
19801        } else {
19802          addonsPlaceholder.html();
19803        }
19804      } catch (error) {
19805        console.error(error);
19806      }
19807    },
19808
19809    getCart: function () {
19810      return JSON.parse(sessionStorage.getItem("checkout-cart"));
19811    },
19812
19813    getFirstLayer: function () {
19814      const that = this;
19815      const layersByPriority = ["customize", "auth", "payment"];
19816      const existingLayers = layersByPriority.filter((layerName) => {
19817        return $(`.js-checkout-layer[data-checkout-layer='${layerName}']`, that.checkoutLayer).length;
19818      });
19819      const layer = existingLayers[0];
19820
19821      return layer;
19822    },
19823
19824    getPaymentForm: function (endpoint, type) {
19825      console.log("[CHECKOUT] Checking payment method " + type);
19826      const that = this;
19827      const formData = that.getCart();
19828      const typeSelector = $(".js-checkout-payment-type", that.checkoutLayer);
19829      const paymentForm = $(`.js-checkout-payment-${type}`, that.checkoutLayer);
19830      const forms = $(".js-checkout-payment-forms", that.checkoutLayer);
19831      const submit = $(".js-checkout-payment-submit", that.checkoutLayer);
19832
19833      // Request payment form if it doesn't exist yet
19834      if (!paymentForm.length) {
19835        // Disable selector
19836        typeSelector.prop("disabled", true);
19837
19838        // Disable submit button
19839        Form.submit.loadingState(submit);
19840        submit.prop("disabled", true);
19841
19842        console.log("[CHECKOUT] Getting payment method for " + type);
19843        $.ajax({
19844          type: "GET",
19845          url: endpoint,
19846          data: formData,
19847          dataType: "html",
19848          success: function (response) {
19849            // Insert new payment form
19850            forms.append(response);
19851
19852            // Enable selector back
19853            typeSelector.prop("disabled", false);
19854
19855            // Enable submit button
19856            Form.submit.defaultState(submit);
19857            submit.prop("disabled", false);
19858          },
19859        });
19860      } else {
19861        // Enable submit button
19862        submit.prop("disabled", false);
19863      }
19864    },
19865
19866    getPriceBreakdown: async function () {
19867      const that = this;
19868      const endpoint = that.checkoutLayer.attr("data-checkout-price-endpoint");
19869      const cart = that.getCart();
19870      const buttonNoExtras = $(".js-checkout-customize-no-extras", that.checkoutLayer);
19871      const buttonContinue = $(".js-checkout-customize-continue", that.checkoutLayer);
19872      let result;
19873
19874      try {
19875        console.log("[CHECKOUT] Getting price breakdown");
19876        result = await $.ajax({
19877          type: "POST",
19878          url: endpoint,
19879          data: cart,
19880          dataType: "json",
19881          success: function (response) {
19882            console.log("[CHECKOUT] Price breakdown retrieved");
19883            that.checkoutLayer.trigger("checkout.cartBreakdown.loaded", response);
19884          },
19885        });
19886
19887        that.resetPaymentForms();
19888        that.checkDefaultPaymentMethod();
19889
19890        if ((result.addons && result.addons.length) || (result.extra && result.extra.units !== 0)) {
19891          buttonNoExtras.fadeOut(Settings.speed, function () {
19892            buttonContinue.fadeIn(Settings.speed);
19893          });
19894        } else {
19895          buttonContinue.fadeOut(Settings.speed, function () {
19896            buttonNoExtras.fadeIn(Settings.speed);
19897          });
19898        }
19899
19900        return result;
19901      } catch (error) {
19902        console.error(error);
19903      }
19904    },
19905
19906    getShippingZone: function () {
19907      const that = this;
19908      const shippingZoneSelect = $(".js-checkout-shipping-zone", that.checkoutLayer);
19909      const shippingZoneId = shippingZoneSelect.length ? shippingZoneSelect.val() : undefined;
19910      const shippingZoneName = shippingZoneSelect.length ? $("option:selected", shippingZoneSelect).text() : undefined;
19911
19912      return {
19913        id: shippingZoneId,
19914        name: shippingZoneName,
19915      };
19916    },
19917
19918    pledge: function (type) {
19919      const that = this;
19920      const paymentForm = $(`.js-checkout-payment-${type}`, that.checkoutLayer);
19921      const submit = $(".js-checkout-payment-submit", that.checkoutLayer);
19922
19923      // As the default text for submit sending has been used to describe the payment type selection process
19924      // e.g. "Configurando metodo de pago" here we need an extra text to represent the real submit event
19925      // to the backend
19926      submit.prop("disabled", true);
19927      const pledgingText = submit.attr("data-submit-pledging-text");
19928      submit.html(pledgingText);
19929      paymentForm.submit();
19930
19931      // Original frontend chose to move the submit to the default state but that will re-enable the submit
19932      // allowing users to click multiple times (generating in some cases multiple contributions)
19933      // I (AGR) don't know what was the rationale behind that decision but I'm removing that instruction
19934      // from the time being.
19935      // Form.submit.defaultState(submit);
19936    },
19937
19938    removeAddon: async function (id) {
19939      const that = this;
19940      const cart = that.getCart();
19941      const addonIndex = cart.addons.findIndex((addon) => addon.id === id);
19942
19943      // Show loader
19944      that.enableLoader();
19945
19946      // Remove addon from cart
19947      cart.addons.splice(addonIndex, 1);
19948
19949      // Update cart
19950      await that.saveCart(cart, true);
19951
19952      // Update addons breakdown
19953      await that.getAddonsBreakdown(cart);
19954
19955      await that.recoverDefaultLimitedValuesForAddon(id);
19956
19957      // Hide loader
19958      that.disableLoader();
19959    },
19960
19961    recoverDefaultLimitedValuesForAddon: function (addonId) {
19962      addon = $("#reward_" + addonId);
19963      addon.find(".available_units").html(addon.attr("data-base-available-units"));
19964      addon.find(".total_units").html(addon.attr("data-total-units"));
19965    },
19966
19967    resetAddons: function (cart) {
19968      cart.addons = [];
19969
19970      return cart;
19971    },
19972
19973    resetPaymentForms: function () {
19974      console.log("[CHECKOUT] Resetting payment forms");
19975
19976      const that = this;
19977      const forms = $(".js-checkout-payment-forms", that.checkoutLayer);
19978
19979      forms.empty();
19980    },
19981
19982    saveCart: async function (cart, update) {
19983      const that = this;
19984      console.log("[CHECKOUT] Saving cart");
19985
19986      sessionStorage.setItem("checkout-cart", JSON.stringify(cart));
19987
19988      if (update) {
19989        // If updating cart, remove older payment forms
19990        that.resetPaymentForms();
19991
19992        // Update total value
19993        await that.getPriceBreakdown();
19994
19995        // Check if extras wrapper has to be displayed
19996        that.checkCartExtras();
19997      }
19998    },
19999
20000    setLayerFromURL: function () {
20001      const that = this;
20002      const searchParams = new URLSearchParams(window.location.search);
20003      const layer = searchParams.has("checkout[layer]") ? searchParams.get("checkout[layer]") : undefined;
20004
20005      // Reset current layer
20006      sessionStorage.removeItem("checkout-layer");
20007
20008      if (layer) {
20009        that.toggleLayer(layer);
20010      } else {
20011        that.toggleLayer();
20012      }
20013    },
20014
20015    setupCart: function () {
20016      const that = this;
20017      const reward = that.checkoutLayer.attr("data-checkout-reward-id");
20018      const shippingZone = that.getShippingZone().id;
20019      const cart = {
20020        bonus: 0,
20021        reward: reward,
20022      };
20023
20024      if (shippingZone) {
20025        cart.shipping_zone = shippingZone;
20026      }
20027
20028      // Reset Cart
20029      sessionStorage.removeItem("checkout-cart");
20030      sessionStorage.removeItem("checkout-cart-total");
20031
20032      // Create cart
20033      that.saveCart(cart);
20034    },
20035
20036    toggleAddonSelector: function (addon, quantity) {
20037      const button = $(".js-checkout-addon-add", addon);
20038      const selector = $(".js-checkout-addon-handler", addon);
20039
20040      if (quantity === 0) {
20041        selector.fadeOut(Settings.speed * 2, function () {
20042          button.fadeIn(Settings.speed * 2);
20043        });
20044      } else {
20045        button.fadeOut(Settings.speed * 2, function () {
20046          selector.fadeIn(Settings.speed * 2);
20047        });
20048      }
20049    },
20050
20051    toggleCart: function (hide) {
20052      const that = this;
20053      const cartOpenClass = "checkout--cart-open";
20054
20055      if (hide) {
20056        that.checkoutLayer.removeClass(cartOpenClass);
20057      } else {
20058        that.checkoutLayer.toggleClass(cartOpenClass);
20059      }
20060    },
20061
20062    toggleLayer: function (layer) {
20063      const that = this;
20064      const oldLayer = sessionStorage.getItem("checkout-layer");
20065      const bar = $(".js-checkout-bar", that.checkoutLayer);
20066
20067      if (!layer) {
20068        console.log("[CHECKOUT] Toggling layer to first layer");
20069        layer = that.getFirstLayer();
20070      } else {
20071        console.log("[CHECKOUT] Toggling layer to requested: " + layer);
20072      }
20073
20074      if (oldLayer === layer) return;
20075
20076      if (Utils.isMobile) {
20077        that.toggleCart(true);
20078
20079        switch (layer) {
20080          case "auth":
20081            // Hide toggle layer button
20082            $(".js-checkout-toggle-layer", bar).hide();
20083            break;
20084
20085          case "payment":
20086            // Show payment submit instead of toggle layer button
20087            $(".js-checkout-toggle-layer", bar).hide();
20088            $(".js-checkout-payment-submit", bar).show();
20089            break;
20090
20091          default:
20092            // Hide payment submit and show toggle layer button
20093            $(".js-checkout-payment-submit", bar).hide();
20094            $(".js-checkout-toggle-layer", bar).show();
20095        }
20096      } else {
20097        switch (layer) {
20098          case "customize":
20099            bar.fadeIn();
20100            break;
20101
20102          default:
20103            bar.fadeOut();
20104        }
20105      }
20106      if (layer == "payment") {
20107        that.resetPaymentForms();
20108        that.checkDefaultPaymentMethod();
20109      }
20110
20111      if (oldLayer) {
20112        $(`.js-checkout-layer[data-checkout-layer='${oldLayer}']`, that.checkoutLayer).fadeOut(Settings.speed, function () {
20113          $("html, body").scrollTop(0);
20114          $(`.js-checkout-layer[data-checkout-layer='${layer}']`, that.checkoutLayer).fadeIn(Settings.speed);
20115        });
20116      } else {
20117        $(`.js-checkout-layer[data-checkout-layer='${layer}']`, that.checkoutLayer).fadeIn(Settings.speed);
20118      }
20119
20120      sessionStorage.setItem("checkout-layer", layer);
20121    },
20122
20123    updateAddon: async function (addon, id, quantity) {
20124      const that = this;
20125      const cart = that.getCart();
20126      const quantityPlaceholder = $(".js-checkout-addon-value", addon);
20127      const hasAddons = cart.addons && cart.addons.length;
20128      const addonIndex = hasAddons
20129        ? cart.addons.findIndex((addon) => {
20130            return addon.id === id;
20131          })
20132        : -1;
20133
20134      // Show loader
20135      that.enableLoader();
20136
20137      if (addonIndex !== -1) {
20138        cart.addons[addonIndex].quantity = quantity;
20139      } else if (hasAddons) {
20140        cart.addons.push({
20141          id: id,
20142          quantity: quantity,
20143        });
20144      } else {
20145        cart.addons = [];
20146        cart.addons.push({
20147          id: id,
20148          quantity: quantity,
20149        });
20150      }
20151
20152      await that.saveCart(cart, true);
20153
20154      // Update addons breakdown
20155      await that.getAddonsBreakdown(cart);
20156
20157      // Update input value with quantity
20158      quantityPlaceholder.val(quantity);
20159
20160      // Hide loader
20161      that.disableLoader();
20162    },
20163
20164    updateBonus: async function (amount) {
20165      const that = this;
20166      const placeholder = $(".js-checkout-bonus-placeholder", that.checkoutLayer);
20167      const cart = that.getCart();
20168
20169      // Be sure that we have an integer
20170      amount = parseInt(amount || 0);
20171
20172      if (amount >= 0 && cart.bonus !== amount) {
20173        // Show loader
20174        that.enableLoader();
20175
20176        cart.bonus = amount;
20177
20178        // Update cart
20179        await that.saveCart(cart, true);
20180
20181        // Update free pledge in cart summary
20182        placeholder.attr("data-checkout-bonus-amount", amount).html(amount);
20183
20184        // Hide loader
20185        that.disableLoader();
20186      }
20187    },
20188
20189    updateShippingZoneName: function (name) {
20190      const that = this;
20191      const namePlaceholders = $(".js-checkout-shipping-zone-label", that.checkoutLayer);
20192
20193      namePlaceholders.html(name);
20194    },
20195
20196    updateTotal: function (cartBreakdown) {
20197      const that = this;
20198
20199      $(".js-checkout-cart-total", that.checkoutLayer).html(cartBreakdown.total);
20200    },
20201
20202    updateAddonsLimitations: function (cartBreakdown) {
20203      const that = this;
20204      const limitedAddons = cartBreakdown.addons.filter(function (item) {
20205        return item.limited_units == true;
20206      });
20207
20208      // Update the legend of limited addons
20209      limitedAddons.forEach((element) => {
20210        addon = $("#reward_" + element.reward_id);
20211        addon.attr("data-limited-units", element.limited_units);
20212        addon.attr("data-base-available-units", element.available_units + element.units);
20213        addon.attr("data-total-units", element.total_units);
20214        addon.find(".available_units").html(element.available_units);
20215        addon.find(".total_units").html(element.total_units);
20216        addon.find(".js-checkout-addon-increase").prop("disabled", element.available_units <= 0);
20217      });
20218    },
20219  };
20220
20221  Checkout.init();
20222
20223  return Checkout;
20224});
20225/**
20226* Comment
20227* @namespace Verkami
20228* @class Comment
20229*/
20230
20231var name = 'Verkami/Comment';
20232
20233modulejs.define(name, function() {
20234  var Comment = {
20235    nodes: [],
20236    buttonDisabledClass: 'button--disabled',
20237
20238    init: function() {
20239      var that = this;
20240      that.nodes = $('.js-comment');
20241
20242      if (that.nodes.length) {
20243        $('.js-comment-button', that.nodes).hide().addClass(that.buttonDisabledClass);
20244
20245        $('.js-comment-button-trigger', that.nodes).on('focus', function() {
20246          $(this).parents('.js-comment').find('.js-comment-button').slideDown();
20247        });
20248
20249        $('.js-comment-button-trigger', that.nodes).on('keyup', function() {
20250          if ($.trim($(this).val())) {
20251            $(this).parents('.js-comment').find('.js-comment-button').removeClass(that.buttonDisabledClass);
20252          }
20253        });
20254      }
20255    }
20256  };
20257
20258  Comment.init();
20259
20260  return Comment;
20261});
20262/**
20263* Comments
20264* @namespace Verkami
20265* @class Comments
20266*/
20267
20268var name = 'Verkami/Comments';
20269
20270modulejs.define(name, function() {
20271  var Comments = {
20272    node: [],
20273    list: [],
20274
20275    init: function() {
20276      var that = this;
20277      var node = [];
20278      var feedback = '';
20279      that.node = $('.js-comments');
20280
20281      if (that.node.length) {
20282        that.list = $('.js-comments-list', that.node);
20283
20284        // Get next comments page
20285        that.node.on('click', '.js-comments-more', function(e) {
20286          node = $(this);
20287          feedback = node.attr('data-comments-more-feedback');
20288
20289          e.preventDefault();
20290
20291          $('a', node).html(feedback);
20292
20293          $.get($('a', node).attr('href'), function(data) {
20294            node.remove();
20295            that.list.append(data);
20296          });
20297        });
20298      }
20299    }
20300  };
20301
20302  Comments.init();
20303
20304  return Comments;
20305});
20306/**
20307 * Community
20308 * @namespace Verkami
20309 * @class Community
20310 */
20311
20312var deps = ["Verkami/Settings"];
20313
20314modulejs.define("Verkami/Community", deps, function (Settings) {
20315  var Community = {
20316    sliderPageSize: 10,
20317    sliderSpeed: Settings.speed * 25,
20318    hideClass: "community__stats__people__item--hide",
20319    showClass: "community__stats__people__item--show",
20320
20321    init: function () {
20322      var that = this;
20323      var node = $(".js-community");
20324
20325      if (node.length) {
20326        that.setup(node);
20327      }
20328
20329      that.triggers();
20330    },
20331
20332    triggers: function () {
20333      var that = this;
20334
20335      $(document).on("trigger.vk.community.setup", function (e, wrapper) {
20336        var node = $(".js-community", wrapper);
20337
20338        that.setup(node);
20339      });
20340    },
20341
20342    changeSlice: function (node, avatarsPaged) {
20343      var that = this;
20344      var sliderPage = parseInt(node.data("community-slider-page")) || 0;
20345
20346      setTimeout(
20347        function () {
20348          that.hideAvatars(avatarsPaged[sliderPage]);
20349
20350          sliderPage = parseInt(sliderPage + 2) > avatarsPaged.length ? 0 : parseInt(sliderPage + 1);
20351          node.data("community-slider-page", sliderPage);
20352
20353          setTimeout(
20354            function () {
20355              that.showAvatars(node, avatarsPaged, sliderPage);
20356            }.bind(this),
20357            Settings.speed * 4
20358          );
20359        }.bind(this),
20360        that.sliderSpeed
20361      );
20362    },
20363
20364    hideAvatars: function (avatars) {
20365      var that = this;
20366
20367      avatars.each(function (i) {
20368        $(this).addClass(that.hideClass);
20369
20370        setTimeout(
20371          function () {
20372            $(this).removeClass(that.hideClass).hide();
20373          }.bind(this),
20374          Settings.speed * 3 + (Settings.speed / 4) * i
20375        );
20376      });
20377    },
20378
20379    setup: function (node) {
20380      var that = this;
20381      var avatars = $(".js-community-avatar");
20382      var avatarsPaged = [];
20383
20384      // Enable slider if more than 1 page of avatars
20385      if (avatars.length > that.sliderPageSize) {
20386        node.data("community-slider-enabled", true);
20387
20388        avatars.slice(10).hide();
20389      }
20390
20391      avatarsPaged = that.sliceAvatars(avatars);
20392
20393      that.showAvatars(node, avatarsPaged, 0);
20394    },
20395
20396    showAvatars: function (node, avatarsPaged, sliderPage) {
20397      var that = this;
20398
20399      avatarsPaged[sliderPage].show();
20400
20401      avatarsPaged[sliderPage].each(function (i) {
20402        $(this).addClass(that.showClass);
20403
20404        setTimeout(
20405          function () {
20406            $(this).removeClass(that.showClass);
20407          }.bind(this),
20408          Settings.speed * 3 + (Settings.speed / 4) * i
20409        );
20410      });
20411
20412      if (node.data("community-slider-enabled") === true) {
20413        that.changeSlice(node, avatarsPaged);
20414      }
20415    },
20416
20417    sliceAvatars: function (avatars) {
20418      var that = this;
20419      var index = 0;
20420      var avatarsPaged = [];
20421      var avatarsPage = [];
20422
20423      for (index = 0; index < avatars.length; index += that.sliderPageSize) {
20424        avatarsPage = avatars.slice(index, index + that.sliderPageSize);
20425        avatarsPaged.push(avatarsPage);
20426      }
20427
20428      return avatarsPaged;
20429    },
20430  };
20431
20432  Community.init();
20433
20434  return Community;
20435});
20436/**
20437 * CookiesAgreement
20438 * @namespace Verkami
20439 * @class CookiesAgreement
20440 */
20441
20442var name = "Verkami/CookiesAgreement";
20443
20444modulejs.define(name, ["Verkami/Start", "Verkami/Sticky", "Verkami/Utils"], function (Start, Sticky, Utils) {
20445  var CookiesAgreement = {
20446    cookie: "",
20447    cookieName: "cookies_consent_level",
20448    disclaimer: [],
20449    disclaimerClose: [],
20450    disclaimerVisibleClass: "cookies--visible",
20451
20452    init: function () {
20453      var that = this;
20454
20455      // @todo: Make Cookies plugin a dependency
20456      that.cookie = Cookies.get(that.cookieName);
20457      that.disclaimer = $(".js-cookies");
20458
20459      if (that.disclaimer.length && !that.cookie) {
20460        that.showDisclaimer();
20461      }
20462
20463      // Check if there is any sticky bar in mobile to add a offset
20464      if (Utils.isMobile) {
20465        that.addMobileStickyOffset();
20466
20467        $(window).scroll(function () {
20468          that.addMobileStickyOffset();
20469        });
20470      }
20471    },
20472
20473    addMobileStickyOffset: function () {
20474      var that = this;
20475      var mobileStickyBar = Sticky.nodesMobile.filter(function () {
20476        return parseInt($(this).attr("data-sticky")) === 1;
20477      });
20478      var startBar = Start.bar.node.hasClass(Start.bar.visibleClass) ? Start.bar.node : [];
20479      var mobileStickyOffset = 0;
20480      var isAnyStickyBar = mobileStickyBar.length || startBar.length;
20481      var isCookiesVisible = that.disclaimer.hasClass(that.disclaimerVisibleClass);
20482
20483      if (isAnyStickyBar && isCookiesVisible) {
20484        if (mobileStickyBar.length) {
20485          mobileStickyOffset = mobileStickyBar.outerHeight();
20486        } else if (startBar.length) {
20487          mobileStickyOffset = startBar.outerHeight();
20488        }
20489      } else {
20490        mobileStickyOffset = 0;
20491      }
20492
20493      that.disclaimer.css("transform", "translateY(-" + mobileStickyOffset + "px)");
20494    },
20495
20496    hideDisclaimer: function (level) {
20497      var that = this;
20498
20499      Cookies.set(that.cookieName, level);
20500      that.cookie = Cookies.get(that.cookieName);
20501
20502      that.disclaimer.removeClass(that.disclaimerVisibleClass);
20503
20504      // Reset the CSS variable with the cookies bar height
20505      $(":root")[0].style.setProperty("--cookiesHeight", 0);
20506    },
20507
20508    showDisclaimer: function () {
20509      var that = this;
20510      that.disclaimerClose = $(".js-cookies-close", that.disclaimer);
20511      that.essentialsClose = $(".js-cookies-essentials-close", that.disclaimer);
20512      that.allClose = $(".js-cookies-all-close", that.disclaimer);
20513
20514      that.disclaimer.addClass(that.disclaimerVisibleClass);
20515
20516      // Add a CSS variable with the cookies bar height
20517      $(":root")[0].style.setProperty("--cookiesHeight", that.disclaimer.innerHeight());
20518
20519      that.disclaimerClose.on("click", function () {
20520        that.hideDisclaimer(2);
20521      });
20522      that.essentialsClose.on("click", function () {
20523        that.hideDisclaimer(1);
20524      });
20525      that.allClose.on("click", function () {
20526        that.hideDisclaimer(2);
20527      });
20528    },
20529  };
20530
20531  CookiesAgreement.init();
20532
20533  return CookiesAgreement;
20534});
20535/**
20536* Filters
20537* @namespace Verkami
20538* @class Filters
20539*/
20540
20541var name = 'Verkami/Filters';
20542var deps = [
20543  'Verkami/Utils'
20544];
20545
20546modulejs.define(name, deps, function(Utils) {
20547  var Filters = {
20548    node: [],
20549    content: [],
20550    trigger: [],
20551    triggerOpenClass: 'browse-bar__trigger--open',
20552
20553    init: function() {
20554      var that = this;
20555      that.node = $('.js-filters');
20556
20557      // Filters are hidden in Mobile, this is a trigger to show them
20558      if (that.node.length && Utils.isMobile) {
20559        that.content = $('.js-filters-content');
20560        that.trigger = $('.js-filters-trigger');
20561
20562        that.trigger.on('click', function() {
20563          that.trigger.toggleClass(that.triggerOpenClass);
20564          that.content.slideToggle();
20565        });
20566      }
20567    }
20568  };
20569
20570  Filters.init();
20571
20572  return Filters;
20573});
20574/**
20575 * Follow
20576 * @namespace Verkami
20577 * @class Flash
20578 */
20579
20580var name = "Verkami/Flash";
20581var deps = ["Verkami/Settings"];
20582
20583modulejs.define(name, deps, function(Settings) {
20584  var Flash = {
20585    nodes: [],
20586    nodeSelector: ".js-flash-box",
20587
20588    init: function() {
20589      var that = this;
20590      that.setupNewNodes();
20591    },
20592
20593    setupNewNodes: function() {
20594      var that = this;
20595      that.nodes = $(that.nodeSelector);
20596
20597      var newNodes = that.nodes.filter(function() {
20598        return !$(this).data("moduleFlashSetupDone");
20599      });
20600
20601      if (newNodes.length) {
20602        that.hideFlash(newNodes);
20603        newNodes.data("moduleFlashSetupDone", true);
20604      }
20605    },
20606
20607    hideFlash: function(nodes) {
20608      nodes.each(function() {
20609        var flashNode = $(this);
20610        setTimeout(function() {
20611          flashNode.fadeOut();
20612        }, Settings.speed * 6);
20613      });
20614    }
20615  };
20616
20617  Flash.init();
20618
20619  return Flash;
20620});
20621/**
20622 * Follow
20623 * @namespace Verkami
20624 * @class Follow
20625 */
20626
20627var deps = ["Verkami/CookiesAgreement", "Verkami/Modal", "Verkami/Settings", "Verkami/Utils"];
20628
20629modulejs.define("Verkami/Follow", deps, function (CookiesAgreement, Modal, Settings, Utils) {
20630  var Follow = {
20631    nodes: [],
20632    cookie: false,
20633    cookieName: "follow_tutorial",
20634    followActiveClass: "follow--active",
20635    followErrorClass: "follow--error",
20636    followModalId: {
20637      modalTrigger: "follow",
20638    },
20639    followTimeoutError: null,
20640
20641    init: function () {
20642      var that = this;
20643      that.cookie = Cookies.get(that.cookieName);
20644      that.setupNewNodes();
20645      that.goToFollow();
20646    },
20647
20648    setupNewNodes: function () {
20649      var that = this;
20650      that.nodes = $(".js-follow");
20651
20652      var newNodes = that.nodes.filter(function () {
20653        return !$(this).data("moduleFollowSetupDone");
20654      });
20655
20656      if (newNodes.length) {
20657        that.showCounter(newNodes);
20658        that.events(newNodes);
20659        newNodes.data("moduleFollowSetupDone", true);
20660      }
20661    },
20662
20663    showCounter: function (nodes) {
20664      var followCounter = [];
20665      var followTrigger = [];
20666
20667      nodes.each(function () {
20668        followTrigger = $(this);
20669        followCounter = $(".js-follow-counter", followTrigger);
20670
20671        if (followCounter.attr("data-follow-value") == "hidden") {
20672          followCounter.animate(
20673            {
20674              width: "hide",
20675            },
20676            "fast"
20677          );
20678        }
20679      });
20680    },
20681
20682    events: function (nodes) {
20683      var that = this;
20684
20685      nodes.on("click.Follow", function () {
20686        that.toggle($(this));
20687      });
20688    },
20689
20690    toggle: function (followTrigger) {
20691      var that = this;
20692      var followCounter = $(".js-follow-counter", followTrigger);
20693      var isFollowing = followTrigger.hasClass(that.followActiveClass);
20694      var isRequesting = false;
20695      var followTargetFollow = followTrigger.attr("data-follow");
20696      var followTargetUnfollow = followTrigger.attr("data-unfollow");
20697      var followTarget = isFollowing ? followTargetUnfollow : followTargetFollow;
20698
20699      if (!isRequesting) {
20700        $.ajax({
20701          type: "POST",
20702          url: followTarget,
20703          dataType: "json",
20704          beforeSend: function () {
20705            isRequesting = true;
20706          },
20707          error: function (data) {
20708            that.updateCounter(followCounter, followTrigger, false, data);
20709            isRequesting = false;
20710          },
20711          success: function (data) {
20712            if (data.error) {
20713              that.updateCounter(followCounter, followTrigger, false, data);
20714            } else {
20715              $(".js-follow-feedback").fadeOut();
20716              that.updateCounter(followCounter, followTrigger, true, data);
20717            }
20718            isRequesting = false;
20719          },
20720        });
20721
20722        // Show the follow instructions modal just once
20723        if (!that.cookie && !isFollowing) {
20724          console.log(that.followModalId.modalTrigger);
20725          Modal.moveToBodyEnd(that.followModalId.modalTrigger);
20726          Modal.show(that.followModalId);
20727
20728          // Save cookie if agreement it's previously done to prevent showing
20729          // this tutorial modal again.
20730          if (CookiesAgreement.cookie) {
20731            Cookies.set(that.cookieName, "true");
20732            that.cookie = Cookies.get(that.cookieName);
20733          }
20734        }
20735      }
20736    },
20737
20738    updateCounter: function (followCounter, followTrigger, status, data) {
20739      var that = this;
20740
20741      if (status) {
20742        followCounter.text(data.formatted_likes);
20743        followTrigger.toggleClass(that.followActiveClass).blur();
20744        that.counterToggle(followCounter, data.likes);
20745      } else {
20746        clearTimeout(that.followTimeoutError);
20747
20748        followTrigger.addClass(that.followErrorClass).blur();
20749
20750        that.followTimeoutError = setTimeout(function () {
20751          followTrigger.removeClass(that.followErrorClass);
20752        }, Settings.speed * 10);
20753      }
20754    },
20755
20756    counterToggle: function (followCounter, likes) {
20757      // Hide counter if nobody is following the project
20758      if (likes == 0) {
20759        followCounter.animate(
20760          {
20761            width: "hide",
20762          },
20763          "fast"
20764        );
20765      } else {
20766        followCounter.animate(
20767          {
20768            width: "show",
20769          },
20770          "fast"
20771        );
20772      }
20773    },
20774
20775    goToFollow: function () {
20776      var hash = Utils.hash.get();
20777      var hashTest = /^[a-zA-Z0-9-_]+$/;
20778      var node = null;
20779
20780      // If there is any anchor to the follow trigger, scroll down to it and show a tip box
20781      if (hash && hashTest.test(hash)) {
20782        node = $("#" + hash);
20783
20784        if (node.length && node.hasClass("js-follow")) {
20785          setTimeout(function () {
20786            $(".js-follow-feedback").fadeIn();
20787          }, Settings.speed * 6);
20788        }
20789      }
20790    },
20791  };
20792
20793  Follow.init();
20794
20795  return Follow;
20796});
20797/**
20798* Footer
20799* @namespace Verkami
20800* @class Footer
20801*/
20802
20803var name = 'Verkami/Footer';
20804var deps = [
20805  'Verkami/Utils'
20806];
20807
20808modulejs.define(name, deps, function(Utils) {
20809  var Footer = {
20810    node: [],
20811    visibleClass: 'footer--visible',
20812
20813    init: function() {
20814      var that = this;
20815      that.node = $('.js-footer');
20816
20817      if (that.node.length && !Utils.isMobile) {
20818        // @todo: Add Appear plugin as a dependency
20819        that.node.appear();
20820
20821        that.node.on('appear', function() {
20822          that.node.addClass(that.visibleClass);
20823        });
20824
20825        that.node.on('disappear', function() {
20826          that.node.removeClass(that.visibleClass);
20827        });
20828      }
20829    }
20830  };
20831
20832  Footer.init();
20833
20834  return Footer;
20835});
20836/**
20837* Hero
20838* @namespace Verkami
20839* @class Hero
20840*/
20841
20842var name = 'Verkami/Hero';
20843var deps = [
20844  'Verkami/Settings',
20845  'Verkami/Utils'
20846];
20847
20848modulejs.define(name, deps, function(Settings, Utils) {
20849  var Hero = {
20850    node: [],
20851    backgrounds: [],
20852    left: [],
20853    right: [],
20854    figures: [],
20855    figuresPausedClass: 'figures--paused',
20856
20857    init: function() {
20858      var that = this;
20859      that.node = $('.js-hero');
20860
20861      if (that.node.length) {
20862        that.backgrounds = $('.js-hero-bgs', that.node);
20863        that.left = $('.js-hero-left', that.node);
20864        that.leftItems = $('.js-hero-bgs-left', that.backgrounds);
20865        that.right = $('.js-hero-right', that.node);
20866        that.rightItems = $('.js-hero-bgs-right', that.backgrounds);
20867        that.figures = $('.js-figures', that.node);
20868        var leftItemsIndex = 0;
20869        var leftItemsCount = that.leftItems.length;
20870        var rightItemsIndex = 0;
20871        var rightItemsCount = that.rightItems.length;
20872
20873        that.preloadBackgrounds();
20874
20875        that.left.hover(function() {
20876          if (leftItemsIndex == leftItemsCount) {
20877            leftItemsIndex = 0;
20878          }
20879          that.showBg(that.leftItems.eq(leftItemsIndex), that.right);
20880          leftItemsIndex++;
20881        }, function() {
20882          that.hideBg(that.leftItems, that.right);
20883        });
20884
20885        that.right.hover(function() {
20886          if (rightItemsIndex == rightItemsCount) {
20887            rightItemsIndex = 0;
20888          }
20889          that.showBg(that.rightItems.eq(rightItemsIndex), that.left);
20890          rightItemsIndex++;
20891        }, function() {
20892          that.hideBg(that.rightItems, that.left);
20893        });
20894      }
20895    },
20896
20897    hideBg: function(target, otherSide) {
20898      var that = this;
20899
20900      that.figures.removeClass(that.figuresPausedClass);
20901
20902      otherSide.css('opacity', 1);
20903
20904      // @todo: Check if it's possible to avoid the speed attribute
20905      that.backgrounds.stop(true, true).fadeOut(Settings.speed, function() {
20906        target.css('display', 'none');
20907      });
20908    },
20909
20910    preloadBackgrounds: function() {
20911      var that = this;
20912      var heroItems = $.fn.add.call(that.leftItems, that.rightItems);
20913
20914      Utils.preloadImages(heroItems);
20915    },
20916
20917    showBg: function(target, otherSide) {
20918      var that = this;
20919
20920      that.figures.addClass(that.figuresPausedClass);
20921
20922      otherSide.css('opacity', 0);
20923
20924      target.css('display', 'table');
20925      that.backgrounds.stop(true, true).fadeIn();
20926    }
20927  };
20928
20929  Hero.init();
20930
20931  return Hero;
20932});
20933/**
20934* IEWarning
20935* @namespace Verkami
20936* @class IEWarning
20937*/
20938
20939var name = 'Verkami/IEWarning';
20940
20941modulejs.define(name, function() {
20942  var IEWarning = {
20943    ieWarningBar: [],
20944
20945    init: function() {
20946      var that = this;
20947      var userAgent = window.navigator.userAgent;
20948      var isIE = userAgent.indexOf('MSIE ');
20949      that.ieWarningBar = $('.js-ie-warning');
20950
20951      if (that.ieWarningBar.length && isIE > 0) {
20952        that.ieWarningBar.show();
20953      }
20954    }
20955  };
20956
20957  IEWarning.init();
20958
20959  return IEWarning;
20960});
20961/**
20962* Navigation
20963* @namespace Verkami
20964* @class Navigation
20965*/
20966
20967var name = 'Verkami/Navigation';
20968var deps = [
20969  'Verkami/Utils'
20970];
20971
20972modulejs.define(name, deps, function(Utils) {
20973  var Navigation = {
20974    toggle: [],
20975    navigationWrapper: [],
20976    toggleActiveClass: 'header-overlay-xs-visible',
20977
20978    init: function() {
20979      var that = this;
20980
20981      that.toggle = $('.js-navigation-toggle');
20982
20983      if (that.toggle.length && (Utils.isMobile || Utils.isTablet)) {
20984        that.navigationWrapper = $('.js-navigation-wrapper');
20985
20986        that.setup();
20987
20988        that.toggle.on('click', function() {
20989          $('body').toggleClass(that.toggleActiveClass);
20990        });
20991
20992        $(window).resize(function() {
20993          that.setup();
20994        });
20995      }
20996    },
20997
20998    setup: function() {
20999      var that = this;
21000      var viewportHeight = Utils.getViewportSize('height');
21001      var navigationWrapperTopMargin = parseInt(that.navigationWrapper.css('margin-top'));
21002
21003      that.navigationWrapper.css('max-height', viewportHeight - navigationWrapperTopMargin);
21004    }
21005  };
21006
21007  Navigation.init();
21008
21009  return Navigation;
21010});
21011/**
21012 * Paginator
21013 * @namespace Verkami
21014 * @class Paginator
21015 */
21016
21017var name = "Verkami/Paginator";
21018var deps = [
21019  "Verkami/Cards",
21020  "Verkami/Follow",
21021  "Verkami/Form",
21022  "Verkami/Modal",
21023  "Verkami/Share",
21024  "Verkami/Utils",
21025  "Verkami/Toggle",
21026];
21027
21028modulejs.define(name, deps, function (Cards, Follow, Form, Modal, Share, Utils, Toggle) {
21029  var Paginator = {
21030    nodes: [],
21031    autoTriggerLimit: 3,
21032
21033    init: function () {
21034      var that = this;
21035      var node = [];
21036      that.nodes = $(".js-paginator");
21037
21038      if (that.nodes.length) {
21039        // Set default page
21040        that.nodes.each(function () {
21041          $(this).attr({
21042            "data-paginator-loading": 0,
21043            "data-paginator-page": 1,
21044          });
21045        });
21046
21047        // Initialize jquery.appear in paginator nodes
21048        $(".js-paginator-trigger", that.nodes).appear();
21049
21050        // Load next page on click trigger
21051        that.nodes.on("click", ".js-paginator-trigger", function (e) {
21052          e.preventDefault();
21053
21054          // Load next page
21055          that.getNextPage($(this));
21056        });
21057
21058        // Load next page on scroll down
21059        that.nodes.on("appear", ".js-paginator-trigger", function () {
21060          // Load next page
21061          that.getNextPage($(this));
21062        });
21063      }
21064    },
21065
21066    getNextPage: function (trigger) {
21067      var that = this;
21068      var node = trigger.closest(".js-paginator");
21069      var placeholder = trigger.closest(".js-paginator-placeholder");
21070      var endpoint = trigger.attr("href");
21071      var newContent = [];
21072      var page = parseInt(node.attr("data-paginator-page"));
21073      var isLoading = parseInt(node.attr("data-paginator-loading"));
21074
21075      if (!isLoading) {
21076        // Set loading flag
21077        node.attr("data-paginator-loading", 1);
21078
21079        // Show loading feedback
21080        Form.submit.loadingState(trigger);
21081
21082        // Disable autotrigger after reaching autoTriggerLimit
21083        if (page === that.autoTriggerLimit) {
21084          node.off("appear", ".js-paginator-trigger");
21085        }
21086
21087        $.get(endpoint, function (data) {
21088          newContent = $(data);
21089
21090          // Update paginator information
21091          node.attr({
21092            "data-paginator-loading": 0,
21093            "data-paginator-page": page + 1,
21094          });
21095
21096          // Show new content
21097          placeholder.replaceWith(newContent);
21098
21099          if (newContent.find(".js-squarize").length) {
21100            Utils.squarize();
21101          }
21102
21103          // Manually refresh affected modules so the triggering events they install
21104          // can be applied to the new, asynchronously loaded nodes.
21105          Follow.setupNewNodes();
21106          Share.setupNewNodes();
21107          Cards.setupNewNodes();
21108          Form.characterCounter.setupNewNodes();
21109          Toggle.setupNewNodes();
21110          Modal.refresh();
21111        });
21112      }
21113    },
21114  };
21115
21116  Paginator.init();
21117
21118  return Paginator;
21119});
21120/**
21121 * Panels
21122 * @namespace Verkami
21123 * @class Panels
21124 *
21125 * Panel IDs:
21126 * 1. Sign up
21127 * 2. Log in
21128 * 3. Signed up with Facebook
21129 * 4. Forgot password
21130 * 5. Forgot password confirmation
21131 * 6. Logged in
21132 */
21133
21134var name = "Verkami/Panels";
21135var deps = [
21136  "Verkami/Form",
21137  "Verkami/PledgePayments",
21138  "Verkami/Settings",
21139  "Verkami/Utils"
21140];
21141
21142modulejs.define(name, deps, function (Form, PledgePayments, Settings, Utils) {
21143  var Panels = {
21144    signup: 1,
21145    login: 2,
21146    signupFacebook: 3,
21147    forgotPassword: 4,
21148    forgotPasswordConfirmation: 5,
21149    loggedIn: 6,
21150
21151    nodes: [],
21152    panelsContentActiveClass: "modal-pledge__content__panel--active",
21153
21154    init: function () {
21155      var that = this;
21156
21157      that._hooks();
21158    },
21159
21160    _hooks: function () {
21161      var that = this;
21162
21163      // Initialize Panels once modal is open
21164      $(document).on("hook.vk.modal.open", ".js-modal", function (e, modalData) {
21165        var isAuthModal = modalData.modalTrigger === "auth_dialog";
21166        var isPasswordExpiredModal = modalData.modalTrigger === "auth_reset_password_token_expired";
21167        var isPledgeModal = modalData.modalTrigger.match("^pledges_process");
21168        var panelModule = [];
21169        var panelId = null;
21170
21171        if (isAuthModal || isPasswordExpiredModal || isPledgeModal) {
21172          panelModule = $(this).hasClass("js-panels") ? $(this) : $(".js-panels", $(this));
21173          panelId = modalData.panelsTrigger ? modalData.panelsTrigger : Utils.hash.pick("panel");
21174
21175          that.setup();
21176
21177          // If panel is defined, show it directly
21178          if (panelId) {
21179            that.toggleContents(panelModule, panelId, Settings.instantSpeed);
21180          } else {
21181            if (isPledgeModal && panelModule.data("logged-in")) {
21182              that.toggleContents(panelModule, that.loggedIn, Settings.instantSpeed);
21183            } else {
21184              that.toggleContents(panelModule, that.signup, Settings.instantSpeed);
21185            }
21186          }
21187        }
21188      });
21189    },
21190
21191    getContent: function (panels, panelId) {
21192      var contents = $(".js-panels-content", panels);
21193      var content = contents.filter("[data-panels-content*=\"" + panelId + "\"]");
21194
21195      return content;
21196    },
21197
21198    getActiveContent: function (panels) {
21199      return panels.data("panels-active");
21200    },
21201
21202    setActiveContent: function (panels, content) {
21203      panels.data("panels-active", content);
21204      // Using the data() method to update data does not affect attributes in the DOM.
21205      // cf. https://api.jquery.com/data/
21206      // Keep both updated consistently to prevent bugs like
21207      // https://github.com/verkami/verkami/issues/3394#issuecomment-712721591
21208      panels.attr("data-panels-active", content);
21209    },
21210
21211    setup: function () {
21212      var that = this;
21213      var panel = [];
21214      that.nodes = $(".js-panels");
21215
21216      that.nodes.each(function () {
21217        panel = $(this);
21218
21219        that.setActiveContent(panel, that.signup);
21220
21221        // Toggle panel content
21222        panel.off("click.vk.panel.toggle").on("click.vk.panel.toggle", ".js-panels-trigger", function (e) {
21223          var panels = $(this).closest(".js-panels");
21224          var panelId = $(this).data("panels-trigger");
21225
21226          e.preventDefault();
21227
21228          that.toggleContents(panels, panelId);
21229        });
21230      });
21231    },
21232
21233    showSubmitButton: function (modal, panelId) {
21234      var that = this;
21235      if (panelId == that.login) {
21236        $(".js-pledge-submit", modal).hide();
21237        $(".js-pledge-login-submit", modal).show();
21238      } else {
21239        $(".js-pledge-submit", modal).show();
21240        $(".js-pledge-login-submit", modal).hide();
21241      }
21242    },
21243
21244    toggleContents: function (panels, panelId, speed) {
21245      speed = speed === undefined ? Settings.speed : speed;
21246      panelId = parseInt(panelId);
21247      var that = this;
21248      var contents = $(".js-panels-content", panels);
21249      var content = that.getContent(panels, panelId);
21250      var pledgeSubmit = panels.closest(".js-pledge").find(".js-pledge-submit");
21251      var pledgePayments = panels.closest(".js-pledge").find(".js-pledge-payments");
21252
21253      that.setActiveContent(panels, panelId);
21254
21255      switch (panelId) {
21256        case that.signup:
21257          var signupInputs = $(".js-signup", contents).find(":input");
21258
21259          Form.error("hide", signupInputs);
21260          PledgePayments.reset(pledgePayments);
21261          PledgePayments.enable(pledgePayments);
21262          break;
21263
21264        case that.login:
21265          var loginInputs = $(".js-login", contents).find(":input");
21266
21267          Form.error("hide", loginInputs);
21268          $(".js-login", contents).trigger("trigger.vk.user.login.init");
21269          PledgePayments.reset(pledgePayments);
21270          PledgePayments.enable(pledgePayments, {
21271            "hidePayments": Settings.beta.tokenizationAvailable()
21272          });
21273          break;
21274
21275        case that.forgotPassword:
21276        case that.forgotPasswordConfirmation:
21277          PledgePayments.disable(pledgePayments, true);
21278          pledgeSubmit.trigger("trigger.vk.pledge.hideSubmit");
21279          break;
21280
21281        default:
21282          PledgePayments.enable(pledgePayments);
21283          break;
21284      }
21285
21286      if (Settings.beta.tokenizationAvailable()) {
21287        that.showSubmitButton(panels, panelId);
21288      }
21289
21290      contents.fadeOut(speed).delay(speed).filter(content).fadeIn(speed);
21291    }
21292  };
21293
21294  Panels.init();
21295
21296  return Panels;
21297});
21298/**
21299* PartnerFollow
21300* @namespace Verkami
21301* @class PartnerFollow
21302*/
21303
21304var name = 'Verkami/PartnerFollow';
21305
21306modulejs.define(name, function() {
21307  var PartnerFollow = {
21308    node: [],
21309    activeClass: 'partner-profile__follow--active',
21310
21311    init: function() {
21312      var that = this;
21313      that.node = $('.js-partner-follow');
21314
21315      if (that.node.length) {
21316        that.node.on('click', function() {
21317          that.node.toggleClass(that.activeClass).blur();
21318        });
21319      }
21320    }
21321  };
21322
21323  PartnerFollow.init();
21324
21325  return PartnerFollow;
21326});
21327/**
21328* Password
21329* @namespace Verkami
21330* @class Password
21331*/
21332
21333var name = 'Verkami/Password';
21334
21335modulejs.define(name, function() {
21336  var Password = {
21337    nodes: [],
21338    visibleClass: 'form-password--visible',
21339
21340    init: function() {
21341      var that = this;
21342      that.nodes = $('.js-password');
21343
21344      // Initialize change password Form toggle controller
21345      that.changeForm.init();
21346
21347      if (that.nodes.length) {
21348        that.nodes.off('click.passwordToggle').on('click.passwordToggle', '.js-password-toggle', function() {
21349          var container = $(this).closest('.js-password');
21350
21351          $('.js-password-input', container).togglePassword();
21352          container.toggleClass(that.visibleClass);
21353        });
21354
21355        var doubleCheck = that.nodes.filter(function() {
21356          return $(this).hasClass('js-password-double-check');
21357        });
21358
21359        if (doubleCheck.length) {
21360          var doubleCheckMain = [];
21361          var doubleCheckTwin = [];
21362
21363          doubleCheck.each(function() {
21364            doubleCheckMain = $('.js-password-input', this);
21365            doubleCheckTwin = $(this).siblings('.js-password').find('.js-password-input');
21366
21367            doubleCheckMain.add(doubleCheckTwin).off('keyup.passwordCheck').on('keyup.passwordCheck', function() {
21368              if (doubleCheckMain.val() === doubleCheckTwin.val()) {
21369                doubleCheckTwin.closest('form').find('input[type="submit"]').removeClass('button--disabled');
21370                doubleCheckTwin.removeClass('form-item__error');
21371              } else {
21372                doubleCheckTwin.closest('form').find('input[type="submit"]').addClass('button--disabled');
21373                doubleCheckTwin.addClass('form-item__error');
21374              }
21375            });
21376          });
21377        }
21378      }
21379    },
21380
21381    changeForm: {
21382      form: [],
21383      trigger: [],
21384
21385      init: function() {
21386        var that = this;
21387        that.form = $('.js-password-change-form');
21388
21389        if (that.form.length) {
21390          that.trigger = $('.js-password-change-trigger');
21391
21392          if (that.form.attr('data-password-change-show') === 'true') {
21393            that.trigger.hide();
21394            that.form.show();
21395          }
21396
21397          that.trigger.on('click', function() {
21398            that.trigger.fadeOut();
21399            that.form.slideToggle();
21400          });
21401        }
21402      }
21403    }
21404  };
21405
21406  Password.init();
21407
21408  return Password;
21409});
21410/**
21411 * Player
21412 * @namespace Verkami
21413 * @class Player
21414 *
21415 * Feature: External placeholder
21416 * -----------------------------
21417 * There is way to put the placeholder outside the main node
21418 * by adding `data-player-name` to both node and placeholder to match them.
21419 * This works only on desktop, mobile and tablet get the placeholder and
21420 * append it to the main node.
21421 *
21422 * API Events:
21423 * ------
21424 * Video ends: [.js-player] hook.vk.player.end
21425 * Video starts: [.js-player] hook.vk.player.start
21426 */
21427
21428/* global Vimeo, YT */
21429
21430var deps = ["Verkami/Settings", "Verkami/Utils", "Verkami/Video"];
21431
21432modulejs.define("Verkami/Player", deps, function (Settings, Utils, Video) {
21433  var Player = {
21434    nodes: [],
21435    vimeoAPI: "https://player.vimeo.com/api/player.js",
21436    vimeoPlayers: [],
21437    youtubeAPI: "https://www.youtube.com/iframe_api",
21438    youtubePlayers: [],
21439    loadingClass: "player--loading",
21440    playingClass: "player--playing",
21441    events: {
21442      esc: "keyup.vk.player.esc",
21443      outside: "click.vk.player.outside",
21444      trigger: "click.vk.player.trigger",
21445    },
21446    hooks: {
21447      end: "hook.vk.player.end",
21448      start: "hook.vk.player.start",
21449    },
21450
21451    init: function () {
21452      var that = this;
21453      that.nodes = $(".js-player");
21454
21455      if (that.nodes.length) {
21456        // Clean Vimeo players
21457        if (that.vimeoPlayers.length) {
21458          that.vimeoPlayers = [];
21459        }
21460
21461        // Clean Youtube players
21462        if (that.youtubePlayers.length) {
21463          that.youtubePlayers = [];
21464        }
21465
21466        // Run players
21467        that.initialize(that.nodes);
21468      }
21469    },
21470
21471    addExitEvents: function(node) {
21472      var that = this;
21473      var exitOutside = node.attr("data-player-exit-outside") === "enabled";
21474
21475      if (!Utils.isMobile) {
21476        // Clicking outside the player closes it
21477        if (exitOutside) {
21478          $(document).on(that.events.outside, function(e) {
21479            var $target = $(e.target);
21480            var isOutside = !$target.closest(node).length;
21481            var isFollow = $target.closest(".follow").length || $target.hasClass("follow");
21482
21483            if (isOutside && !isFollow) {
21484              that.showCover(node);
21485            }
21486          });
21487        }
21488
21489        // Escape key closes the player
21490        $(document).on(that.events.esc, function(e) {
21491          if (e.keyCode == 27) {
21492            that.showCover(node);
21493          }
21494        });
21495      }
21496    },
21497
21498    enhanceThumbnail: function (node) {
21499      var cover = $(".js-player-cover", node);
21500      var coverPath = "";
21501      var enhance = cover.attr("data-player-enhance-thumbnail") === "true";
21502      var enhanceUrl = "";
21503
21504      if (enhance) {
21505        enhanceUrl = cover.attr("data-player-enhance-thumbnail-url");
21506
21507        $.get(enhanceUrl, function (response) {
21508          // If no image is retrieved, don't change anything
21509          if (Object.prototype.hasOwnProperty.call(response, "image")) {
21510            coverPath = "url(" + response.image + ")";
21511
21512            cover.css("background-image", coverPath);
21513
21514            // Turn off enhancement to avoid new requests
21515            cover.attr("data-player-enhance-thumbnail", "false");
21516          }
21517        });
21518      }
21519    },
21520
21521    getPlaceholder: function (node) {
21522      var name = node.data("player-name");
21523      var placeholder = [];
21524
21525      if (name) {
21526        placeholder = $(".js-player-placeholder[data-player-name=" + name + "]").length
21527          ? $(".js-player-placeholder[data-player-name=" + name + "]")
21528          : $(".js-player-placeholder", node);
21529
21530        if (!Utils.isDesktop) {
21531          placeholder.appendTo(node);
21532        }
21533      } else {
21534        placeholder = $(".js-player-placeholder", node);
21535      }
21536
21537      return placeholder;
21538    },
21539
21540    hideCover: function (node) {
21541      var that = this;
21542      var cover = $(".js-player-cover", node);
21543      var trigger = $(".js-player-trigger", node);
21544      var placeholder = that.getPlaceholder(node);
21545
21546      node.trigger(that.hooks.start);
21547
21548      that.addExitEvents(node);
21549
21550      cover.fadeOut("slower");
21551      trigger.fadeOut("slower");
21552      $("body").addClass(that.playingClass);
21553
21554      setTimeout(function () {
21555        placeholder.stop().animate(
21556          {
21557            opacity: 1,
21558          },
21559          Settings.speed * 4,
21560          "easeInOutCubic"
21561        );
21562
21563        node.removeClass(that.loadingClass);
21564      }, Settings.speed * 4);
21565    },
21566
21567    initialize: function (nodes) {
21568      var that = this;
21569      var node = [];
21570      var placeholder = [];
21571      nodes = nodes.filter(function () {
21572        return !$(this).attr("data-player-initialized");
21573      });
21574
21575      if (nodes.length) {
21576        nodes.each(function (i) {
21577          node = $(this);
21578          placeholder = that.getPlaceholder(node);
21579
21580          node.data("data-player-index", i);
21581
21582          that.enhanceThumbnail(node);
21583
21584          node
21585            .off(that.events.trigger, ".js-player-trigger")
21586            .on(that.events.trigger, ".js-player-trigger", function () {
21587              that.setup($(this).closest(".js-player"), i);
21588            });
21589
21590          node.attr("data-player-initialized", "true");
21591
21592          placeholder.css("opacity", 0);
21593        });
21594      }
21595    },
21596
21597    loadYoutube: function (node, callback) {
21598      var that = this;
21599
21600      // Get YouTube API
21601      $.getScript(that.youtubeAPI);
21602
21603      // Use API just once it's ready
21604      window.onYouTubeIframeAPIReady = function () {
21605        callback.resolve(node);
21606      };
21607    },
21608
21609    loadVimeo: function (node, callback) {
21610      var that = this;
21611
21612      // Get Vimeo API
21613      $.getScript(that.vimeoAPI, function () {
21614        callback.resolve(node);
21615      });
21616    },
21617
21618    removeExitEvents: function () {
21619      var that = this;
21620
21621      if (!Utils.isMobile) {
21622        // See addExitEvents() for further information
21623        $(document).off(that.events.outside);
21624
21625        // See addExitEvents() for further information
21626        $(document).off(that.events.esc);
21627      }
21628    },
21629
21630    renderYoutube: function (node, i) {
21631      var that = this;
21632      var id = node.attr("data-player-id");
21633      var iframe = $("<div/>");
21634      var placeholder = that.getPlaceholder(node);
21635
21636      node.addClass(that.loadingClass);
21637
21638      iframe.prop("id", "video_" + id).appendTo(placeholder);
21639
21640      that.youtubePlayers[i] = new window.YT.Player("video_" + id, {
21641        videoId: id,
21642        playerVars: {
21643          autoplay: !Utils.isMobile && !Utils.isTablet ? 1 : 0,
21644          iv_load_policy: 3,
21645          modestbranding: 1,
21646          rel: 0,
21647          showinfo: 0,
21648        },
21649        events: {
21650          onReady: function () {
21651            Video.setSize($("iframe", placeholder));
21652
21653            that.hideCover(node);
21654          },
21655          onStateChange: function (e) {
21656            if (e.data == YT.PlayerState.PLAYING) {
21657              that.hideCover(node);
21658            } else if (e.data == YT.PlayerState.ENDED) {
21659              that.showCover(node);
21660            }
21661          },
21662        },
21663      });
21664
21665      $(window).on("resize.player", function () {
21666        Video.setSize($("iframe", placeholder));
21667      });
21668    },
21669
21670    renderVimeo: function (node, i) {
21671      var that = this;
21672      var id = node.attr("data-player-id");
21673      var placeholder = that.getPlaceholder(node);
21674
21675      node.addClass(that.loadingClass);
21676
21677      that.vimeoPlayers[i] = new Vimeo.Player(placeholder, {
21678        id: id,
21679        autoplay: !Utils.isMobile && !Utils.isTablet,
21680        muted: true,
21681        outro: false,
21682      });
21683
21684      that.vimeoPlayers[i].ready().then(function () {
21685        that.vimeoPlayers[i].on("loaded", function () {
21686          Video.setSize($("iframe", placeholder));
21687
21688          // Play video
21689          // Note: autoplay is not working in last Chrome version 66.0.3359.139
21690          that.vimeoPlayers[i].play();
21691
21692          if (Utils.isMobile || Utils.isTablet) {
21693            that.hideCover($(this.element).closest(".js-player"));
21694          }
21695
21696          $(window).resize(function () {
21697            Video.setSize($("iframe", placeholder));
21698          });
21699        });
21700
21701        that.vimeoPlayers[i].on("play", function () {
21702          that.hideCover($(this.element).closest(".js-player"));
21703        });
21704
21705        that.vimeoPlayers[i].on("ended", function () {
21706          that.showCover(node);
21707        });
21708      });
21709    },
21710
21711    showCover: function (node) {
21712      var that = this;
21713      var cover = $(".js-player-cover", node);
21714      var trigger = $(".js-player-trigger", node);
21715      var type = node.attr("data-player-type").toLowerCase();
21716      var index = parseInt(node.data("data-player-index"));
21717      var placeholder = that.getPlaceholder(node);
21718
21719      node.trigger(that.hooks.end);
21720
21721      that.removeExitEvents();
21722
21723      switch (type) {
21724        case "vimeo":
21725          // Check if Vimeo API is loaded
21726          if (window.Vimeo) {
21727            that.vimeoPlayers[index].pause();
21728          }
21729          break;
21730
21731        case "youtube":
21732          // Check if YouTube API is loaded
21733          if (window.YT) {
21734            that.youtubePlayers[index].pauseVideo();
21735          }
21736          break;
21737      }
21738
21739      placeholder.stop().animate(
21740        {
21741          opacity: 0,
21742        },
21743        Settings.speed * 4,
21744        "easeInOutCubic"
21745      );
21746      cover.fadeIn("slower");
21747      trigger.fadeIn("slower");
21748      $("body").removeClass(that.playingClass);
21749    },
21750
21751    setup: function (node, i) {
21752      var that = this;
21753      var callback = null;
21754      var type = node.attr("data-player-type").toLowerCase();
21755      var placeholder = that.getPlaceholder(node);
21756
21757      switch (type) {
21758        case "vimeo":
21759          // Check if Vimeo API is loaded
21760          if (window.Vimeo) {
21761            // Check if video is already loaded
21762            if (placeholder.is(":empty")) {
21763              that.renderVimeo(node, i);
21764            } else {
21765              that.vimeoPlayers[i].play();
21766              that.hideCover(node);
21767            }
21768          } else {
21769            callback = $.Deferred();
21770
21771            // Load Vimeo API
21772            that.loadVimeo(node, callback);
21773
21774            callback.done(function (node) {
21775              that.renderVimeo(node, i);
21776            });
21777          }
21778
21779          break;
21780
21781        case "youtube":
21782          // Check if YouTube API is loaded
21783          if (window.YT) {
21784            // Check if video is already loaded
21785            if (placeholder.is(":empty")) {
21786              that.renderYoutube(node, i);
21787            } else {
21788              that.youtubePlayers[i].playVideo();
21789            }
21790          } else {
21791            callback = $.Deferred();
21792
21793            // Load Youtube API
21794            that.loadYoutube(node, callback);
21795
21796            callback.done(function (node) {
21797              that.renderYoutube(node, i);
21798            });
21799          }
21800
21801          break;
21802      }
21803    },
21804  };
21805
21806  Player.init();
21807
21808  return Player;
21809});
21810/**
21811 * Pledge
21812 * @namespace Verkami
21813 * @class Pledge
21814 */
21815
21816var name = "Verkami/Pledge";
21817var deps = [
21818  "Verkami/Form",
21819  "Verkami/Modal",
21820  "Verkami/Panels",
21821  "Verkami/PledgePayments",
21822  "Verkami/Scroll",
21823  "Verkami/User",
21824  "Verkami/Settings",
21825  "Verkami/Utils",
21826];
21827
21828modulejs.define(name, deps, function (Form, Modal, Panels, PledgePayments, Scroll, User, Settings, Utils) {
21829  var Pledge = {
21830    pledgeButtonDisabledClass: "button--disabled",
21831
21832    init: function () {
21833      var that = this;
21834
21835      that._callbacks();
21836      that._hooks();
21837    },
21838
21839    _callbacks: function () {
21840      var that = this;
21841
21842      $(document).on("trigger.vk.pledge.disableSubmit", ".js-pledge-submit", function () {
21843        that.disableSubmit($(this));
21844      });
21845
21846      $(document).on("trigger.vk.pledge.hideSubmit", ".js-pledge-submit", function () {
21847        that.disableSubmit($(this), true);
21848      });
21849
21850      $(document).on("trigger.vk.pledge.enableSubmit", ".js-pledge-submit", function () {
21851        that.enableSubmit($(this));
21852      });
21853    },
21854
21855    _hooks: function () {
21856      var that = this;
21857
21858      $(document).on("hook.vk.modal.open", ".js-modal", function (e, modalData) {
21859        var isPledgeModal = modalData.modalTrigger.match("^pledges_process");
21860
21861        if (isPledgeModal) {
21862          var pledgeNode = $(this).hasClass("js-pledge") ? $(this) : $(".js-pledge", $(this));
21863
21864          that.setup(pledgeNode);
21865        }
21866      });
21867    },
21868
21869    events: function (pledge) {
21870      var that = this;
21871
21872      pledge.payments.on("change", ".js-pledge-payments-trigger", function () {
21873        PledgePayments.paymentMethodSelected($(this));
21874      });
21875
21876      pledge.node
21877        .off("click.vk.pledge.asideToggle")
21878        .on("click.vk.pledge.asideToggle", ".js-pledge-aside-toggle", function (e) {
21879          e.preventDefault();
21880
21881          $(".js-pledge-aside-content", $(this).closest(".js-pledge-aside")).slideToggle("fast");
21882
21883          $(this).toggleClass("modal-pledge__aside__toggle--active");
21884        });
21885
21886      pledge.loginSubmit.off("click.vk.pledge.login.submit").on("click.vk.pledge.login.submit", function () {
21887        var authForm = $(this).closest(".js-modal").find(".js-login");
21888        that.submit("login", authForm, null, {
21889          submit: $(this),
21890        });
21891      });
21892
21893      var captchaEnabledInSubmit = pledge.submit.hasClass("js-recaptcha");
21894      var eventToListen = "click.vk.pledge.submit";
21895      if (captchaEnabledInSubmit) {
21896        console.log("[CAPTCHA] Pledge submit with captcha requirements detected.");
21897        console.log("[CAPTCHA] Listening to captcha events.");
21898        eventToListen = "captcha.vk.validated";
21899      }
21900
21901      pledge.submit.off(eventToListen).on(eventToListen, function () {
21902        console.log("Processing pledge submit triggered by " + eventToListen);
21903
21904        var pledgeNode = $(this).closest(".js-pledge");
21905        var pledge = {
21906          panels: $(".js-panels", pledgeNode),
21907          content: $(".js-pledge-content", pledgeNode),
21908          node: pledgeNode,
21909          payments: $(".js-pledge-payments", pledgeNode),
21910          paymentsTip: $(".js-pledge-payments-tip", pledgeNode),
21911          submit: $(this),
21912        };
21913        var activeContent = Panels.getActiveContent(pledge.panels);
21914        var paymentForm = [];
21915        var paymentTrigger = $(".js-pledge-payments-trigger", pledge.payments).filter(":checked");
21916        var paymentType = paymentTrigger.attr("data-pledge-payment");
21917        var currentModal = pledge.submit.closest(".js-modal");
21918        var authForm = [];
21919
21920        // Save redirect in the auth form if triggering submit has a custom one.
21921        // This is later used by the User module.
21922        $(".js-login, .js-signup, .js-auth-facebook, .js-auth-google", currentModal).attr(
21923          "data-auth-redirect",
21924          pledge.submit.data("authRedirect")
21925        );
21926
21927        if (activeContent == Panels.signup) {
21928          if (paymentTrigger.length) {
21929            authForm = currentModal.find(".js-signup");
21930            that.submit("signup", authForm, paymentType, pledge);
21931          }
21932        } else if (activeContent == Panels.login) {
21933          if (paymentTrigger.length) {
21934            authForm = currentModal.find(".js-login");
21935            that.submit("login", authForm, paymentType, pledge);
21936          }
21937        } else if (activeContent == Panels.loggedIn) {
21938          var selector = that.paymentTypeSelector(pledge, paymentType);
21939          paymentForm = $(selector, pledge.payments);
21940          // Disable the submit element to prevent double-clicks/submissions
21941          Form.submit.loadingState(pledge.submit);
21942          paymentForm.submit();
21943        }
21944      });
21945    },
21946
21947    paymentTypeSelector: function (pledge, selectedPaymentType) {
21948      if (selectedPaymentType == "redsys" || selectedPaymentType == "redsys_direct") {
21949        var requestTokenCheck = $(".js-redsys-token-request-check", pledge.payments);
21950        if (requestTokenCheck.is(":checked")) {
21951          selectedPaymentType += "-token-request";
21952        }
21953      }
21954      return ".js-pledge-payments-" + selectedPaymentType;
21955    },
21956
21957    disableSubmit: function (pledgeSubmit, hide) {
21958      var that = this;
21959
21960      if (hide) {
21961        pledgeSubmit.fadeOut();
21962      } else {
21963        pledgeSubmit.addClass(that.pledgeButtonDisabledClass);
21964
21965        if (!pledgeSubmit.is(":visible")) {
21966          pledgeSubmit.fadeIn();
21967        }
21968      }
21969    },
21970
21971    enableSubmit: function (pledgeSubmit) {
21972      var that = this;
21973
21974      if (!pledgeSubmit.is(":visible")) {
21975        pledgeSubmit.fadeIn();
21976      }
21977
21978      pledgeSubmit.removeClass(that.pledgeButtonDisabledClass);
21979    },
21980
21981    setAuth: function (pledge) {
21982      var panelModule = $(".js-panels", pledge.node);
21983      if (panelModule.data("logged-in")) {
21984        Panels.toggleContents(panelModule, Panels.loggedIn);
21985      }
21986    },
21987
21988    setup: function (pledgeNode) {
21989      var that = this;
21990      var pledge = {
21991        content: $(".js-pledge-content", pledgeNode),
21992        node: pledgeNode,
21993        payments: $(".js-pledge-payments", pledgeNode),
21994        paymentsTip: $(".js-pledge-payments-tip", pledgeNode),
21995        submit: $(".js-pledge-submit", pledgeNode),
21996        loginSubmit: $(".js-pledge-login-submit", pledgeNode),
21997      };
21998      var viewportHeight = Utils.getViewportSize("height");
21999      var modalHeight = $(".modal__box", pledge.node).outerHeight();
22000      var modalOffset = 30;
22001      var modalMaxHeight = viewportHeight - modalOffset * 2;
22002
22003      // Toggle loggedin panel if user is already logged in that.setAuth(pledge);
22004
22005      if (modalHeight > modalMaxHeight) {
22006        var rewardDescription = $(".js-pledge-reward-description", pledge.node);
22007        var rewardDescriptionOffset = rewardDescription.position().top;
22008
22009        pledge.content.outerHeight(modalMaxHeight);
22010        rewardDescription.css("maxHeight", modalMaxHeight - rewardDescriptionOffset - 120);
22011      }
22012
22013      // Add events
22014      that.events(pledge);
22015    },
22016
22017    submit: function (type, authForm, paymentType, pledge) {
22018      var that = this;
22019      var successCallback, errorCallback, authType;
22020
22021      Form.submit.loadingState(pledge.submit);
22022
22023      if (type == "signup") {
22024        successCallback = User.signedUpEvent;
22025        errorCallback = User.signedUpErrorEvent;
22026        authType = User.signup;
22027      } else if (type == "login") {
22028        successCallback = User.loggedInEvent;
22029        errorCallback = User.loginErrorEvent;
22030        authType = User.login;
22031      }
22032
22033      authForm.one(successCallback, function () {
22034        if (Settings.beta.tokenizationAvailable() && successCallback == User.loggedInEvent) {
22035          var currentModal = pledge.submit.closest(".js-modal");
22036          var loading = currentModal.find(".js-modal-loading");
22037          var panelContents = currentModal.find(".js-panels");
22038          Modal.loading.hide(loading);
22039          Form.submit.defaultState(pledge.submit);
22040          Panels.showSubmitButton(currentModal, Panels.pledgeSubmit);
22041          Panels.toggleContents(panelContents, Panels.loggedIn);
22042        } else {
22043          pledge.payments.one("paymentFormLoaded", function () {
22044            var selector = that.paymentTypeSelector(pledge, paymentType);
22045            var paymentForm = $(selector, pledge.payments);
22046            paymentForm.submit();
22047          });
22048          PledgePayments.getForm(pledge.node, false);
22049        }
22050      });
22051
22052      authForm.one(errorCallback, function () {
22053        authForm.off(successCallback);
22054        Form.submit.errorState(pledge.submit);
22055        Scroll.smooth.doScroll("reset", 0, pledge.content);
22056      });
22057
22058      authType.submit(authForm, false);
22059    },
22060  };
22061
22062  Pledge.init();
22063
22064  return Pledge;
22065});
22066/**
22067* PledgeHigh
22068* @namespace Verkami
22069* @class PledgeHigh
22070*/
22071
22072var name = 'Verkami/PledgeHigh';
22073var deps = [
22074  'Verkami/Form',
22075  'Verkami/Modal',
22076  'Verkami/Settings'
22077];
22078
22079modulejs.define(name, deps, function(Form, Modal, Settings) {
22080  var PledgeHigh = {
22081    nodes: [],
22082
22083    init: function() {
22084      var that = this;
22085      var modalId = '';
22086      var node = [];
22087      var trigger = [];
22088      that.nodes = $('.js-pledge-high');
22089
22090      if (that.nodes.length) {
22091        that.nodes.each(function() {
22092          node = $(this);
22093
22094          node.on('submit', function(e) {
22095            node = $(this);
22096            modalId = node.closest('.js-modal').attr('data-modal-id');
22097            trigger = $('.js-pledge-high-trigger', node);
22098
22099            // Prevent form native submitting
22100            e.preventDefault();
22101
22102            // Change submit button to loading state
22103            Form.submit.loadingState(trigger);
22104
22105            // Send request
22106            $.post(node.attr('action'), node.serialize())
22107              .done(function() {
22108                // Change submit button to success state
22109                Form.submit.successState(trigger);
22110
22111                // Close modal after a little bit
22112                setTimeout(function() {
22113                  Modal.hide(modalId);
22114                }, Settings.speed * 10);
22115              })
22116              .fail(function() {
22117                // Change submit button to error state
22118                Form.submit.errorState(trigger);
22119              });
22120          });
22121        });
22122      }
22123    }
22124  };
22125
22126  PledgeHigh.init();
22127
22128  return PledgeHigh;
22129});
22130/**
22131 * PledgePayments
22132 * @namespace Verkami
22133 * @class PledgePayments
22134 */
22135
22136var name = "Verkami/PledgePayments";
22137var deps = ["Verkami/Form", "Verkami/Modal", "Verkami/Settings", "Verkami/Utils"];
22138
22139modulejs.define(name, deps, function (Form, Modal, Settings, Utils) {
22140  var PledgePayments = {
22141    disabledClass: "modal-pledge__payment--disabled",
22142
22143    init: function () {
22144      var that = this;
22145      // Initialize Retry Payment controller
22146      that.retryPaypal.init();
22147      that.retryRedsys.init();
22148    },
22149
22150    disable: function (node, hide) {
22151      var that = this;
22152      if (hide) {
22153        node.fadeOut();
22154      } else {
22155        node.addClass(that.disabledClass);
22156
22157        if (!node.is(":visible")) {
22158          node.fadeIn();
22159        }
22160      }
22161    },
22162
22163    reset: function (node) {
22164      var that = this;
22165
22166      Form.reset(node);
22167      $(".js-pledge-payments-forms", node).empty();
22168      $(".js-tokenized-cards", node)
22169        .empty()
22170        // Make the placeholder take no space when it holds no cards
22171        .removeClass("form-item");
22172
22173      // Hide pledge payment information
22174      if (!Utils.isMobile) {
22175        that.tip.hide($(".js-pledge-payments-tip", node));
22176      }
22177
22178      // Disable pledge button
22179      $(".js-pledge-submit", node.closest(".js-pledge")).trigger("trigger.vk.pledge.disableSubmit");
22180    },
22181
22182    enable: function (node, options) {
22183      options = options || {};
22184      var that = this;
22185      if (options.hidePayments) {
22186        node.fadeOut(Settings.speed);
22187      } else {
22188        if (!node.is(":visible")) {
22189          node.delay(Settings.speed).fadeIn(Settings.speed);
22190        }
22191        node.removeClass(that.disabledClass);
22192        //that.checkDefaultPaymentMethod(node);
22193      }
22194    },
22195
22196    checkDefaultPaymentMethod: function (pledgeNode) {
22197      var that = this;
22198      var selectedMethod = $(".js-pledge-payments-trigger", pledgeNode).first();
22199      selectedMethod.prop("checked", true);
22200      that.paymentMethodSelected(selectedMethod);
22201    },
22202
22203    paymentMethodSelected: function (paymentMethod) {
22204      var that = this;
22205      var pledge = paymentMethod.closest(".js-pledge");
22206      var pledgeSubmit = $(".js-pledge-submit", pledge);
22207      var isLoggedIn = $(".js-panels", pledge).data("logged-in");
22208
22209      if (isLoggedIn) {
22210        PledgePayments.getForm(pledge, true);
22211      } else {
22212        // Else, enable pledge button, payment form will be requested when user triggers the submit
22213        pledgeSubmit.trigger("trigger.vk.pledge.enableSubmit");
22214      }
22215      that.showTokenizationCheck(pledge, paymentMethod);
22216      that.showBizumDisclaimer(pledge, paymentMethod);
22217    },
22218
22219    showTokenizationCheck: function (pledge, paymentMethod) {
22220      var paymentType = paymentMethod.attr("data-pledge-payment");
22221      var box = pledge.find(".js-redsys-token-request-box");
22222      if (paymentType == "redsys" || paymentType == "redsys_direct") {
22223        box.slideDown();
22224      } else {
22225        box.slideUp();
22226      }
22227    },
22228
22229    showBizumDisclaimer: function (pledge, paymentMethod) {
22230      var paymentType = paymentMethod.attr("data-pledge-payment");
22231      var box = pledge.find(".js-bizum-disclaimer");
22232      if (paymentType == "bizum" || paymentType == "bizum_direct") {
22233        box.slideDown();
22234      } else {
22235        box.slideUp();
22236      }
22237    },
22238
22239    getForm: function (pledgeNode, waitForUser) {
22240      var that = this;
22241      var loading = [];
22242      var pledge = {
22243        content: $(".js-pledge-content", pledgeNode),
22244        node: pledgeNode,
22245        payments: $(".js-pledge-payments", pledgeNode),
22246        paymentsTip: $(".js-pledge-payments-tip", pledgeNode),
22247        submit: $(".js-pledge-submit", pledgeNode),
22248      };
22249      var paymentTriggers = $(".js-pledge-payments-trigger", pledge.payments);
22250      var paymentTrigger = paymentTriggers.filter(":checked");
22251      var paymentEndpoint = paymentTrigger.attr("data-pledge-payment-endpoint");
22252      var paymentType = paymentTrigger.attr("data-pledge-payment");
22253      var paymentForm = $(".js-pledge-payments-" + paymentType, pledge.payments);
22254
22255      // Request payment form if it doesn't exist yet
22256      if (!paymentForm.length) {
22257        loading = pledge.payments.closest(".js-modal").find(".js-modal-loading");
22258        // Disable selector
22259        paymentTriggers.prop("disabled", true);
22260        // Hide pledge payment information
22261        if (!Utils.isMobile) {
22262          that.tip.hide(pledge.paymentsTip);
22263        }
22264        // Show loading spinner
22265        Modal.loading.show(loading);
22266
22267        $.ajax({
22268          type: "GET",
22269          url: paymentEndpoint,
22270          dataType: "html",
22271          success: function (response) {
22272            // Insert new payment form
22273            $(".js-pledge-payments-forms", pledge.payments).append(response);
22274
22275            // If feedback is required
22276            if (waitForUser) {
22277              // Enable selector back
22278              paymentTriggers.prop("disabled", false);
22279
22280              // Hide loading spinner
22281              Modal.loading.hide(loading);
22282
22283              // Show pledge payment information
22284              if (!Utils.isMobile) {
22285                that.tip.show(pledge.paymentsTip);
22286              }
22287
22288              // Enable pledge button
22289              pledge.submit.trigger("trigger.vk.pledge.enableSubmit");
22290            } else {
22291              // Trigger payment form loaded callback
22292              pledge.payments.trigger("paymentFormLoaded");
22293            }
22294          },
22295        });
22296      } else {
22297        // Show pledge payment information
22298        if (!Utils.isMobile) {
22299          that.tip.show(pledge.paymentsTip);
22300        }
22301
22302        // Enable pledge button
22303        pledge.submit.trigger("trigger.vk.pledge.enableSubmit");
22304      }
22305    },
22306
22307    retryRedsys: {
22308      init: function () {
22309        var that = this;
22310        $("body").on("click.PledgeRetry", ".js-pledge-payment-retry-redsys", function (e) {
22311          e.preventDefault();
22312          that.retry($(this));
22313        });
22314      },
22315      retry: function (node) {
22316        var endpoint = node.attr("data-pledge-payment-retry-redsys-endpoint");
22317        var formHolder = node.siblings(".js-pledge-payment-retry-redsys-form");
22318        $.ajax({
22319          type: "GET",
22320          url: endpoint,
22321          dataType: "html",
22322          success: function (response) {
22323            formHolder.append(response);
22324            $("form", formHolder).submit();
22325          },
22326        });
22327      },
22328    },
22329
22330    retryPaypal: {
22331      init: function () {
22332        var that = this;
22333        $("body").on("click.PledgeRetry", ".js-pledge-payment-retry-paypal", function (e) {
22334          e.preventDefault();
22335
22336          that.send($(this));
22337        });
22338      },
22339
22340      send: function (node) {
22341        // Error 520009: "Account AUTHOR_EMAIL is restricted"
22342        var authorAccountIsRestrictedError = "520009";
22343        var authorEmail = node.attr("data-pledge-payment-retry-author");
22344        var endpoint = node.attr("data-pledge-payment-retry-endpoint");
22345        var backerErrorModal = node.attr("data-pledge-payment-retry-backer-error-modal");
22346        var authorErrorModal = node.attr("data-pledge-payment-retry-author-error-modal");
22347        var success = node.attr("data-pledge-payment-retry-success-modal");
22348        var errorPayload = [];
22349        var errorList = [];
22350        var errorFlat = {};
22351        var errorContent = [];
22352        var errorsIdList = [];
22353        var errorAccountRestrictedIndex = null;
22354        var errorAccountRestrictedEmail = null;
22355        var modal = [];
22356        var modalData = {};
22357
22358        $.get(endpoint, function (data) {
22359          if (data.paymentExecStatus === "COMPLETED") {
22360            modal = Modal.get(success);
22361            modalData = {
22362              modalTrigger: success,
22363            };
22364
22365            // Switch button to success state
22366            Form.submit.successState(node);
22367
22368            // Open success payment modal
22369            Modal.show(modalData);
22370
22371            // Refresh page if user closes the modal
22372            $(".js-modal-close", modal)
22373              .off("click.vk.modal.close")
22374              .on("click", function () {
22375                location.reload(true);
22376              });
22377          } else {
22378            // Switch button to error state
22379            Form.submit.errorState(node);
22380
22381            // Join all errors
22382            errorPayload = (data.payErrorList && data.payErrorList.payError) || data.error;
22383
22384            // Parse errors
22385            errorList = $.map(errorPayload, function (e) {
22386              errorFlat = e.error ? e.error : e;
22387
22388              return {
22389                id: errorFlat.errorId,
22390                message: errorFlat.message,
22391                parameter: errorFlat.parameter && errorFlat.parameter[0],
22392              };
22393            });
22394
22395            if (errorList.length) {
22396              errorContent = $("<div>");
22397
22398              // Output errors in HTML
22399              $.each(errorList, function (i, val) {
22400                $("<p>")
22401                  .html(errorList[i].message + "<br />Error ID: " + errorList[i].id)
22402                  .appendTo(errorContent);
22403              });
22404
22405              // List errors by ID
22406              errorsIdList = $.map(errorList, function (e) {
22407                return e.id;
22408              });
22409
22410              errorAccountRestrictedIndex = errorsIdList.indexOf(authorAccountIsRestrictedError);
22411              if (errorAccountRestrictedIndex !== -1) {
22412                // If present, check if the error is due to author's email being restricted
22413                errorAccountRestrictedEmail =
22414                  errorList[errorAccountRestrictedIndex].parameter.__value__ ||
22415                  errorList[errorAccountRestrictedIndex].parameter;
22416              }
22417              if (errorAccountRestrictedEmail === authorEmail) {
22418                modalData = { modalTrigger: authorErrorModal };
22419              } else {
22420                modalData = {
22421                  modalTrigger: backerErrorModal,
22422                  pledgePaymentRetryErrorContent: errorContent,
22423                };
22424              }
22425              // Open PayPal error modal
22426              Modal.show(modalData);
22427            }
22428          }
22429        });
22430      },
22431    },
22432
22433    tip: {
22434      delay: 5000,
22435      timeout: null,
22436      tipVisibleClass: "modal-pledge__payment__tip--visible",
22437
22438      hide: function (node) {
22439        var that = this;
22440
22441        node.removeClass(that.tipVisibleClass);
22442      },
22443
22444      show: function (node) {
22445        var that = this;
22446
22447        node.addClass(that.tipVisibleClass);
22448
22449        clearTimeout(that.timeout);
22450
22451        that.timeout = setTimeout(function () {
22452          that.hide(node);
22453        }, that.delay);
22454      },
22455    },
22456  };
22457
22458  PledgePayments.init();
22459
22460  return PledgePayments;
22461});
22462/**
22463 * ProjectHero
22464 * @namespace Verkami
22465 * @class ProjectHero
22466 */
22467
22468var name = "Verkami/ProjectHero";
22469var deps = ["Verkami/Player", "Verkami/Settings", "Verkami/Utils"];
22470
22471modulejs.define(name, deps, function (Player, Settings, Utils) {
22472  var ProjectHero = {
22473    node: [],
22474    playingClass: "project-hero--playing",
22475
22476    init: function () {
22477      var that = this;
22478      that.node = $(".js-project-hero");
22479
22480      if (that.node.length) {
22481        that.follow.init();
22482        that.player.init();
22483      }
22484    },
22485
22486    follow: {
22487      node: [],
22488      liteClass: "follow--lite",
22489      liteWidth: "104px",
22490
22491      init: function () {
22492        var that = this;
22493        this.follow = $(".follow", ProjectHero.node);
22494        var width = 0;
22495
22496        if (this.follow.length) {
22497          width = that.follow.outerWidth();
22498
22499          // Save its initial width to perform the animation
22500          that.follow.data("follow-width", width);
22501        }
22502      },
22503
22504      collapse: function () {
22505        var that = this;
22506        that.follow.addClass(that.liteClass);
22507
22508        that.follow.stop().animate(
22509          {
22510            width: that.liteWidth,
22511          },
22512          Settings.speed * 4,
22513          "easeInOutCubic"
22514        );
22515      },
22516
22517      expand: function () {
22518        var that = this;
22519        that.follow.removeClass(that.liteClass);
22520
22521        that.follow.stop().animate(
22522          {
22523            width: that.follow.data("follow-width"),
22524          },
22525          Settings.speed * 4
22526        );
22527      },
22528    },
22529
22530    player: {
22531      init: function () {
22532        var that = ProjectHero;
22533        var player = $(".js-player", that.node);
22534
22535        player.on("hook.vk.player.start", function () {
22536          that.node.addClass(that.playingClass);
22537
22538          if (Utils.isDesktop) {
22539            that.follow.collapse();
22540          }
22541        });
22542
22543        player.on("hook.vk.player.end", function () {
22544          that.node.removeClass(that.playingClass);
22545
22546          if (Utils.isDesktop) {
22547            that.follow.expand();
22548          }
22549        });
22550      },
22551    },
22552  };
22553
22554  ProjectHero.init();
22555
22556  return ProjectHero;
22557});
22558/**
22559 * Project
22560 * @namespace Verkami
22561 * @class Project
22562 */
22563
22564var name = "Verkami/Project";
22565var deps = [
22566  "Verkami/Modal",
22567  "Verkami/Player",
22568  "Verkami/Scroll",
22569  "Verkami/Settings",
22570  "Verkami/Sticky",
22571  "Verkami/Tabs",
22572  "Verkami/TwitterWidget",
22573  "Verkami/Url",
22574  "Verkami/Utils",
22575  "Verkami/Video",
22576];
22577
22578modulejs.define(name, deps, function (Modal, Player, Scroll, Settings, Sticky, Tabs, TwitterWidget, Url, Utils, Video) {
22579  var Project = {
22580    node: [],
22581    about: [],
22582    tabs: [],
22583
22584    init: function () {
22585      var that = this;
22586      var initialPageName = "";
22587      var pageName = "";
22588      var trigger = [];
22589      var tabsIndex = null;
22590      var tabsContents = [];
22591      var stickyOffset = null;
22592      var hash = Utils.hash.get();
22593      var hashTest = /^[a-zA-Z0-9-_]+$/;
22594      var hashComment = [];
22595      that.node = $(".js-project");
22596
22597      $(".js-project-bonus-input").one("input.project.bonus", function (e) {
22598        $(".js-project-bonus-submit").slideDown();
22599      });
22600
22601      that.node.on("keypress.checkout.bonus paste.checkout.bonus", ".js-project-bonus-input", function (e) {
22602        if (String.fromCharCode(e.keyCode).match(/[^0-9]/g)) return false;
22603      });
22604
22605      if (that.node.length) {
22606        that.about = $(".js-project-about", that.node);
22607        that.tabs = $(".js-project-tabs", that.node);
22608        initialPageName = that.tabs.attr("data-project-tabs-active");
22609
22610        // Save initial URL state
22611        window.history.replaceState({ page: initialPageName }, null, location.href);
22612
22613        // Hook browser history
22614        $(window).on("popstate.project", function (e) {
22615          if (e.originalEvent.state) {
22616            pageName = e.originalEvent.state.page;
22617            tabsContents = $(".js-tabs-content", that.tabs);
22618            stickyOffset = Sticky.getOffset();
22619
22620            switch (pageName) {
22621              case "project":
22622                trigger = $(".js-tabs-trigger", that.tabs).filter(function () {
22623                  return $(this).attr("data-url-name") === "project";
22624                });
22625                tabsIndex = $(".js-tabs-trigger", that.tabs).index(trigger);
22626
22627                Tabs.toggleContents(tabsContents, tabsIndex);
22628                Tabs.toggleTriggers(trigger);
22629                Scroll.smooth.doScroll(that.tabs, stickyOffset);
22630
22631                break;
22632
22633              case "projectBlogList":
22634                trigger = $(".js-tabs-trigger", that.tabs).filter(function () {
22635                  return $(this).attr("data-url-name") === "projectBlogList";
22636                });
22637                tabsIndex = $(".js-tabs-trigger", that.tabs).index(trigger);
22638
22639                Tabs.toggleContents(tabsContents, tabsIndex);
22640                Tabs.toggleTriggers(trigger);
22641                Scroll.smooth.doScroll(that.tabs, stickyOffset);
22642
22643                // Show list view
22644                that.blog.toggleView("list");
22645                break;
22646
22647              case "projectBlogPost":
22648                var trigger = $(".js-tabs-trigger", that.tabs).filter(function () {
22649                  return $(this).attr("data-url-name") === "projectBlogList";
22650                });
22651                var tabsIndex = $(".js-tabs-trigger", that.tabs).index(trigger);
22652
22653                Tabs.toggleContents(tabsContents, tabsIndex);
22654                Tabs.toggleTriggers(trigger);
22655                Scroll.smooth.doScroll(that.tabs, stickyOffset);
22656
22657                // Show list view
22658                that.blog.toggleView("post");
22659                break;
22660
22661              default:
22662                return;
22663            }
22664          }
22665        });
22666
22667        // Initialize Twitter Third Party Widget
22668        TwitterWidget.init();
22669
22670        // Initialize project blog controller
22671        that.blog.init();
22672
22673        // Process images and embeds in mobile version
22674        if (Utils.isMobile) {
22675          that.processMedia();
22676        }
22677
22678        // Hook tabs change event
22679        $(".js-tabs-content", that.tabs).on("hook.vk.tabs.show", function (e, index) {
22680          // Mobile only: Set blog class to project tabs if blog is active
22681          if (Utils.isMobile) {
22682            var urlName = $(".js-tabs-trigger", that.tabs).eq(index).attr("data-url-name");
22683            var tabClass = "project-details__block--blog";
22684
22685            if (urlName === "projectBlogList") {
22686              that.tabs.addClass(tabClass);
22687            } else {
22688              that.tabs.removeClass(tabClass);
22689            }
22690          }
22691
22692          // Reset video size if tab was hidden
22693          $(".js-video", this).each(function () {
22694            Video.setSize($(this));
22695          });
22696        });
22697
22698        // Show blog list
22699        that.node.on("click", ".js-project-more-updates", function () {
22700          var activeIndex = 1;
22701          var activeTrigger = $(".js-tabs-trigger", that.tabs).eq(activeIndex);
22702          var tabsContents = $(".js-tabs-content", that.tabs);
22703          var stickyOffset = Sticky.getOffset();
22704
22705          Tabs.toggleContents(tabsContents, activeIndex);
22706          Tabs.toggleTriggers(activeTrigger);
22707          Scroll.smooth.doScroll(that.tabs, stickyOffset);
22708        });
22709
22710        if (Utils.isMobile || Utils.Tablet) {
22711          that.tabs.on("click", ".js-tabs-trigger", function () {
22712            Scroll.smooth.doScroll($("#project_details_anchor"));
22713          });
22714        }
22715
22716        // If there is any comment anchored, scroll down to it
22717        if (hash && hashTest.test(hash)) {
22718          hashComment = $("#" + hash, that.node);
22719
22720          if (hashComment.length) {
22721            setTimeout(function () {
22722              stickyOffset = Sticky.getOffset();
22723
22724              Scroll.smooth.doScroll(hashComment, stickyOffset + 40);
22725            }, Settings.speed * 4);
22726          }
22727        }
22728      }
22729    },
22730
22731    blog: {
22732      blogListPlaceholder: [],
22733      blogPostPlaceholder: [],
22734      blogLoading: [],
22735
22736      init: function () {
22737        var that = this;
22738        that.blogListPlaceholder = $(".js-project-blog-list", Project.node);
22739        that.blogPostPlaceholder = $(".js-project-blog-post", Project.node);
22740        that.blogLoading = $(".js-project-blog-loading", Project.node);
22741
22742        Project.node.on("click", ".js-project-blog-post-load", function (e) {
22743          var source = $(this).attr("href");
22744
22745          e.preventDefault();
22746
22747          that.getPost(source);
22748        });
22749
22750        that.blogPostPlaceholder.on("click", ".js-project-blog-back", function (e) {
22751          var source = $(this).attr("href");
22752
22753          e.preventDefault();
22754
22755          // Show list view
22756          that.toggleView("list", source);
22757        });
22758      },
22759
22760      getPost: function (source) {
22761        var that = this;
22762        var stickyOffset = Sticky.getOffset();
22763        var isBlogListVisible = that.blogListPlaceholder.is(":visible");
22764        var hash = source.indexOf("#") != -1 ? source.substring(source.indexOf("#")) : false;
22765        var trigger = [];
22766        var tabsIndex = null;
22767
22768        // Show list view
22769        if (!isBlogListVisible) {
22770          trigger = $(".js-tabs-trigger", Project.tabs).filter(function () {
22771            return $(this).attr("data-url-name") === "projectBlogList";
22772          });
22773          tabsIndex = $(".js-tabs-trigger", Project.tabs).index(trigger);
22774
22775          Tabs.toggleContents($(".js-tabs-content", Project.tabs), tabsIndex);
22776          Tabs.toggleTriggers(trigger);
22777        }
22778
22779        // Scroll to the top of the post
22780        Scroll.smooth.doScroll(Project.tabs, stickyOffset);
22781
22782        // Show spinner
22783        that.blogLoading.fadeIn();
22784
22785        $.get(source, function (response) {
22786          // Add post content to the DOM
22787          that.blogPostPlaceholder.html(response);
22788
22789          // Refresh modal triggers
22790          Modal.refresh();
22791
22792          // Refresh players
22793          console.log("Setting size for players to adjust in " + Settings.speed);
22794          setTimeout(() => {
22795            $(".js-video", that.blogPostPlaceholder).each(function () {
22796              console.log("Setting size for video... " + $(this));
22797              Video.setSize($(this));
22798            });
22799            console.log("Player init");
22800            Player.init();
22801            console.log("Player done");
22802          }, Settings.speed * 2);
22803
22804          // Hide spinner
22805          that.blogLoading.fadeOut();
22806
22807          // Show post view
22808          that.toggleView("post", source);
22809
22810          if (hash) {
22811            setTimeout(function () {
22812              Scroll.smooth.doScroll($(hash), stickyOffset);
22813            }, Settings.speed * 3);
22814          }
22815        });
22816      },
22817
22818      toggleView: function (view, source) {
22819        var that = this;
22820
22821        if (view === "post") {
22822          that.blogListPlaceholder.fadeOut(function () {
22823            that.blogPostPlaceholder.fadeIn();
22824
22825            // Update URL
22826            if (source) {
22827              Url.update({ page: "projectBlogPost" }, source);
22828            }
22829          });
22830        } else {
22831          that.blogPostPlaceholder.fadeOut(function () {
22832            that.blogListPlaceholder.fadeIn();
22833
22834            // Update URL
22835            if (source) {
22836              Url.update({ page: "projectBlogList" }, source);
22837            }
22838          });
22839        }
22840      },
22841    },
22842
22843    processMedia: function () {
22844      var that = this;
22845      var iframes = $("iframe", that.about);
22846      var images = $("img", that.about);
22847      var nodes = $.fn.add.call(iframes, images);
22848      var parent = [];
22849
22850      nodes.each(function () {
22851        parent = $(this).parent();
22852
22853        if (parent.hasClass("js-project-about")) {
22854          $(this).wrap('<p class="project-details__about__media"></p>');
22855        } else {
22856          parent.addClass("project-details__about__media");
22857        }
22858      });
22859    },
22860  };
22861
22862  Project.init();
22863
22864  return Project;
22865});
22866/**
22867 * Promotion
22868 * @namespace Verkami
22869 * @class Promotion
22870 */
22871
22872var name = "Verkami/Promotion";
22873var deps = ["Verkami/CookiesAgreement", "Verkami/Utils"];
22874
22875modulejs.define(name, deps, function(CookiesAgreement, Utils) {
22876  var Promotion = {
22877    nodes: [],
22878    hiddenClass: "promotion--hidden",
22879
22880    init: function() {
22881      var that = this;
22882      that.nodes = $(".js-promotion");
22883
22884      if (that.nodes.length) {
22885        var close = [];
22886        var links = [];
22887
22888        that.nodes.each(function() {
22889          var node = this;
22890          var link = $(node).find("a");
22891
22892          if (that.isPromotionHidden($(node))) {
22893            $(node).addClass(that.hiddenClass);
22894          } else {
22895            $(node).on("click", function() {
22896              that.hidePromotion($(node));
22897              Utils.redirect(link.attr("href"));
22898            });
22899            close = $(".js-promotion-close", node);
22900            close.on("click", function(e) {
22901              e.stopPropagation();
22902              that.hidePromotion($(node));
22903            });
22904            link.on("click", function(e) {
22905              e.stopPropagation();
22906              that.hidePromotion($(node));
22907            });
22908          }
22909        });
22910      }
22911    },
22912
22913    isPromotionHidden: function(promotion) {
22914      return !!Cookies.get(promotion.attr("data-promotion-cookie-name"));
22915    },
22916
22917    hidePromotion: function(promotion) {
22918      var that = this;
22919      promotion.addClass(that.hiddenClass);
22920      Cookies.set(promotion.attr("data-promotion-cookie-name"), "true", { expires: 365 * 20 });
22921    }
22922  };
22923
22924  Promotion.init();
22925
22926  return Promotion;
22927});
22928/**
22929 * Question
22930 * @namespace Verkami
22931 * @class Question
22932 */
22933
22934var name = "Verkami/Question";
22935var deps = ["Verkami/Form", "Verkami/Modal", "Verkami/Settings"];
22936
22937modulejs.define(name, deps, function (Form, Modal, Settings) {
22938  var Question = {
22939    nodes: [],
22940
22941    init: function () {
22942      var that = this;
22943      that.nodes = $(".js-question");
22944
22945      that.nodes.each(function () {
22946        that.setup($(this));
22947      });
22948    },
22949
22950    setup: function (node) {
22951      var endpoint = "";
22952      var submit = [];
22953
22954      node.on("submit", function (e) {
22955        endpoint = node.attr("action");
22956        submit = $(":submit", node);
22957
22958        // Prevent submit form by default
22959        e.preventDefault();
22960
22961        Form.submit.loadingState(submit);
22962
22963        // Send the following status and get the current likes
22964        $.ajax({
22965          type: "POST",
22966          url: endpoint,
22967          data: $(this).serialize(),
22968          error: function (data) {
22969            Form.submit.errorState(submit);
22970          },
22971          success: function (data) {
22972            if (data.sent) {
22973              submit.removeAttr("disabled");
22974              Form.submit.successState(submit);
22975
22976              setTimeout(function () {
22977                submit.closest(".js-modal").trigger("trigger.vk.modal.close");
22978
22979                setTimeout(function () {
22980                  Form.reset(submit.closest("form"));
22981                }, Settings.speed * 3);
22982              }, Settings.speed * 12);
22983            } else {
22984              Form.submit.errorState(submit);
22985            }
22986          },
22987        });
22988      });
22989    },
22990  };
22991
22992  Question.init();
22993
22994  return Question;
22995});
22996/**
22997* Search
22998* @namespace Verkami
22999* @class Search
23000*/
23001
23002var name = 'Verkami/Search';
23003var deps = [
23004  'Verkami/Settings',
23005  'Verkami/Utils'
23006];
23007
23008modulejs.define(name, deps, function(Settings, Utils) {
23009  var Search = {
23010    node: [],
23011    close: [],
23012    input: [],
23013    form: [],
23014    trigger: [],
23015    wrapper: [],
23016    loadingClass: 'search--loading',
23017    visibleClass: 'search-visible',
23018
23019    init: function() {
23020      var that = this;
23021      that.node = $('.js-search');
23022
23023      if (that.node.length) {
23024        that.close = $('.js-search-close', that.node);
23025        that.input = $('.js-search-field', that.node);
23026        that.form = $('.js-search-form', that.node);
23027        that.trigger = $('.js-search-trigger');
23028        that.wrapper = $('.js-search-wrapper', that.node);
23029
23030        that.results.init();
23031
23032        that.trigger.on('click', function() {
23033          $('body').addClass(that.visibleClass);
23034
23035          // @todo: Can I avoid speed as first parameter?
23036          that.node.fadeIn(Settings.speed, function() {
23037            that.setup();
23038
23039            that.input.focus();
23040
23041            $(window).resize(function() {
23042              that.setup();
23043            });
23044          });
23045
23046          // Escape key closes the search layer
23047          $(document).on('keyup', function(e) {
23048            if (e.keyCode == 27) {
23049              that.hide();
23050
23051              $(this).off('keyup');
23052            }
23053          });
23054        });
23055
23056        that.close.on('click', function() {
23057          that.hide();
23058        });
23059      }
23060    },
23061
23062    hide: function() {
23063      var that = this;
23064
23065      $('body').removeClass(that.visibleClass);
23066      that.node.fadeOut();
23067      that.input.blur();
23068    },
23069
23070    results: {
23071      categories: [],
23072      empty: [],
23073      projects: [],
23074      source: '',
23075      lastQuery: '',
23076      minQuery: 3,
23077      timeout: null,
23078
23079      init: function() {
23080        var that = this;
23081        that.categories = $('.js-search-categories', Search.node);
23082        that.empty = $('.js-search-empty', Search.node);
23083        that.projects = $('.js-search-projects', Search.node);
23084        that.source = Search.input.data('search-source');
23085
23086        Search.input.on('keyup', function() {
23087          that.getResults();
23088        });
23089      },
23090
23091      buildResult: function(data) {
23092        var name = data.name;
23093        var url = data.url;
23094        var result = $('<li>', { class: 'search__results__group__list__item' });
23095        var link = $('<a>', { href: url, title: name }).text(name).appendTo(result);
23096
23097        return result;
23098      },
23099
23100      getResults: function() {
23101        var that = this;
23102        var text = Search.input.val().toLowerCase();
23103
23104        if (text.length >= that.minQuery && text !== that.lastQuery) {
23105          clearTimeout(that.timeout);
23106
23107          that.timeout = setTimeout(function() {
23108            // Show spinner
23109            Search.node.addClass(Search.loadingClass);
23110
23111            // Avoid submit form until request ends
23112            Search.form.off('submit.form').on('submit.form', function(e) {
23113              e.preventDefault();
23114            });
23115
23116            // Disable search input
23117            Search.input.attr('disabled', true);
23118
23119            // Hide results
23120            that.hideResults([that.categories, that.empty, that.projects]);
23121
23122            $.ajax({
23123              type: 'GET',
23124              url: that.source,
23125              data: {
23126                'term': text,
23127                'sorted_by': 'by_money'
23128              },
23129              dataType: 'text',
23130              error: function(msg) {
23131                // We need to check if the value is the same
23132                if (text == Search.input.val().toLowerCase()) {
23133                  $('form', Search.node).attr('action', '#');
23134                }
23135              },
23136              success: function(msg) {
23137                // We need to check if the value is the same
23138                if (text == Search.input.val().toLowerCase()) {
23139                  var results = $.parseJSON(msg);
23140                  var url = results.items[0].url;
23141                  var projects = results.items[1].children;
23142                  var categories = results.items[2].children;
23143
23144                  // Cache the query
23145                  that.lastQuery = text;
23146
23147                  // Remove form submit blocker
23148                  Search.form.off('submit.form');
23149
23150                  if (categories || projects) {
23151                    // Change search label
23152                    $('.js-search-label', Search.node).children('span').first().fadeOut('fast', function() {
23153                      $('.js-search-label', Search.node).children('span').last().fadeIn('fast');
23154                    });
23155
23156                    // Update search form target
23157                    $('form', Search.node).attr('action', url);
23158
23159                    if (categories) {
23160                      that.showResults(that.categories, categories);
23161                    }
23162
23163                    if (projects) {
23164                      that.showResults(that.projects, projects);
23165                    }
23166                  } else {
23167                    that.showResults(that.empty);
23168                  }
23169                }
23170              },
23171              complete: function() {
23172                // Remove spinner
23173                Search.node.removeClass(Search.loadingClass);
23174
23175                // Enable search input back again
23176                Search.input.attr('disabled', false).focus();
23177              }
23178            });
23179          }, Settings.delay);
23180        } else {
23181          if (text !== that.lastQuery) {
23182            // Change search label
23183            $('.js-search-label').children('span').last().fadeOut('fast', function() {
23184              $('.js-search-label').children('span').first().fadeIn('fast');
23185            });
23186
23187            // Hide results
23188            that.hideResults([that.categories, that.empty, that.projects]);
23189          }
23190        }
23191      },
23192
23193      hideResults: function(target) {
23194        var that = this;
23195
23196        $.each(target, function() {
23197          $(this).fadeOut('fast', function() {
23198            $('.js-search-results', this).children().remove().end();
23199          });
23200        });
23201      },
23202
23203      showResults: function(target, data) {
23204        var that = this;
23205        data = data ? data : false;
23206        var results = [];
23207        var resultsList = target.find('.js-search-results');
23208
23209        if (data) {
23210          $.each(data, function(index, val) {
23211            var result = that.buildResult(val);
23212
23213            results.push(result);
23214          });
23215
23216          target.fadeOut('fast', function() {
23217            resultsList.children().remove().end();
23218            resultsList.append(results).end().fadeIn('fast');
23219          });
23220        } else {
23221          target.fadeIn('fast');
23222        }
23223      }
23224    },
23225
23226    setup: function() {
23227      var that = this;
23228      var gutter = parseInt(that.node.css('padding-top'));
23229      var offset = that.wrapper.position().top + gutter;
23230      var viewportHeight = Utils.getViewportSize('height');
23231      var wrapperHeight = viewportHeight - offset;
23232
23233      that.wrapper.outerHeight(wrapperHeight);
23234    }
23235  };
23236
23237  Search.init();
23238
23239  return Search;
23240});
23241/**
23242* SettingsNotifications
23243* @namespace Verkami
23244* @class SettingsNotifications
23245*/
23246
23247var name = 'Verkami/SettingsNotifications';
23248
23249modulejs.define(name, function() {
23250  var SettingsNotifications = {
23251    node: [],
23252    box: [],
23253    triggers: [],
23254
23255    init: function() {
23256      var that = this;
23257      that.node = $('.js-profile-notifications');
23258
23259      if (that.node.length) {
23260        that.box = $('.js-profile-notifications-box', that.node);
23261        that.triggers = $('input[type=radio]', that.node);
23262        var isTrigger = $('.js-profile-notifications-trigger').is(':checked');
23263
23264        that.toggleBox(isTrigger);
23265
23266        that.triggers.on('change', function() {
23267          isTrigger = $(this).hasClass('js-profile-notifications-trigger');
23268
23269          that.toggleBox(isTrigger);
23270        });
23271      }
23272    },
23273
23274    toggleBox: function(isTrigger) {
23275      var that = this;
23276
23277      if (isTrigger) {
23278        that.box.slideDown();
23279      } else {
23280        that.box.slideUp();
23281      }
23282    }
23283  };
23284
23285  SettingsNotifications.init();
23286
23287  return SettingsNotifications;
23288});
23289/**
23290 * SettingsNotifications
23291 * @namespace Verkami
23292 * @class SettingsSubscriptions
23293 */
23294
23295var name = "Verkami/SettingsSubscriptions";
23296
23297modulejs.define(name, function() {
23298  var SettingsSubscriptions = {
23299    node: [],
23300    switchers: [],
23301    checks: [],
23302
23303    init: function() {
23304      var that = this;
23305      that.node = $(".js-settings-subscriptions");
23306
23307      if (that.node.length) {
23308        that.switchers = $(".js-settings-subscriptions-switcher", that.node);
23309        that.checks = $("input[type=checkbox]", that.node);
23310
23311        that.checks.on("click", function() {
23312          var switcher = $(this).siblings(".js-settings-subscriptions-switcher");
23313          if ($(this).is(":checked")) {
23314            switcher.show();
23315          } else {
23316            switcher.hide();
23317          }
23318        });
23319
23320        that.switchers.on("click", function() {
23321          if ($(this).attr("data-alternative-mode")) {
23322            that.switch($(this));
23323          }
23324        });
23325      }
23326    },
23327
23328    switch: function(switcher) {
23329      var currentMode = switcher.attr("data-current-mode");
23330      var currentModeName = switcher.attr("data-current-mode-name");
23331      var formField = switcher.parent().find(".js-settings-subscriptions-switcher-value");
23332      switcher.attr("data-current-mode", switcher.attr("data-alternative-mode"));
23333      switcher.attr("data-current-mode-name", switcher.attr("data-alternative-mode-name"));
23334      formField.val(switcher.attr("data-current-mode"));
23335      switcher.html(switcher.attr("data-current-mode-name"));
23336      switcher.attr("data-alternative-mode", currentMode);
23337      switcher.attr("data-alternative-mode-name", currentModeName);
23338    }
23339  };
23340
23341  SettingsSubscriptions.init();
23342
23343  return SettingsSubscriptions;
23344});
23345/**
23346* SocialManage
23347* @namespace Verkami
23348* @class SocialManage
23349*/
23350
23351var name = 'Verkami/SocialManage';
23352var deps = [
23353  'Verkami/Form'
23354];
23355
23356modulejs.define(name, deps, function(Form) {
23357  var SocialManage = {
23358    node: [],
23359    limit: 0,
23360    template: [],
23361
23362    init: function() {
23363      var that = this;
23364      that.node = $('.js-social-manage');
23365
23366      if (that.node.length) {
23367        that.limit = that.node.attr('data-social-profiles-limit');
23368        that.template = $('.js-social-manage-template', that.node);
23369
23370        // If limit is not reached, show a input to add a new link
23371        if (!that.isLimitReached()) {
23372          that.addLink();
23373        }
23374
23375        // Show new link and remove link once choosing a social network
23376        $(that.node).on('change.fs', '.js-social-manage-select', function() {
23377          var item = $(this).parents('.js-social-manage-item').removeClass('js-social-manage-placeholder');
23378          var isLast = !item.next('.js-social-manage-item').length;
23379
23380          $('.js-social-manage-remove', item).fadeIn('fast');
23381
23382          if (isLast && !that.isLimitReached()) {
23383            that.addLink();
23384          }
23385        });
23386
23387        // Remove social link
23388        that.node.on('click', '.js-social-manage-remove', function() {
23389          that.removeLink($(this));
23390        });
23391      }
23392    },
23393
23394    addLink: function() {
23395      var that = this;
23396      var links = $('.js-social-manage-item', that.node);
23397      var linkNew = that.template.clone().addClass('js-social-manage-placeholder');
23398      var linkNewId = $.now();
23399      var input = $('.js-social-manage-input', linkNew);
23400      var label = $('.js-social-manage-label', linkNew);
23401      var select = $('.js-social-manage-select', linkNew);
23402      var placeholder = 'placeholder';
23403      var newInputId = input.attr('id').replace(placeholder, linkNewId);
23404      var newInputName = input.attr('name').replace(placeholder, linkNewId);
23405      var newSelectName = select.attr('name').replace(placeholder, linkNewId);
23406
23407      // Update form fields unique attributes
23408      input.attr({
23409        'id': newInputId,
23410        'name': newInputName
23411      });
23412      label.attr('for', newInputId);
23413      select.attr('name', newSelectName);
23414
23415      // Style new select
23416      Form.select.refresh($('select', linkNew));
23417
23418      // Set classes, add to the DOM and show it
23419      linkNew.toggleClass('js-social-manage-template js-social-manage-item');
23420
23421      // Insert new link in the right place
23422      if (links.last().length) {
23423        linkNew.insertAfter(links.last());
23424      } else {
23425        linkNew.appendTo(that.node);
23426      }
23427
23428      // Show new link
23429      linkNew.slideDown('fast');
23430    },
23431
23432    isLimitReached: function() {
23433      var that = this;
23434      var linksCount = $('.js-social-manage-item', that.node).filter(function() {
23435        return $(this).is(':visible');
23436      }).length;
23437
23438      return linksCount === that.limit || linksCount >= that.limit;
23439    },
23440
23441    isPlaceholder: function() {
23442      var that = this;
23443      var isPlaceholder = $('.js-social-manage-placeholder', that.node).length;
23444
23445      return isPlaceholder;
23446    },
23447
23448    removeLink: function(trigger) {
23449      var that = this;
23450      var linkToRemove = trigger.closest('.js-social-manage-item');
23451      var linkHiddenName = $('.js-social-manage-input', linkToRemove).attr('name').replace('value', '_destroy');
23452
23453      // Save removed input in a hidden field
23454      $('<input>').attr({
23455        'name': linkHiddenName,
23456        'type': 'hidden',
23457        'value': 1
23458      }
23458).appendTo(linkToRemove);
23459
23460      // Hide the link
23461      linkToRemove.slideUp('fast', function() {
23462        // Add a new placeholder
23463        if (!that.isLimitReached() && !that.isPlaceholder()) {
23464          that.addLink();
23465        }
23466      });
23467    }
23468  };
23469
23470  SocialManage.init();
23471
23472  return SocialManage;
23473});
23474/**
23475* Start
23476* @namespace Verkami
23477* @class Start
23478*/
23479
23480var name = 'Verkami/Start';
23481var deps = [
23482  'Verkami/Scroll',
23483  'Verkami/Utils'
23484];
23485
23486modulejs.define(name, deps, function(Scroll, Utils) {
23487  var Start = {
23488    heroModule: [],
23489
23490    init: function() {
23491      var that = this;
23492      that.heroModule = $('.js-start-hero');
23493
23494      if (!Utils.isMobile && !Utils.isTablet) {
23495        if (that.heroModule.length) {
23496          that.setHeroHeight();
23497        }
23498
23499        that.parallax();
23500      }
23501
23502      that.bar.init();
23503    },
23504
23505    bar: {
23506      node: [],
23507      visibleClass: 'start-bar--visible',
23508      trigger: [],
23509      triggerOffset: null,
23510
23511      init: function() {
23512        var that = this;
23513        that.node = $('.js-start-bar');
23514
23515        if (that.node.length) {
23516          that.trigger = $('.js-start-bar-trigger');
23517          that.triggerOffset = that.trigger.offset().top;
23518
23519          that.toggle();
23520
23521          $(window).scroll(function() {
23522            that.toggle();
23523          });
23524        }
23525      },
23526
23527      toggle: function() {
23528        var that = this;
23529        var scrollPosition = Scroll.position();
23530
23531        if (scrollPosition > that.triggerOffset) {
23532          that.node.addClass(that.visibleClass);
23533        } else {
23534          that.node.removeClass(that.visibleClass);
23535        }
23536      }
23537    },
23538
23539    parallax: function() {
23540      var that = this;
23541      var offset = Utils.getViewportSize('height') / 2 - 55;
23542
23543      $.stellar({
23544        horizontalScrolling: false,
23545        parallaxBackgrounds: false,
23546        verticalOffset: offset
23547      });
23548
23549    },
23550
23551    setHeroHeight: function() {
23552      var that = this;
23553      var offsetToTop =  that.heroModule.offset().top;
23554      var viewportHeight = Utils.getViewportSize('height');
23555      var heroHeight = viewportHeight - offsetToTop;
23556
23557      that.heroModule.height(heroHeight);
23558    }
23559  };
23560
23561  Start.init();
23562
23563  return Start;
23564});
23565/**
23566* StartRewards
23567* @namespace Verkami
23568* @class StartRewards
23569*/
23570
23571var name = 'Verkami/StartRewards';
23572var deps = [
23573  'Verkami/DataTransfer',
23574  'Verkami/Form',
23575  'Verkami/Modal',
23576  'Verkami/ReadMore',
23577  'Verkami/Settings'
23578];
23579
23580modulejs.define(name, deps, function(DataTransfer, Form, Modal, ReadMore, Settings) {
23581  var StartRewards = {
23582    node: [],
23583
23584    init: function() {
23585      var that = this;
23586      that.node = $('.js-rewards');
23587
23588      if (that.node.length) {
23589        that.events();
23590      }
23591    },
23592
23593    add: function(rewardItem) {
23594      var that = this;
23595      var newRewardItem = rewardItem.clone().hide();
23596      var callback = $.Deferred();
23597
23598      // Set up reward ID
23599      newRewardItem = that.setup(newRewardItem, callback);
23600
23601      // Insert new reward in DOM after set it up
23602      $.when(callback).done(function(response) {
23603        if (response) {
23604          newRewardItem
23605            .removeClass('start__rewards__item--add')
23606            .insertBefore(rewardItem)
23607            .slideDown();
23608
23609          // Refresh events and other functionalities
23610          that.refreshReward(newRewardItem);
23611
23612          // Perform the dataTransfer from the form to the reward display
23613          DataTransfer.transfer($('.js-pull', newRewardItem).data());
23614
23615          // Reset add reward form
23616          Form.reset($('.start__rewards__item--add', that.node));
23617        }
23618      });
23619    },
23620
23621    delete: function(rewardItem) {
23622      var that = this;
23623
23624      // @todo: Check if it's possible to avoid the speed attribute
23625      rewardItem.slideUp(Settings.speed, function() {
23626        rewardItem.remove();
23627      });
23628    },
23629
23630    duplicate: function(rewardItem) {
23631      var that = this;
23632      var newRewardItem = rewardItem.clone().hide();
23633      var callback = $.Deferred();
23634
23635      // Set up reward ID
23636      newRewardItem = that.setup(newRewardItem, callback);
23637
23638      // Insert new reward in DOM after set it up
23639      $.when(callback).done(function(response) {
23640        if (response) {
23641          newRewardItem.insertAfter(rewardItem).slideDown();
23642
23643          // Refresh events and other functionalities
23644          that.refreshReward(newRewardItem);
23645        }
23646      });
23647    },
23648
23649    edit: function(rewardItem) {
23650      var that = this;
23651      var editedClass = 'start__rewards__item--edited';
23652
23653      // Format month display
23654      var monthPlaceholder = $('.js-reward-month', rewardItem);
23655      var month = moment(new Date(monthPlaceholder.html())).format('MMMM');
23656
23657      monthPlaceholder.html(month);
23658
23659      setTimeout(function() {
23660        rewardItem.addClass(editedClass);
23661
23662        setTimeout(function() {
23663          rewardItem.removeClass(editedClass);
23664        }, Settings.speed * 2);
23665      }, Settings.speed);
23666    },
23667
23668    events: function() {
23669      var that = this;
23670
23671      that.node.on('click', '.js-rewards-add', function(e) {
23672        e.preventDefault();
23673
23674        that.add(that.getRewardItem($(this)));
23675      });
23676
23677      that.node.on('click', '.js-rewards-delete', function() {
23678        that.delete(that.getRewardItem($(this)));
23679      });
23680
23681      that.node.on('click', '.js-rewards-duplicate', function() {
23682        that.duplicate(that.getRewardItem($(this)));
23683      });
23684
23685      that.node.on('click', '.js-rewards-edit', function(e) {
23686        e.preventDefault();
23687
23688        that.edit(that.getRewardItem($(this)));
23689      });
23690    },
23691
23692    getRewardItem: function(element) {
23693      var rewardItem = element.closest('.js-rewards-item');
23694
23695      return $(rewardItem);
23696    },
23697
23698    refreshReward: function(rewardItem) {
23699      // Set Up readMore node
23700      ReadMore.setup(rewardItem);
23701
23702      // Refresh dataTransfer
23703      DataTransfer.refresh();
23704
23705      // Set Up selects and form validation
23706      Form.emptyCheck.init();
23707      Form.select.refresh($('.js-select select', rewardItem));
23708
23709      // Refresh modal events
23710      Modal.refresh();
23711    },
23712
23713    setup: function(rewardItem, callback) {
23714      var id = rewardItem.data('reward-id');
23715      var newId = $.now();
23716      var idPlaceholders = $('.js-reward-item-id-placeholder', rewardItem);
23717      var idPlaceholderItem = [];
23718      var replacedData = '';
23719      var replacedId = '';
23720      var replacedFor = '';
23721      var replacedName = '';
23722
23723      // Save the new reward ID
23724      rewardItem.attr('data-reward-id', newId);
23725
23726      // Change Reward ID in all places
23727      idPlaceholders.each(function() {
23728        idPlaceholderItem = $(this);
23729
23730        // Find and replace the ID in form field names, fors and data attributes
23731        if (idPlaceholderItem.is(':input')) {
23732          // Replace old ID to the new one
23733          if (idPlaceholderItem.is('[id]')) {
23734            replacedId = idPlaceholderItem.attr('id').replace(id, newId);
23735
23736            idPlaceholderItem.attr('id', replacedId);
23737          }
23738
23739          // Replace old name to the new one
23740          if (idPlaceholderItem.is('[name]')) {
23741            replacedName = idPlaceholderItem.attr('name').replace(id, newId);
23742
23743            idPlaceholderItem.attr('name', replacedName);
23744          }
23745        } else if (idPlaceholderItem.is('label')) {
23746          // Replace old for to the new one
23747          if (idPlaceholderItem.is('[for]')) {
23748            replacedFor = idPlaceholderItem.attr('for').replace(id, newId);
23749
23750            idPlaceholderItem.attr('for', replacedFor);
23751          }
23752        }
23753
23754        $.each(idPlaceholderItem.data(), function(key, value) {
23755          // Find data attributes containing the old ID
23756          if (typeof value === 'string' && ~value.indexOf(id)) {
23757            // Convert the key from camelCase to dashed
23758            key = key.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase();
23759
23760            // Replace old ID to the new one
23761            replacedData = idPlaceholderItem.attr('data-' + key).replace(id, newId);
23762
23763            // Save the new data attribute value
23764            idPlaceholderItem.attr('data-' + key, replacedData);
23765          }
23766        });
23767      });
23768
23769      // Resolve Set Up callback
23770      callback.resolve(true);
23771
23772      return rewardItem;
23773    }
23774  };
23775
23776  StartRewards.init();
23777
23778  return StartRewards;
23779});
23780/**
23781 * Subscribe
23782 * @namespace Verkami
23783 * @class Subscribe
23784 */
23785
23786var name = "Verkami/Subscribe";
23787var deps = ["Verkami/Form", "Verkami/Settings", "Verkami/Utils"];
23788
23789modulejs.define(name, deps, function (Form, Settings, Utils) {
23790  var Subscribe = {
23791    node: [],
23792    form: [],
23793    input: [],
23794    button: [],
23795    feedback: [],
23796    trigger: [],
23797    close: [],
23798    type: "",
23799    emailErrorMessage: "",
23800    buttonDisabledClass: "button--disabled",
23801    buttonErrorClass: "button--alert",
23802    buttonLoadingClass: "button--loading",
23803    buttonOkClass: "button--success",
23804    buttonTransitionSpeed: Settings.speed * 16,
23805    feedbackErrorClass: "subscribe__feedback--error",
23806    feedbackOkClass: "subscribe__feedback--success",
23807    triggerErrorClass: "subscribe__trigger--error",
23808    triggerOkClass: "subscribe__trigger--success",
23809    triggerLoadingClass: "subscribe__trigger--loading",
23810    triggerLoadingText: "",
23811
23812    init: function () {
23813      var that = this;
23814      that.node = $(".js-subscribe");
23815
23816      if (that.node.length) {
23817        that.form = $(".js-subscribe-form", that.node);
23818        that.feedback = $(".js-subscribe-feedback", that.node);
23819        that.emailErrorMessage = that.form.attr("data-subscribe-error");
23820        that.type = that.node.attr("data-subscribe-type");
23821        that.close = $(".js-subscribe-close", that.node);
23822
23823        that.close.on("click", function() {
23824          Cookies.set(that.node.attr("data-cookie-name"), "true");
23825          that.node.fadeOut();
23826        });
23827        // Set up different events for each subscribe form type
23828        if (that.type === "direct") {
23829          that.trigger = $(".js-subscribe-trigger", that.node);
23830          that.triggerLoadingText = that.trigger.attr("data-subscribe-sending-text");
23831
23832          // One-click subscribing when user is logged in
23833          that.trigger.on("click", function () {
23834            // Save default text
23835            that.trigger.attr("data-subscribe-default-text", $("span", that.trigger).html());
23836
23837            // Turn on the loading style
23838            that.trigger.addClass(that.triggerLoadingClass);
23839
23840            // Show loading text
23841            $("span", that.trigger).html(that.triggerLoadingText);
23842
23843            $.post(
23844              that.form.attr("action"),
23845              that.form.serialize(),
23846              function (response) {
23847                that.toggleFeedback(response.signed_up, response.message, that.type);
23848              },
23849              "json",
23850            );
23851          });
23852        } else if (that.type === "redirect") {
23853          that.trigger = $(".js-subscribe-trigger", that.node);
23854          that.trigger.on("click", function () {
23855            Cookies.set(that.node.attr("data-cookie-name"), "true");
23856            window.location.href = that.node.attr("data-subscribe-url");
23857          });
23858        } else if (that.type === "form") {
23859          that.input = $(".js-subscribe-input", that.node);
23860          that.button = $(".js-subscribe-button", that.node);
23861
23862          if (Utils.isMobile || Utils.isTablet) {
23863            that.trigger = $(".js-subscribe-trigger", that.node);
23864
23865            that.trigger.on("click", function () {
23866              that.showForm();
23867            });
23868          }
23869
23870          that.input.on("keyup input blur", function () {
23871            that.validate();
23872          });
23873
23874          that.form.submit(function () {
23875            that.button.addClass(that.buttonLoadingClass);
23876
23877            if (that.validate()) {
23878              $.post(
23879                $(this).attr("action"),
23880                $(this).serialize(),
23881                function (response) {
23882                  that.toggleFeedback(response.signed_up, response.message, that.type);
23883                },
23884                "json",
23885              );
23886            } else {
23887              that.toggleFeedback(false, that.emailErrorMessage, that.type);
23888            }
23889            return false;
23890          });
23891        }
23892      }
23893    },
23894
23895    showForm: function () {
23896      var that = this;
23897
23898      // @todo: Is it possible to jump the speed attr and set callback as first arg?
23899      that.trigger.slideUp(Settings.speed, function () {
23900        that.form.slideDown();
23901        that.input.focus();
23902      });
23903    },
23904
23905    toggleFeedback: function (signedUp, message, type) {
23906      var that = this;
23907      var buttonClass = signedUp ? that.buttonOkClass : that.buttonErrorClass;
23908      var feedbackClass = signedUp ? that.feedbackOkClass : that.feedbackErrorClass;
23909      var triggerClass = signedUp ? that.triggerOkClass : that.triggerErrorClass;
23910
23911      if (type === "direct") {
23912        // Turn on the loading style
23913        that.trigger.removeClass(that.triggerLoadingClass);
23914
23915        // Change trigger style depending on the response
23916        that.trigger.addClass(triggerClass);
23917
23918        // Show feedback message
23919        that.feedback.html(message).fadeIn();
23920
23921        if (!signedUp) {
23922          setTimeout(function () {
23923            // Hide feedback message
23924            that.feedback.fadeOut();
23925
23926            // Hide loading text
23927            $("span", that.trigger).html(that.trigger.attr("data-subscribe-default-text"));
23928
23929            // Remove the error class
23930            that.trigger.removeClass(triggerClass);
23931          }, that.buttonTransitionSpeed);
23932        }
23933      } else if (type === "form") {
23934        // Update submit style
23935        that.button.removeClass(that.buttonLoadingClass).addClass(buttonClass);
23936
23937        // Update feedback style and toggle it
23938        that.feedback.html(message).addClass(feedbackClass).slideDown();
23939
23940        // Get the form back to its default state
23941        setTimeout(function () {
23942          that.button.removeClass(buttonClass);
23943
23944          // @todo: Is it possible to jump the speed attr and set callback as first arg?
23945          that.feedback.slideUp(Settings.speed, function () {
23946            that.feedback.removeClass(feedbackClass);
23947          });
23948
23949          that.input.val("");
23950        }, that.buttonTransitionSpeed);
23951      }
23952    },
23953
23954    validate: function () {
23955      var that = this;
23956
23957      var isValid = Form.validate.email(that.input.val());
23958
23959      if (isValid) {
23960        that.button.removeClass(that.buttonDisabledClass);
23961        return true;
23962      } else {
23963        that.button.addClass(that.buttonDisabledClass);
23964        return false;
23965      }
23966    },
23967  };
23968
23969  Subscribe.init();
23970
23971  return Subscribe;
23972});
23973/**
23974* SurveyBillingShipping
23975* @namespace Verkami
23976* @class SurveyBillingShipping
23977*/
23978
23979var name = "Verkami/SurveyBillingShipping";
23980
23981modulejs.define(name, function() {
23982  var SurveyBillingShipping = {
23983    node: [],
23984    box: [],
23985    triggers: [],
23986
23987    init: function() {
23988      var that = this;
23989      that.node = $(".js-use-billing-for-shipping");
23990
23991      if (that.node.length) {
23992        that.box = $(".js-use-billing-for-shipping-box", that.node);
23993        that.triggers = $("input[type=radio]", that.node);
23994        var isTrigger = $(".js-use-billing-for-shipping-trigger").is(":checked");
23995
23996        that.toggleBox(isTrigger);
23997
23998        that.triggers.on("change", function() {
23999          isTrigger = $(this).hasClass("js-use-billing-for-shipping-trigger");
24000
24001          that.toggleBox(isTrigger);
24002        });
24003      }
24004    },
24005
24006    toggleBox: function(isTrigger) {
24007      var that = this;
24008
24009      if (isTrigger) {
24010        that.box.slideDown();
24011      } else {
24012        that.box.slideUp();
24013      }
24014    }
24015  };
24016
24017  SurveyBillingShipping.init();
24018
24019  return SurveyBillingShipping;
24020});
24021/**
24022* TwitterWidget
24023* @namespace Verkami
24024* @class TwitterWidget
24025*/
24026
24027var name = 'Verkami/TwitterWidget';
24028
24029modulejs.define(name, function() {
24030  var TwitterWidget = {
24031    source: 'https://platform.twitter.com/widgets.js',
24032
24033    init: function() {
24034      var that = this;
24035
24036      window.twttr = (function (d, s, id) {
24037        var t, js, fjs = d.getElementsByTagName(s)[0];
24038        if (d.getElementById(id)) return;
24039        js = d.createElement(s); js.id = id; js.src= that.source;
24040        fjs.parentNode.insertBefore(js, fjs);
24041        return window.twttr || (t = { _e: [], ready: function (f) { t._e.push(f) } });
24042      }(document, 'script', 'twitter-wjs'));
24043    }
24044  };
24045
24046  TwitterWidget.init();
24047
24048  return TwitterWidget;
24049});
24050/**
24051 * User
24052 * @namespace Verkami
24053 * @class User
24054 */
24055
24056var name = "Verkami/User";
24057var deps = ["Verkami/Avatar", "Verkami/Form", "Verkami/Modal", "Verkami/Panels", "Verkami/Settings", "Verkami/Utils"];
24058
24059modulejs.define(name, deps, function (Avatar, Form, Modal, Panels, Settings, Utils) {
24060  var User = {
24061    logoutTrigger: [],
24062    passwordForm: [],
24063    signupForm: [],
24064    buttonDisabledClass: "button--disabled",
24065    loggedInEvent: "loggedIn",
24066    loginErrorEvent: "loginError",
24067    signedUpEvent: "signedUp",
24068    signedUpErrorEvent: "signedUpError",
24069
24070    init: function () {
24071      var that = this;
24072
24073      that._callbacks();
24074
24075      that.setup();
24076    },
24077
24078    _callbacks: function () {
24079      var that = this;
24080
24081      $(document).on("trigger.vk.user.setup", function (e) {
24082        that.setup();
24083      });
24084
24085      $(document).on("trigger.vk.user.login.init", ".js-login", function () {
24086        that.login.init($(this));
24087      });
24088    },
24089
24090    facebook: function (nodes) {
24091      var node = [];
24092      var path = [];
24093      var pathNew = [];
24094      var redirect = [];
24095
24096      nodes.each(function () {
24097        node = $(this);
24098        redirect = node.attr("data-auth-redirect");
24099
24100        if (redirect) {
24101          path = node.attr("href");
24102          pathNew = path + "&origin=" + redirect;
24103
24104          node.attr("href", pathNew);
24105        }
24106      });
24107    },
24108
24109    google: function (nodes) {
24110      var node = [];
24111      var path = [];
24112      var pathNew = [];
24113      var redirect = [];
24114
24115      nodes.each(function () {
24116        node = $(this);
24117        redirect = node.attr("data-auth-redirect");
24118
24119        if (redirect) {
24120          //path = node.attr("href");
24121          input = node.parent().find("input[name='proceed_to']");
24122          input.val(input.val() + "&origin=" + redirect);
24123        }
24124      });
24125    },
24126
24127    refreshUserInfo: function (panelContents, userInfo) {
24128      $(".js-username-placeholder").html(userInfo.name);
24129      if (Settings.beta.tokenizationAvailable()) {
24130        $(".js-tokenized-cards", panelContents)
24131          // Make the placeholder a regular form item when it holds cards
24132          .addClass("form-item")
24133          .html(userInfo.cards);
24134      }
24135      Avatar.refresh(userInfo.avatar);
24136    },
24137
24138    login: {
24139      inputEvents: "keyup.loginInput paste.loginInput input.loginInput",
24140      loginErrorTimeout: null,
24141
24142      init: function (loginForm) {
24143        var that = this;
24144        var loginButton = $(".js-login-button", loginForm.closest(".
24144js-modal"));
24145
24146        loginButton.off("click.loginSubmit").on("click.loginSubmit", function (e) {
24147          e.preventDefault();
24148
24149          that.submit(loginForm, false);
24150        });
24151      },
24152
24153      error: function (loading, loginInputs) {
24154        // Hide loading spinner
24155        Modal.loading.hide(loading);
24156
24157        // Enable inputs back
24158        loginInputs.prop("disabled", false);
24159
24160        // Show errors
24161        Form.error("show", loginInputs);
24162      },
24163
24164      submit: function (loginForm, feedback) {
24165        var that = this;
24166        var loginEmail = $(".js-login-email", loginForm);
24167        var loginPassword = $(".js-login-password", loginForm);
24168        var loginInputs = $.fn.add(loginEmail).add(loginPassword);
24169        var formData = loginForm.serializeArray();
24170        var source = loginForm.attr("action");
24171        var loading = loginForm.closest(".js-modal").find(".js-modal-loading");
24172
24173        // Boolean to know if we are inside the pledge process
24174        var isPledge = loginForm.closest(".js-pledge").length;
24175
24176        // Remove error class on keyup
24177        Form.error("hide", loginInputs);
24178
24179        clearTimeout(that.loginErrorTimeout);
24180
24181        // Disable inputs
24182        loginInputs.prop("disabled", true);
24183
24184        // Show loading spinner
24185        Modal.loading.show(loading);
24186
24187        $.ajax({
24188          type: "POST",
24189          url: source,
24190          data: formData,
24191          dataType: "json",
24192          error: function () {
24193            // Show errors
24194            that.error(loading, loginInputs);
24195
24196            // Remove error style if user is typing
24197            loginInputs.off("keyup.removeError").one("keyup.removeError", function () {
24198              $(this).closest(".form-item--error").removeClass("form-item--error");
24199            });
24200
24201            if (isPledge) {
24202              // Trigger loginError callback to use in the pledge modal
24203              loginForm.trigger(User.loginErrorEvent);
24204            }
24205          },
24206          success: function (response) {
24207            var isLogged = response.logged;
24208            var redirectPath = loginForm.attr("data-auth-redirect");
24209
24210            if (feedback) {
24211              Modal.loading.hide(loading);
24212            }
24213
24214            if (isLogged) {
24215              var panelContents = loginForm.closest(".js-panels");
24216              var loggedInPanelPresent = Panels.getContent(panelContents, Panels.loggedIn).length;
24217
24218              if (loggedInPanelPresent) {
24219                $(".js-pledge .js-panels").data("logged-in", true);
24220                User.refreshUserInfo(panelContents, response.user);
24221                loginInputs.prop("disabled", false);
24222
24223                if (isPledge) {
24224                  // Trigger loggedIn callback to use in the pledge modal
24225                  if (redirectPath) {
24226                    Utils.redirect(redirectPath);
24227                  } else {
24228                    loginForm.trigger(User.loggedInEvent);
24229                  }
24230                } else {
24231                  Modal.loading.hide(loading);
24232                  loginForm
24233                    .closest(".js-modal")
24234                    .find(".js-modal-close")
24235                    .off("click.vk.modal.close")
24236                    .on("click.vk.modal.close", function () {
24237                      // Go to the custom redirect URL
24238                      Utils.redirect(redirectPath || response.redirect);
24239                    });
24240                }
24241              } else {
24242                Utils.redirect(redirectPath || response.redirect);
24243              }
24244            } else {
24245              // Show errors
24246              that.error(loading, loginInputs);
24247
24248              // Remove error style if user is typing
24249              loginInputs.off("keyup.removeError").one("keyup.removeError", function () {
24250                $(this).closest(".form-item--error").removeClass("form-item--error");
24251              });
24252
24253              if (isPledge) {
24254                // Trigger loginError callback to use in the pledge modal
24255                loginForm.trigger(User.loginErrorEvent);
24256              }
24257            }
24258          },
24259        });
24260      },
24261
24262      validate: function (loginEmail, loginPassword) {
24263        var isValidEmail = Form.validate.email(loginEmail.val());
24264        var isValidPassword = loginPassword.val().length > 3;
24265
24266        return isValidEmail && isValidPassword;
24267      },
24268    },
24269
24270    logout: function (trigger) {
24271      var source = trigger.attr("href");
24272      var isLoggedOut = null;
24273      var panelContents = [];
24274      var loading = trigger.closest(".js-modal").find(".js-modal-loading");
24275
24276      // Show loading spinner
24277      Modal.loading.show(loading);
24278
24279      $.ajax({
24280        type: "GET",
24281        url: source,
24282        dataType: "json",
24283        success: function (response) {
24284          isLoggedOut = !response.logged;
24285
24286          // Hide loading spinner
24287          Modal.loading.hide(loading);
24288
24289          if (isLoggedOut) {
24290            panelContents = trigger.closest(".js-panels");
24291
24292            // Change pledge logged in flag
24293            $(".js-pledge .js-panels").data("logged-in", false);
24294
24295            // Clean login input
24296            Form.reset($(".js-login"));
24297
24298            // Show login panel
24299            Panels.toggleContents(panelContents, 2);
24300
24301            // Refresh page if user closes the modal (this is a temporarily fix to show user's menu, top bars, etc.)
24302            trigger
24303              .closest(".js-modal")
24304              .find(".js-modal-close")
24305              .off("click.vk.modal.close")
24306              .on("click.vk.modal.close", function () {
24307                location.reload(true);
24308              });
24309          }
24310        },
24311      });
24312    },
24313
24314    passwordRecovery: {
24315      error: function (emailField, type) {
24316        var errorClass = "form-item__error";
24317        var errorDatabaseMessage = emailField.closest(".js-password-recovery").find(".js-password-recovery-database");
24318        var errorGenericMessage = emailField.closest(".js-password-recovery").find(".js-password-recovery-generic");
24319        var errorTypoMessage = emailField.closest(".js-password-recovery").find(".js-password-recovery-typo");
24320
24321        // Add error style to the field
24322        emailField.addClass(errorClass);
24323
24324        // Show the error message
24325        switch (type) {
24326          case "generic":
24327            errorGenericMessage.slideDown("fast");
24328
24329            setTimeout(function () {
24330              errorGenericMessage.slideUp("fast");
24331            }, Settings.speed * 10);
24332
24333            break;
24334          case "database":
24335            errorDatabaseMessage.slideDown("fast");
24336
24337            setTimeout(function () {
24338              errorDatabaseMessage.slideUp("fast");
24339            }, Settings.speed * 10);
24340
24341            break;
24342
24343          case "typo":
24344            errorTypoMessage.slideDown("fast");
24345
24346            setTimeout(function () {
24347              errorTypoMessage.slideUp("fast");
24348            }, Settings.speed * 10);
24349
24350            break;
24351        }
24352
24353        // Remove errors once user starts to type again
24354        emailField.off("keyup.passwordRecover").one("keyup.passwordRecover", function () {
24355          // Clean email field error
24356          emailField.removeClass(errorClass);
24357        });
24358      },
24359
24360      recover: function (form) {
24361        var that = this;
24362        var emailField = $(".js-password-recovery-email", form);
24363        var email = emailField.val().trim();
24364        var isValidEmail = Form.validate.email(email);
24365        var panelModule = [];
24366        var panelId = 0;
24367        var loading = [];
24368        var formData = [];
24369
24370        if (isValidEmail) {
24371          formData = form.serializeArray();
24372          loading = form.closest(".js-modal").find(".js-modal-loading");
24373
24374          // Show loading spinner
24375          Modal.loading.show(loading);
24376
24377          $.ajax({
24378            type: "POST",
24379            url: form.attr("action"),
24380            data: formData,
24381            dataType: "json",
24382            error: function () {
24383              // Hide loading spinner
24384              Modal.loading.hide(loading);
24385
24386              // Show error
24387              that.error(emailField, "generic");
24388            },
24389            success: function (data) {
24390              // Hide loading spinner
24391              Modal.loading.hide(loading);
24392
24393              // Check if provided email is the same as the response one
24394              if (data.user) {
24395                panelId = parseInt($(".button:submit", form).attr("data-panels-trigger"));
24396                panelModule = form.closest(".js-panels");
24397
24398                // Show confirmation panel if requested in the submit button
24399                if (panelId) {
24400                  Panels.toggleContents(panelModule, panelId);
24401                }
24402              } else {
24403                // Show error
24404                that.error(emailField, "database");
24405              }
24406            },
24407          });
24408        } else {
24409          // Show error
24410          that.error(emailField, "typo");
24411        }
24412      },
24413    },
24414
24415    setup: function () {
24416      var that = this;
24417      that.logoutTrigger = $(".js-logout");
24418      that.passwordForm = $(".js-password-recovery");
24419      that.signupForm = $(".js-signup");
24420
24421      if (that.logoutTrigger.length) {
24422        that.logoutTrigger.off("click.logoutTrigger").on("click.logoutTrigger", function (e) {
24423          e.preventDefault();
24424
24425          that.logout($(this));
24426        });
24427      }
24428
24429      if (that.passwordForm.length) {
24430        that.passwordForm.off("submit.passwordRecovery").on("submit.passwordRecovery", function (e) {
24431          e.preventDefault();
24432
24433          that.passwordRecovery.recover($(this));
24434        });
24435      }
24436
24437      if (that.signupForm.length) {
24438        that.signupForm.each(function () {
24439          that.signup.init($(this));
24440        });
24441      }
24442
24443      // Setup Facebook button
24444      that.facebook($(".js-auth-facebook"));
24445      that.google($(".js-auth-google"));
24446    },
24447
24448    signup: {
24449      init: function (node) {
24450        var that = this;
24451
24452        that.events(node);
24453      },
24454
24455      events: function (node) {
24456        var that = this;
24457        var submit = node.closest(".js-modal").find(".js-signup-submit");
24458        var captchaEnabledInSubmit = submit.hasClass("js-recaptcha");
24459        var eventToListen = "click.signUpSubmit";
24460        if (captchaEnabledInSubmit) {
24461          console.log("[CAPTCHA] Signup with captcha requirements detected.");
24462          console.log("[CAPTCHA] Listening to captcha events.");
24463          eventToListen = "captcha.vk.validated";
24464        }
24465
24466        submit.off(eventToListen).on(eventToListen, function (e) {
24467          console.log("Processing signup submit triggered by " + eventToListen);
24468          e.preventDefault();
24469
24470          that.submit($(this).closest(".js-modal").find(".js-signup"), true);
24471        });
24472      },
24473
24474      submit: function (signupForm, feedback) {
24475        var signupAgreement = signupForm.closest(".js-modal").find(".js-signup-agreement");
24476        var signupEmail = $(".js-signup-email", signupForm);
24477        var signupEmailConfirmation = $(".js-signup-email-confirmation", signupForm);
24478        var signupName = $(".js-signup-name", signupForm);
24479        var signupNewsletter = $(".js-signup-newsletter", signupForm);
24480        var signupPassword = $(".js-signup-password", signupForm);
24481        var signupInputs = $.fn.add(signupEmail).add(signupEmailConfirmation).add(signupName).add(signupPassword);
24482        var timeout = null;
24483        var loading = signupForm.closest(".js-modal").find(".js-modal-loading");
24484
24485        // Validate agreement
24486        var isValidAgreement = signupAgreement.is(":checked");
24487
24488        // Boolean to know if we are inside the pledge process
24489        var isPledge = signupForm.closest(".js-pledge").length;
24490
24491        // Remove input error on keyup
24492        signupInputs.off("keyup.signupInputs");
24493
24494        signupInputs.on("keyup.signupInputs", function () {
24495          Form.error("hide", $(this));
24496        });
24497
24498        // Remove checkbox error on change
24499        signupAgreement.off("change.signupAgreement");
24500
24501        signupAgreement.on("change.signupAgreement", function () {
24502          Form.error("hide", $(this));
24503        });
24504
24505        // Submit form is all required fields are ok, otherwise show errors
24506        if (isValidAgreement) {
24507          var formData = signupForm.serializeArray();
24508          var source = signupForm.attr("action");
24509
24510          // Show loading spinner
24511          Modal.loading.show(loading);
24512
24513          clearTimeout(timeout);
24514
24515          timeout = setTimeout(function () {
24516            $.ajax({
24517              type: "POST",
24518              url: source,
24519              data: formData,
24520              dataType: "json",
24521              error: function () {
24522                // Hide loading spinner
24523                Modal.loading.hide(loading);
24524
24525                Form.error("show", $.fn.add.call(signupInputs, isValidAgreement));
24526
24527                if (isPledge) {
24528                  signupForm.trigger(User.signedUpErrorEvent);
24529                }
24530              },
24531              success: function (response) {
24532                var isSignedUp = response.signup;
24533                var modalId = null;
24534                var redirectPath = signupForm.attr("data-auth-redirect");
24535
24536                if (feedback) {
24537                  // Hide loading spinner
24538                  Modal.loading.hide(loading);
24539                }
24540
24541                if (isSignedUp) {
24542                  redirectPath = redirectPath ? redirectPath : response.redirect;
24543
24544                  if (isPledge) {
24545                    // Trigger signedUp callback to use in the pledge modal
24546                    signupForm.trigger(User.signedUpEvent);
24547                  } else {
24548                    modalId = signupForm.closest(".js-modal").data("modal-id");
24549
24550                    // Go to the custom redirect URL
24551                    Utils.redirect(redirectPath);
24552                  }
24553                } else {
24554                  // Show error messages
24555                  var errorNode = [];
24556
24557                  // Remove old errors
24558                  signupInputs.closest("[class*='form-item']").find(".form-item__error-message").remove();
24559
24560                  $.each(response.errors, function (index, error) {
24561                    for (var name in error) {
24562                      if (error.hasOwnProperty(name)) {
24563                        // Error message placeholder
24564                        errorNode = $("<div>", {
24565                          class: "form-item__error-message",
24566                        }).html(error[name]);
24567
24568                        // Output each error in its place
24569                        switch (name) {
24570                          case "email":
24571                            Form.error("show", signupEmail);
24572                            errorNode.appendTo(signupEmail.closest("[class*='form-item']"));
24573                            break;
24574
24575                          case "email_confirmation":
24576                            Form.error("show", signupEmailConfirmation);
24577                            errorNode.appendTo(signupEmailConfirmation.closest("[class*='form-item']"));
24578                            break;
24579
24580                          case "name":
24581                            Form.error("show", signupName);
24582                            errorNode.appendTo(signupName.closest("[class*='form-item']"));
24583                            break;
24584
24585                          case "password":
24586                            Form.error("show", signupPassword);
24587                            errorNode.appendTo(signupPassword.closest("[class*='form-item']"));
24588                            break;
24589                        }
24590                      }
24591                    }
24592                  });
24593
24594                  // Remove error message if user is typing
24595                  signupInputs.one("keyup", function () {
24596                    $(this)
24597                      .closest("[class*='form-item']")
24598                      .find(".form-item__error-message")
24599                      .slideUp("fast", function () {
24600                        $(this).remove();
24601                      });
24602                  });
24603
24604                  // Hide loading spinner
24605                  Modal.loading.hide(loading);
24606
24607                  if (isPledge) {
24608                    signupForm.trigger(User.signedUpErrorEvent);
24609                  }
24610                }
24611              },
24612            });
24613          }, Settings.delay);
24614        } else {
24615          Form.error("show", signupAgreement);
24616
24617          if (isPledge) {
24618            signupForm.trigger(User.signedUpErrorEvent);
24619          }
24620        }
24621      },
24622    },
24623  };
24624
24625  User.init();
24626
24627  return User;
24628});
24629/**
24630* Widget
24631* @namespace Verkami
24632* @class Widget
24633*/
24634
24635var name = 'Verkami/Widget';
24636var deps = [
24637  'Verkami/Modal',
24638  'Verkami/Settings'
24639];
24640
24641modulejs.define(name, deps, function(Modal, Settings) {
24642  var Widget = {
24643    nodes: [],
24644    feedbackDelay: 4000,
24645    horizontalClass: 'modal-embed--horizontal',
24646    verticalClass: 'modal-embed--vertical',
24647
24648    init: function() {
24649      var that = this;
24650      that.nodes = $('.js-widget');
24651
24652      if (that.nodes.length) {
24653        // Initialize callbacks
24654        that._callbacks();
24655
24656        that.nodes.each(function() {
24657          that.events($(this));
24658        });
24659      }
24660    },
24661
24662    _callbacks: function() {
24663      var that = this;
24664
24665      $(document).on('trigger.vk.widget.getIframe', function(e) {
24666        that.getIframe(e.modalData);
24667      });
24668    },
24669
24670    events: function(node) {
24671      var that = this;
24672      var toggles = $('.js-widget-toggle', node);
24673      var copy = $('.js-widget-copy', node);
24674      var feedback = $('.js-widget-feedback', node);
24675
24676      // Toggle widget orientation
24677      toggles.on('click', function() {
24678        var orientation = $(this).data('widget-orientation');
24679
24680        that.toggle(orientation, node);
24681      });
24682
24683      // Copy widget code to clipboard
24684      new Clipboard(copy[0], {
24685        text: function(trigger) {
24686          var markUp = '';
24687          var modalId = node.closest('.js-modal').data('modal-id');
24688
24689          if (node.hasClass(that.horizontalClass)) {
24690            markUp = $('#verkamiLandscape', node)[0].outerHTML;
24691          } else if (node.hasClass(that.verticalClass)) {
24692            markUp = $('#verkamiPortrait', node)[0].outerHTML;
24693          }
24694
24695          // @todo: Check if it's possible to avoid the speed attribute
24696          feedback.fadeIn().delay(that.feedbackDelay).fadeOut(Settings.speed, function() {
24697            Modal.hide(modalId, false);
24698          });
24699
24700          return markUp;
24701        }
24702      });
24703    },
24704
24705    getIframe: function(modalData) {
24706      var that = this;
24707      var iframe = [];
24708      var iframeSrc = '';
24709      var modal = Modal.get(modalData.modalTrigger);
24710
24711      $('.js-widget-iframe', modal).each(function() {
24712        iframe = $(this);
24713        iframeSrc = iframe.attr('data-widget-src');
24714
24715        if (iframe.attr('src') !== iframeSrc) {
24716          iframe.attr('src', iframeSrc);
24717
24718          // Clean up iframe data
24719          iframe.removeAttr('data-widget-src');
24720        }
24721      });
24722    },
24723
24724    toggle: function(orientation, node) {
24725      var that = this;
24726      var modalId = node.closest('.js-modal').data('modal-id');
24727
24728      switch (orientation) {
24729        case 'horizontal':
24730          node.removeClass(that.verticalClass)
24731              .addClass(that.horizontalClass)
24732              .closest('.js-modal')
24733              .addClass('modal--xl');
24734          break;
24735        case 'vertical':
24736          node.removeClass(that.horizontalClass)
24737              .addClass(that.verticalClass)
24738              .closest('.js-modal')
24739              .removeClass('modal--xl');
24740          break;
24741      }
24742
24743      setTimeout(function() {
24744        Modal.setup(modalId);
24745      }, Settings.speed);
24746    }
24747  };
24748
24749  Widget.init();
24750
24751  return Widget;
24752});
24753/**
24754 * YearInReview
24755 * @namespace Verkami
24756 * @class YearInReview
24757 */
24758
24759var name = "Verkami/YearInReview";
24760var deps = ["Verkami/CookiesAgreement"];
24761
24762modulejs.define(name, deps, function(CookiesAgreement) {
24763  var YearInReview = {
24764    node: [],
24765    cookieName: "",
24766    cookie: "",
24767    close: [],
24768    hiddenClass: "year-in-review--hidden",
24769
24770    init: function() {
24771      var that = this;
24772      that.node = $(".js-year-in-review");
24773
24774      if (that.node.length) {
24775        that.cookieName = that.node.attr("data-year-in-review-cookie");
24776        that.cookie = Cookies.get(that.cookieName);
24777
24778        if (that.cookie) {
24779          that.node.addClass(that.hiddenClass);
24780        } else {
24781          that.close = $(".js-year-in-review-close", that.node);
24782
24783          that.close.on("click", function() {
24784            that.node.addClass(that.hiddenClass);
24785
24786            if (CookiesAgreement.cookie) {
24787              // @todo: Make Cookies plugin a dependency
24788              Cookies.set(that.cookieName, "true", { expires: 365 });
24789            }
24790          });
24791        }
24792      }
24793    }
24794  };
24795
24796  YearInReview.init();
24797
24798  return YearInReview;
24799});
24800
24801
24802
24803/**
24804 * ModuleJS (JS dependency manager)
24805 */
24806
24807
24808/**
24809 * Load third party plugins
24810 * Note: jQuery is a global dependency and it's loaded separately
24811 */
24812
24813
24814
24815
24816
24817
24818
24819
24820
24821
24822
24823
24824
24825
24826
24827
24828
24829
24830
24831
24832
24833/**
24834 * Load Verkami utils, components and modules
24835 */
24836
24837
24838
24839
24840/**
24841 * Set up Verkami dependencies sorted by name
24842 *
24843 * Note: Dependencies are managed in each module
24844 */
24845function VerkamiApp() {
24846  // Load utils
24847  modulejs.require("Verkami/Async");
24848  modulejs.require("Verkami/DataTransfer");
24849  modulejs.require("Verkami/DropCap");
24850  modulejs.require("Verkami/Scroll");
24851  modulejs.require("Verkami/Settings");
24852  modulejs.require("Verkami/Utils");
24853
24854  // Load components
24855  modulejs.require("Verkami/Autocomplete");
24856  modulejs.require("Verkami/Bar");
24857  modulejs.require("Verkami/ColorPicker");
24858  modulejs.require("Verkami/Dropdown");
24859  modulejs.require("Verkami/Fak");
24860  modulejs.require("Verkami/Faq");
24861  modulejs.require("Verkami/Form");
24862  modulejs.require("Verkami/Modal");
24863  modulejs.require("Verkami/PopUp");
24864  modulejs.require("Verkami/ReadMore");
24865  modulejs.require("Verkami/Share");
24866  modulejs.require("Verkami/Sticky");
24867  modulejs.require("Verkami/Switcher");
24868  modulejs.require("Verkami/Tabs");
24869  modulejs.require("Verkami/Toggle");
24870  modulejs.require("Verkami/Url");
24871  modulejs.require("Verkami/Video");
24872
24873  // Load modules
24874  modulejs.require("Verkami/Auth");
24875  modulejs.require("Verkami/Avatar");
24876  modulejs.require("Verkami/Backers");
24877  modulejs.require("Verkami/BlogBar");
24878  modulejs.require("Verkami/BlogNavigation");
24879  modulejs.require("Verkami/Cards");
24880  modulejs.require("Verkami/Carousel");
24881  modulejs.require("Verkami/Checkout");
24882  modulejs.require("Verkami/Comment");
24883  modulejs.require("Verkami/Comments");
24884  modulejs.require("Verkami/Community");
24885  modulejs.require("Verkami/CookiesAgreement");
24886  modulejs.require("Verkami/Filters");
24887  modulejs.require("Verkami/Flash");
24888  modulejs.require("Verkami/Follow");
24889  modulejs.require("Verkami/Footer");
24890  modulejs.require("Verkami/Hero");
24891  modulejs.require("Verkami/IEWarning");
24892  modulejs.require("Verkami/Navigation");
24893  modulejs.require("Verkami/Paginator");
24894  modulejs.require("Verkami/Panels");
24895  modulejs.require("Verkami/PartnerFollow");
24896  modulejs.require("Verkami/Password");
24897  modulejs.require("Verkami/Player");
24898  modulejs.require("Verkami/Pledge");
24899  modulejs.require("Verkami/PledgeHigh");
24900  modulejs.require("Verkami/PledgePayments");
24901  modulejs.require("Verkami/Project");
24902  modulejs.require("Verkami/ProjectHero");
24903  modulejs.require("Verkami/Question");
24904  modulejs.require("Verkami/Search");
24905  modulejs.require("Verkami/SettingsNotifications");
24906  modulejs.require("Verkami/SettingsSubscriptions");
24907  modulejs.require("Verkami/SocialManage");
24908  modulejs.require("Verkami/Start");
24909  modulejs.require("Verkami/StartRewards");
24910  modulejs.require("Verkami/Subscribe");
24911  modulejs.require("Verkami/User");
24912  modulejs.require("Verkami/Widget");
24913  modulejs.require("Verkami/YearInReview");
24914  modulejs.require("Verkami/Promotion");
24915  modulejs.require("Verkami/SurveyBillingShipping");
24916}
24917
24918function LoadVerkamiCaptcha() {
24919  console.log("[CAPTCHA] Enabling captcha system.");
24920  var captcha = modulejs.require("Verkami/Captcha");
24921  captcha.init();
24922}
24923/**
24924 * Initialize Verkami JS on loading
24925 */
24926$(function () {
24927  // We could expose the modules here like window.Verkami = { module:  "require_here", };
24928  VerkamiApp();
24929});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.