PageSourceSearch

https://www.svnk.nl/typo3temp/assets/compressed/merged-078264cbe7deb5bddc353a8f8d15c989.js?1790924251

js svnk.nl collected 2026-10-06 04:29:06 UTC 272,398 bytes, 9,133 lines download raw bytes

1
2// Source: http://stackoverflow.com/a/460709
3Element.prototype.triggerEvent = function(eventName)
4{
5    if (document.createEvent)
6    {
7        var evt = document.createEvent('HTMLEvents');
8        evt.initEvent(eventName, true, true);
9
10        return this.dispatchEvent(evt);
11    }
12
13    if (this.fireEvent)
14        return this.fireEvent('on' + eventName);
15}
16
17var AngularServiceData = {
18    _data: {},
19    add: function(item) {
20        if (item && 'url' in item) {
21            if (!this._data[item.url]) {
22                this._data[item.url] = [];
23            }
24
25            this._data[item.url].push({
26                parameters: item.parameters,
27                data: item.data
28            });
29        }
30    },
31    addAll: function(items) {
32        if (items) {
33            for (var i = 0; i < items.length; i++) {
34                this.add(items[i]);
35            }
36        }
37    },
38    get: function(url) {
39        if (this._data[url]) {
40            return this._data[url];
41        } else {
42            return [];
43        }
44    }
45};
46
47
48/*  Prototype JavaScript framework, version 1.7.3
49 *  (c) 2005-2010 Sam Stephenson
50 *
51 *  Prototype is freely distributable under the terms of an MIT-style license.
52 *  For details, see the Prototype web site: http://www.prototypejs.org/
53 *
54 *--------------------------------------------------------------------------*/
55
56var Prototype = {
57
58  Version: '1.7.3',
59
60  Browser: (function(){
61    var ua = navigator.userAgent;
62    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
63    return {
64      IE:             !!window.attachEvent && !isOpera,
65      Opera:          isOpera,
66      WebKit:         ua.indexOf('AppleWebKit/') > -1,
67      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
68      MobileSafari:   /Apple.*Mobile/.test(ua)
69    }
70  })(),
71
72  BrowserFeatures: {
73    XPath: !!document.evaluate,
74
75    SelectorsAPI: !!document.querySelector,
76
77    ElementExtensions: (function() {
78      var constructor = window.Element || window.HTMLElement;
79      return !!(constructor && constructor.prototype);
80    })(),
81    SpecificElementExtensions: (function() {
82      if (typeof window.HTMLDivElement !== 'undefined')
83        return true;
84
85      var div = document.createElement('div'),
86          form = document.createElement('form'),
87          isSupported = false;
88
89      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
90        isSupported = true;
91      }
92
93      div = form = null;
94
95      return isSupported;
96    })()
97  },
98
99  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
100  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
101
102  emptyFunction: function() { },
103
104  K: function(x) { return x }
105};
106
107if (Prototype.Browser.MobileSafari)
108  Prototype.BrowserFeatures.SpecificElementExtensions = false;
109/* Based on Alex Arnell's inheritance implementation. */
110
111var Class = (function() {
112
113  var IS_DONTENUM_BUGGY = (function(){
114    for (var p in { toString: 1 }) {
115      if (p === 'toString') return false;
116    }
117    return true;
118  })();
119
120  function subclass() {};
121  function create() {
122    var parent = null, properties = $A(arguments);
123    if (Object.isFunction(properties[0]))
124      parent = properties.shift();
125
126    function klass() {
127      this.initialize.apply(this, arguments);
128    }
129
130    Object.extend(klass, Class.Methods);
131    klass.superclass = parent;
132    klass.subclasses = [];
133
134    if (parent) {
135      subclass.prototype = parent.prototype;
136      klass.prototype = new subclass;
137      parent.subclasses.push(klass);
138    }
139
140    for (var i = 0, length = properties.length; i < length; i++)
141      klass.addMethods(properties[i]);
142
143    if (!klass.prototype.initialize)
144      klass.prototype.initialize = Prototype.emptyFunction;
145
146    klass.prototype.constructor = klass;
147    return klass;
148  }
149
150  function addMethods(source) {
151    var ancestor   = this.superclass && this.superclass.prototype,
152        properties = Object.keys(source);
153
154    if (IS_DONTENUM_BUGGY) {
155      if (source.toString != Object.prototype.toString)
156        properties.push("toString");
157      if (source.valueOf != Object.prototype.valueOf)
158        properties.push("valueOf");
159    }
160
161    for (var i = 0, length = properties.length; i < length; i++) {
162      var property = properties[i], value = source[property];
163      if (ancestor && Object.isFunction(value) &&
164          value.argumentNames()[0] == "$super") {
165        var method = value;
166        value = (function(m) {
167          return function() { return ancestor[m].apply(this, arguments); };
168        })(property).wrap(method);
169
170        value.valueOf = (function(method) {
171          return function() { return method.valueOf.call(method); };
172        })(method);
173
174        value.toString = (function(method) {
175          return function() { return method.toString.call(method); };
176        })(method);
177      }
178      this.prototype[property] = value;
179    }
180
181    return this;
182  }
183
184  return {
185    create: create,
186    Methods: {
187      addMethods: addMethods
188    }
189  };
190})();
191(function() {
192
193  var _toString = Object.prototype.toString,
194      _hasOwnProperty = Object.prototype.hasOwnProperty,
195      NULL_TYPE = 'Null',
196      UNDEFINED_TYPE = 'Undefined',
197      BOOLEAN_TYPE = 'Boolean',
198      NUMBER_TYPE = 'Number',
199      STRING_TYPE = 'String',
200      OBJECT_TYPE = 'Object',
201      FUNCTION_CLASS = '[object Function]',
202      BOOLEAN_CLASS = '[object Boolean]',
203      NUMBER_CLASS = '[object Number]',
204      STRING_CLASS = '[object String]',
205      ARRAY_CLASS = '[object Array]',
206      DATE_CLASS = '[object Date]',
207      NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
208        typeof JSON.stringify === 'function' &&
209        JSON.stringify(0) === '0' &&
210        typeof JSON.stringify(Prototype.K) === 'undefined';
211
212
213
214  var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',
215   'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
216
217  var IS_DONTENUM_BUGGY = (function(){
218    for (var p in { toString: 1 }) {
219      if (p === 'toString') return false;
220    }
221    return true;
222  })();
223
224  function Type(o) {
225    switch(o) {
226      case null: return NULL_TYPE;
227      case (void 0): return UNDEFINED_TYPE;
228    }
229    var type = typeof o;
230    switch(type) {
231      case 'boolean': return BOOLEAN_TYPE;
232      case 'number':  return NUMBER_TYPE;
233      case 'string':  return STRING_TYPE;
234    }
235    return OBJECT_TYPE;
236  }
237
238  function extend(destination, source) {
239    for (var property in source)
240      destination[property] = source[property];
241    return destination;
242  }
243
244  function inspect(object) {
245    try {
246      if (isUndefined(object)) return 'undefined';
247      if (object === null) return 'null';
248      return object.inspect ? object.inspect() : String(object);
249    } catch (e) {
250      if (e instanceof RangeError) return '...';
251      throw e;
252    }
253  }
254
255  function toJSON(value) {
256    return Str('', { '': value }, []);
257  }
258
259  function Str(key, holder, stack) {
260    var value = holder[key];
261    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
262      value = value.toJSON(key);
263    }
264
265    var _class = _toString.call(value);
266
267    switch (_class) {
268      case NUMBER_CLASS:
269      case BOOLEAN_CLASS:
270      case STRING_CLASS:
271        value = value.valueOf();
272    }
273
274    switch (value) {
275      case null: return 'null';
276      case true: return 'true';
277      case false: return 'false';
278    }
279
280    var type = typeof value;
281    switch (type) {
282      case 'string':
283        return value.inspect(true);
284      case 'number':
285        return isFinite(value) ? String(value) : 'null';
286      case 'object':
287
288        for (var i = 0, length = stack.length; i < length; i++) {
289          if (stack[i] === value) {
290            throw new TypeError("Cyclic reference to '" + value + "' in object");
291          }
292        }
293        stack.push(value);
294
295        var partial = [];
296        if (_class === ARRAY_CLASS) {
297          for (var i = 0, length = value.length; i < length; i++) {
298            var str = Str(i, value, stack);
299            partial.push(typeof str === 'undefined' ? 'null' : str);
300          }
301          partial = '[' + partial.join(',') + ']';
302        } else {
303          var keys = Object.keys(value);
304          for (var i = 0, length = keys.length; i < length; i++) {
305            var key = keys[i], str = Str(key, value, stack);
306            if (typeof str !== "undefined") {
307               partial.push(key.inspect(true)+ ':' + str);
308             }
309          }
310          partial = '{' + partial.join(',') + '}';
311        }
312        stack.pop();
313        return partial;
314    }
315  }
316
317  function stringify(object) {
318    return JSON.stringify(object);
319  }
320
321  function toQueryString(object) {
322    return $H(object).toQueryString();
323  }
324
325  function toHTML(object) {
326    return object && object.toHTML ? object.toHTML() : String.interpret(object);
327  }
328
329  function keys(object) {
330    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
331    var results = [];
332    for (var property in object) {
333      if (_hasOwnProperty.call(object, property))
334        results.push(property);
335    }
336
337    if (IS_DONTENUM_BUGGY) {
338      for (var i = 0; property = DONT_ENUMS[i]; i++) {
339        if (_hasOwnProperty.call(object, property))
340          results.push(property);
341      }
342    }
343
344    return results;
345  }
346
347  function values(object) {
348    var results = [];
349    for (var property in object)
350      results.push(object[property]);
351    return results;
352  }
353
354  function clone(object) {
355    return extend({ }, object);
356  }
357
358  function isElement(object) {
359    return !!(object && object.nodeType == 1);
360  }
361
362  function isArray(object) {
363    return _toString.call(object) === ARRAY_CLASS;
364  }
365
366  var hasNativeIsArray = (typeof Array.isArray == 'function')
367    && Array.isArray([]) && !Array.isArray({});
368
369  if (hasNativeIsArray) {
370    isArray = Array.isArray;
371  }
372
373  function isHash(object) {
374    return object instanceof Hash;
375  }
376
377  function isFunction(object) {
378    return _toString.call(object) === FUNCTION_CLASS;
379  }
380
381  function isString(object) {
382    return _toString.call(object) === STRING_CLASS;
383  }
384
385  function isNumber(object) {
386    return _toString.call(object) === NUMBER_CLASS;
387  }
388
389  function isDate(object) {
390    return _toString.call(object) === DATE_CLASS;
391  }
392
393  function isUndefined(object) {
394    return typeof object === "undefined";
395  }
396
397  extend(Object, {
398    extend:        extend,
399    inspect:       inspect,
400    toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
401    toQueryString: toQueryString,
402    toHTML:        toHTML,
403    keys:          Object.keys || keys,
404    values:        values,
405    clone:         clone,
406    isElement:     isElement,
407    isArray:       isArray,
408    isHash:        isHash,
409    isFunction:    isFunction,
410    isString:      isString,
411    isNumber:      isNumber,
412    isDate:        isDate,
413    isUndefined:   isUndefined
414  });
415})();
416Object.extend(Function.prototype, (function() {
417  var slice = Array.prototype.slice;
418
419  function update(array, args) {
420    var arrayLength = array.length, length = args.length;
421    while (length--) array[arrayLength + length] = args[length];
422    return array;
423  }
424
425  function merge(array, args) {
426    array = slice.call(array, 0);
427    return update(array, args);
428  }
429
430  function argumentNames() {
431    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
432      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
433      .replace(/\s+/g, '').split(',');
434    return names.length == 1 && !names[0] ? [] : names;
435  }
436
437
438  function bind(context) {
439    if (arguments.length < 2 && Object.isUndefined(arguments[0]))
440      return this;
441
442    if (!Object.isFunction(this))
443      throw new TypeError("The object is not callable.");
444
445    var nop = function() {};
446    var __method = this, args = slice.call(arguments, 1);
447
448    var bound = function() {
449      var a = merge(args, arguments);
450      var c = this instanceof bound ? this : context;
451      return __method.apply(c, a);
452    };
453
454    nop.prototype   = this.prototype;
455    bound.prototype = new nop();
456
457    return bound;
458  }
459
460  function bindAsEventListener(context) {
461    var __method = this, args = slice.call(arguments, 1);
462    return function(event) {
463      var a = update([event || window.event], args);
464      return __method.apply(context, a);
465    }
466  }
467
468  function curry() {
469    if (!arguments.length) return this;
470    var __method = this, args = slice.call(arguments, 0);
471    return function() {
472      var a = merge(args, arguments);
473      return __method.apply(this, a);
474    }
475  }
476
477  function delay(timeout) {
478    var __method = this, args = slice.call(arguments, 1);
479    timeout = timeout * 1000;
480    return window.setTimeout(function() {
481      return __method.apply(__method, args);
482    }, timeout);
483  }
484
485  function defer() {
486    var args = update([0.01], arguments);
487    return this.delay.apply(this, args);
488  }
489
490  function wrap(wrapper) {
491    var __method = this;
492    return function() {
493      var a = update([__method.bind(this)], arguments);
494      return wrapper.apply(this, a);
495    }
496  }
497
498  function methodize() {
499    if (this._methodized) return this._methodized;
500    var __method = this;
501    return this._methodized = function() {
502      var a = update([this], arguments);
503      return __method.apply(null, a);
504    };
505  }
506
507  var extensions = {
508    argumentNames:       argumentNames,
509    bindAsEventListener: bindAsEventListener,
510    curry:               curry,
511    delay:               delay,
512    defer:               defer,
513    wrap:                wrap,
514    methodize:           methodize
515  };
516
517  if (!Function.prototype.bind)
518    extensions.bind = bind;
519
520  return extensions;
521})());
522
523
524
525(function(proto) {
526
527
528  function toISOString() {
529    return this.getUTCFullYear() + '-' +
530      (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
531      this.getUTCDate().toPaddedString(2) + 'T' +
532      this.getUTCHours().toPaddedString(2) + ':' +
533      this.getUTCMinutes().toPaddedString(2) + ':' +
534      this.getUTCSeconds().toPaddedString(2) + 'Z';
535  }
536
537
538  function toJSON() {
539    return this.toISOString();
540  }
541
542  if (!proto.toISOString) proto.toISOString = toISOString;
543  if (!proto.toJSON) proto.toJSON = toJSON;
544
545})(Date.prototype);
546
547
548RegExp.prototype.match = RegExp.prototype.test;
549
550RegExp.escape = function(str) {
551  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
552};
553var PeriodicalExecuter = Class.create({
554  initialize: function(callback, frequency) {
555    this.callback = callback;
556    this.frequency = frequency;
557    this.currentlyExecuting = false;
558
559    this.registerCallback();
560  },
561
562  registerCallback: function() {
563    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
564  },
565
566  execute: function() {
567    this.callback(this);
568  },
569
570  stop: function() {
571    if (!this.timer) return;
572    clearInterval(this.timer);
573    this.timer = null;
574  },
575
576  onTimerEvent: function() {
577    if (!this.currentlyExecuting) {
578      try {
579        this.currentlyExecuting = true;
580        this.execute();
581        this.currentlyExecuting = false;
582      } catch(e) {
583        this.currentlyExecuting = false;
584        throw e;
585      }
586    }
587  }
588});
589Object.extend(String, {
590  interpret: function(value) {
591    return value == null ? '' : String(value);
592  },
593  specialChar: {
594    '\b': '\\b',
595    '\t': '\\t',
596    '\n': '\\n',
597    '\f': '\\f',
598    '\r': '\\r',
599    '\\': '\\\\'
600  }
601});
602
603Object.extend(String.prototype, (function() {
604  var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
605    typeof JSON.parse === 'function' &&
606    JSON.parse('{"test": true}').test;
607
608  function prepareReplacement(replacement) {
609    if (Object.isFunction(replacement)) return replacement;
610    var template = new Template(replacement);
611    return function(match) { return template.evaluate(match) };
612  }
613
614  function isNonEmptyRegExp(regexp) {
615    return regexp.source && regexp.source !== '(?:)';
616  }
617
618
619  function gsub(pattern, replacement) {
620    var result = '', source = this, match;
621    replacement = prepareReplacement(replacement);
622
623    if (Object.isString(pattern))
624      pattern = RegExp.escape(pattern);
625
626    if (!(pattern.length || isNonEmptyRegExp(pattern))) {
627      replacement = replacement('');
628      return replacement + source.split('').join(replacement) + replacement;
629    }
630
631    while (source.length > 0) {
632      match = source.match(pattern)
633      if (match && match[0].length > 0) {
634        result += source.slice(0, match.index);
635        result += String.interpret(replacement(match));
636        source  = source.slice(match.index + match[0].length);
637      } else {
638        result += source, source = '';
639      }
640    }
641    return result;
642  }
643
644  function sub(pattern, replacement, count) {
645    replacement = prepareReplacement(replacement);
646    count = Object.isUndefined(count) ? 1 : count;
647
648    return this.gsub(pattern, function(match) {
649      if (--count < 0) return match[0];
650      return replacement(match);
651    });
652  }
653
654  function scan(pattern, iterator) {
655    this.gsub(pattern, iterator);
656    return String(this);
657  }
658
659  function truncate(length, truncation) {
660    length = length || 30;
661    truncation = Object.isUndefined(truncation) ? '...' : truncation;
662    return this.length > length ?
663      this.slice(0, length - truncation.length) + truncation : String(this);
664  }
665
666  function strip() {
667    return this.replace(/^\s+/, '').replace(/\s+$/, '');
668  }
669
670  function stripTags() {
671    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, '');
672  }
673
674  function stripScripts() {
675    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
676  }
677
678  function extractScripts() {
679    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
680        matchOne = new RegExp(Prototype.ScriptFragment, 'im');
681    return (this.match(matchAll) || []).map(function(scriptTag) {
682      return (scriptTag.match(matchOne) || ['', ''])[1];
683    });
684  }
685
686  function evalScripts() {
687    return this.extractScripts().map(function(script) { return eval(script); });
688  }
689
690  function escapeHTML() {
691    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
692  }
693
694  function unescapeHTML() {
695    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
696  }
697
698
699  function toQueryParams(separator) {
700    var match = this.strip().match(/([^?#]*)(#.*)?$/);
701    if (!match) return { };
702
703    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
704      if ((pair = pair.split('='))[0]) {
705        var key = decodeURIComponent(pair.shift()),
706            value = pair.length > 1 ? pair.join('=') : pair[0];
707
708        if (value != undefined) {
709          value = value.gsub('+', ' ');
710          value = decodeURIComponent(value);
711        }
712
713        if (key in hash) {
714          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
715          hash[key].push(value);
716        }
717        else hash[key] = value;
718      }
719      return hash;
720    });
721  }
722
723  function toArray() {
724    return this.split('');
725  }
726
727  function succ() {
728    return this.slice(0, this.length - 1) +
729      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
730  }
731
732  function times(count) {
733    return count < 1 ? '' : new Array(count + 1).join(this);
734  }
735
736  function camelize() {
737    return this.replace(/-+(.)?/g, function(match, chr) {
738      return chr ? chr.toUpperCase() : '';
739    });
740  }
741
742  function capitalize() {
743    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
744  }
745
746  function underscore() {
747    return this.replace(/::/g, '/')
748               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
749               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
750               .replace(/-/g, '_')
751               .toLowerCase();
752  }
753
754  function dasherize() {
755    return this.replace(/_/g, '-');
756  }
757
758  function inspect(useDoubleQuotes) {
759    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(ch
759aracter) {
760      if (character in String.specialChar) {
761        return String.specialChar[character];
762      }
763      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
764    });
765    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
766    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
767  }
768
769  function unfilterJSON(filter) {
770    return this.replace(filter || Prototype.JSONFilter, '$1');
771  }
772
773  function isJSON() {
774    var str = this;
775    if (str.blank()) return false;
776    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
777    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
778    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
779    return (/^[\],:{}\s]*$/).test(str);
780  }
781
782  function evalJSON(sanitize) {
783    var json = this.unfilterJSON(),
784        cx = /[\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\u0000]/g;
785    if (cx.test(json)) {
786      json = json.replace(cx, function (a) {
787        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
788      });
789    }
790    try {
791      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
792    } catch (e) { }
793    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
794  }
795
796  function parseJSON() {
797    var json = this.unfilterJSON();
798    return JSON.parse(json);
799  }
800
801  function include(pattern) {
802    return this.indexOf(pattern) > -1;
803  }
804
805  function startsWith(pattern, position) {
806    position = Object.isNumber(position) ? position : 0;
807    return this.lastIndexOf(pattern, position) === position;
808  }
809
810  function endsWith(pattern, position) {
811    pattern = String(pattern);
812    position = Object.isNumber(position) ? position : this.length;
813    if (position < 0) position = 0;
814    if (position > this.length) position = this.length;
815    var d = position - pattern.length;
816    return d >= 0 && this.indexOf(pattern, d) === d;
817  }
818
819  function empty() {
820    return this == '';
821  }
822
823  function blank() {
824    return /^\s*$/.test(this);
825  }
826
827  function interpolate(object, pattern) {
828    return new Template(this, pattern).evaluate(object);
829  }
830
831  return {
832    gsub:           gsub,
833    sub:            sub,
834    scan:           scan,
835    truncate:       truncate,
836    strip:          String.prototype.trim || strip,
837    stripTags:      stripTags,
838    stripScripts:   stripScripts,
839    extractScripts: extractScripts,
840    evalScripts:    evalScripts,
841    escapeHTML:     escapeHTML,
842    unescapeHTML:   unescapeHTML,
843    toQueryParams:  toQueryParams,
844    parseQuery:     toQueryParams,
845    toArray:        toArray,
846    succ:           succ,
847    times:          times,
848    camelize:       camelize,
849    capitalize:     capitalize,
850    underscore:     underscore,
851    dasherize:      dasherize,
852    inspect:        inspect,
853    unfilterJSON:   unfilterJSON,
854    isJSON:         isJSON,
855    evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
856    include:        include,
857    startsWith:     String.prototype.startsWith || startsWith,
858    endsWith:       String.prototype.endsWith || endsWith,
859    empty:          empty,
860    blank:          blank,
861    interpolate:    interpolate
862  };
863})());
864
865var Template = Class.create({
866  initialize: function(template, pattern) {
867    this.template = template.toString();
868    this.pattern = pattern || Template.Pattern;
869  },
870
871  evaluate: function(object) {
872    if (object && Object.isFunction(object.toTemplateReplacements))
873      object = object.toTemplateReplacements();
874
875    return this.template.gsub(this.pattern, function(match) {
876      if (object == null) return (match[1] + '');
877
878      var before = match[1] || '';
879      if (before == '\\') return match[2];
880
881      var ctx = object, expr = match[3],
882          pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
883
884      match = pattern.exec(expr);
885      if (match == null) return before;
886
887      while (match != null) {
888        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
889        ctx = ctx[comp];
890        if (null == ctx || '' == match[3]) break;
891        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
892        match = pattern.exec(expr);
893      }
894
895      return before + String.interpret(ctx);
896    });
897  }
898});
899Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
900
901var $break = { };
902
903var Enumerable = (function() {
904  function each(iterator, context) {
905    try {
906      this._each(iterator, context);
907    } catch (e) {
908      if (e != $break) throw e;
909    }
910    return this;
911  }
912
913  function eachSlice(number, iterator, context) {
914    var index = -number, slices = [], array = this.toArray();
915    if (number < 1) return array;
916    while ((index += number) < array.length)
917      slices.push(array.slice(index, index+number));
918    return slices.collect(iterator, context);
919  }
920
921  function all(iterator, context) {
922    iterator = iterator || Prototype.K;
923    var result = true;
924    this.each(function(value, index) {
925      result = result && !!iterator.call(context, value, index, this);
926      if (!result) throw $break;
927    }, this);
928    return result;
929  }
930
931  function any(iterator, context) {
932    iterator = iterator || Prototype.K;
933    var result = false;
934    this.each(function(value, index) {
935      if (result = !!iterator.call(context, value, index, this))
936        throw $break;
937    }, this);
938    return result;
939  }
940
941  function collect(iterator, context) {
942    iterator = iterator || Prototype.K;
943    var results = [];
944    this.each(function(value, index) {
945      results.push(iterator.call(context, value, index, this));
946    }, this);
947    return results;
948  }
949
950  function detect(iterator, context) {
951    var result;
952    this.each(function(value, index) {
953      if (iterator.call(context, value, index, this)) {
954        result = value;
955        throw $break;
956      }
957    }, this);
958    return result;
959  }
960
961  function findAll(iterator, context) {
962    var results = [];
963    this.each(function(value, index) {
964      if (iterator.call(context, value, index, this))
965        results.push(value);
966    }, this);
967    return results;
968  }
969
970  function grep(filter, iterator, context) {
971    iterator = iterator || Prototype.K;
972    var results = [];
973
974    if (Object.isString(filter))
975      filter = new RegExp(RegExp.escape(filter));
976
977    this.each(function(value, index) {
978      if (filter.match(value))
979        results.push(iterator.call(context, value, index, this));
980    }, this);
981    return results;
982  }
983
984  function include(object) {
985    if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)
986      return true;
987
988    var found = false;
989    this.each(function(value) {
990      if (value == object) {
991        found = true;
992        throw $break;
993      }
994    });
995    return found;
996  }
997
998  function inGroupsOf(number, fillWith) {
999    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
1000    return this.eachSlice(number, function(slice) {
1001      while(slice.length < number) slice.push(fillWith);
1002      return slice;
1003    });
1004  }
1005
1006  function inject(memo, iterator, context) {
1007    this.each(function(value, index) {
1008      memo = iterator.call(context, memo, value, index, this);
1009    }, this);
1010    return memo;
1011  }
1012
1013  function invoke(method) {
1014    var args = $A(arguments).slice(1);
1015    return this.map(function(value) {
1016      return value[method].apply(value, args);
1017    });
1018  }
1019
1020  function max(iterator, context) {
1021    iterator = iterator || Prototype.K;
1022    var result;
1023    this.each(function(value, index) {
1024      value = iterator.call(context, value, index, this);
1025      if (result == null || value >= result)
1026        result = value;
1027    }, this);
1028    return result;
1029  }
1030
1031  function min(iterator, context) {
1032    iterator = iterator || Prototype.K;
1033    var result;
1034    this.each(function(value, index) {
1035      value = iterator.call(context, value, index, this);
1036      if (result == null || value < result)
1037        result = value;
1038    }, this);
1039    return result;
1040  }
1041
1042  function partition(iterator, context) {
1043    iterator = iterator || Prototype.K;
1044    var trues = [], falses = [];
1045    this.each(function(value, index) {
1046      (iterator.call(context, value, index, this) ?
1047        trues : falses).push(value);
1048    }, this);
1049    return [trues, falses];
1050  }
1051
1052  function pluck(property) {
1053    var results = [];
1054    this.each(function(value) {
1055      results.push(value[property]);
1056    });
1057    return results;
1058  }
1059
1060  function reject(iterator, context) {
1061    var results = [];
1062    this.each(function(value, index) {
1063      if (!iterator.call(context, value, index, this))
1064        results.push(value);
1065    }, this);
1066    return results;
1067  }
1068
1069  function sortBy(iterator, context) {
1070    return this.map(function(value, index) {
1071      return {
1072        value: value,
1073        criteria: iterator.call(context, value, index, this)
1074      };
1075    }, this).sort(function(left, right) {
1076      var a = left.criteria, b = right.criteria;
1077      return a < b ? -1 : a > b ? 1 : 0;
1078    }).pluck('value');
1079  }
1080
1081  function toArray() {
1082    return this.map();
1083  }
1084
1085  function zip() {
1086    var iterator = Prototype.K, args = $A(arguments);
1087    if (Object.isFunction(args.last()))
1088      iterator = args.pop();
1089
1090    var collections = [this].concat(args).map($A);
1091    return this.map(function(value, index) {
1092      return iterator(collections.pluck(index));
1093    });
1094  }
1095
1096  function size() {
1097    return this.toArray().length;
1098  }
1099
1100  function inspect() {
1101    return '#<Enumerable:' + this.toArray().inspect() + '>';
1102  }
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112  return {
1113    each:       each,
1114    eachSlice:  eachSlice,
1115    all:        all,
1116    every:      all,
1117    any:        any,
1118    some:       any,
1119    collect:    collect,
1120    map:        collect,
1121    detect:     detect,
1122    findAll:    findAll,
1123    select:     findAll,
1124    filter:     findAll,
1125    grep:       grep,
1126    include:    include,
1127    member:     include,
1128    inGroupsOf: inGroupsOf,
1129    inject:     inject,
1130    invoke:     invoke,
1131    max:        max,
1132    min:        min,
1133    partition:  partition,
1134    pluck:      pluck,
1135    reject:     reject,
1136    sortBy:     sortBy,
1137    toArray:    toArray,
1138    entries:    toArray,
1139    zip:        zip,
1140    size:       size,
1141    inspect:    inspect,
1142    find:       detect
1143  };
1144})();
1145
1146function $A(iterable) {
1147  if (!iterable) return [];
1148  const object = Object(iterable);
1149  if ('toArray' in object) return iterable.toArray();
1150  if (Symbol.iterator in object) return [...iterable];
1151  var length = iterable.length || 0, results = new Array(length);
1152  while (length--) results[length] = iterable[length];
1153  return results;
1154}
1155
1156
1157function $w(string) {
1158  if (!Object.isString(string)) return [];
1159  string = string.strip();
1160  return string ? string.split(/\s+/) : [];
1161}
1162
1163Array.from = $A;
1164
1165
1166(function() {
1167  var arrayProto = Array.prototype,
1168      slice = arrayProto.slice,
1169      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1170
1171  function each(iterator, context) {
1172    for (var i = 0, length = this.length >>> 0; i < length; i++) {
1173      if (i in this) iterator.call(context, this[i], i, this);
1174    }
1175  }
1176  if (!_each) _each = each;
1177
1178  function clear() {
1179    this.length = 0;
1180    return this;
1181  }
1182
1183  function first() {
1184    return this[0];
1185  }
1186
1187  function last() {
1188    return this[this.length - 1];
1189  }
1190
1191  function compact() {
1192    return this.select(function(value) {
1193      return value != null;
1194    });
1195  }
1196
1197  function flatten() {
1198    return this.inject([], function(array, value) {
1199      if (Object.isArray(value))
1200        return array.concat(value.flatten());
1201      array.push(value);
1202      return array;
1203    });
1204  }
1205
1206  function without() {
1207    var values = slice.call(arguments, 0);
1208    return this.select(function(value) {
1209      return !values.include(value);
1210    });
1211  }
1212
1213  function reverse(inline) {
1214    return (inline === false ? this.toArray() : this)._reverse();
1215  }
1216
1217  function uniq(sorted) {
1218    return this.inject([], function(array, value, index) {
1219      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1220        array.push(value);
1221      return array;
1222    });
1223  }
1224
1225  function intersect(array) {
1226    return this.uniq().findAll(function(item) {
1227      return array.indexOf(item) !== -1;
1228    });
1229  }
1230
1231
1232  function clone() {
1233    return slice.call(this, 0);
1234  }
1235
1236  function size() {
1237    return this.length;
1238  }
1239
1240  function inspect() {
1241    return '[' + this.map(Object.inspect).join(', ') + ']';
1242  }
1243
1244  function indexOf(item, i) {
1245    if (this == null) throw new TypeError();
1246
1247    var array = Object(this), length = array.length >>> 0;
1248    if (length === 0) return -1;
1249
1250    i = Number(i);
1251    if (isNaN(i)) {
1252      i = 0;
1253    } else if (i !== 0 && isFinite(i)) {
1254      i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1255    }
1256
1257    if (i > length) return -1;
1258
1259    var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);
1260    for (; k < length; k++)
1261      if (k in array && array[k] === item) return k;
1262    return -1;
1263  }
1264
1265
1266  function lastIndexOf(item, i) {
1267    if (this == null) throw new TypeError();
1268
1269    var array = Object(this), length = array.length >>> 0;
1270    if (length === 0) return -1;
1271
1272    if (!Object.isUndefined(i)) {
1273      i = Number(i);
1274      if (isNaN(i)) {
1275        i = 0;
1276      } else if (i !== 0 && isFinite(i)) {
1277        i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1278      }
1279    } else {
1280      i = length;
1281    }
1282
1283    var k = i >= 0 ? Math.min(i, length - 1) :
1284     length - Math.abs(i);
1285
1286    for (; k >= 0; k--)
1287      if (k in array && array[k] === item) return k;
1288    return -1;
1289  }
1290
1291  function concat(_) {
1292    var array = [], items = slice.call(arguments, 0), item, n = 0;
1293    items.unshift(this);
1294    for (var i = 0, length = items.length; i < length; i++) {
1295      item = items[i];
1296      if (Object.isArray(item) && !('callee' in item)) {
1297        for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
1298          if (j in item) array[n] = item[j];
1299          n++;
1300        }
1301      } else {
1302        array[n++] = item;
1303      }
1304    }
1305    array.length = n;
1306    return array;
1307  }
1308
1309
1310  function wrapNative(method) {
1311    return function() {
1312      if (arguments.length === 0) {
1313        return method.call(this, Prototype.K);
1314      } else if (arguments[0] === undefined) {
1315        var args = slice.call(arguments, 1);
1316        args.unshift(Prototype.K);
1317        return method.apply(this, args);
1318      } else {
1319        return method.apply(this, arguments);
1320      }
1321    };
1322  }
1323
1324
1325  function map(iterator) {
1326    if (this == null) throw new TypeError();
1327    iterator = iterator || Prototype.K;
1328
1329    var object = Object(this);
1330    var results = [], context = arguments[1], n = 0;
1331
1332    for (var i = 0, length = object.length >>> 0; i < length; i++) {
1333      if (i in object) {
1334        results[n] = iterator.call(context, object[i], i, object);
1335      }
1336      n++;
1337    }
1338    results.length = n;
1339    return results;
1340  }
1341
1342  if (arrayProto.map) {
1343    map = wrapNative(Array.prototype.map);
1344  }
1345
1346  function filter(iterator) {
1347    if (this == null || !Object.isFunction(iterator))
1348      throw new TypeError();
1349
1350    var object = Object(this);
1351    var results = [], context = arguments[1], value;
1352
1353    for (var i = 0, length = object.length >>> 0; i < length; i++) {
1354      if (i in object) {
1355        value = object[i];
1356        if (iterator.call(context, value, i, object)) {
1357          results.push(value);
1358        }
1359      }
1360    }
1361    return results;
1362  }
1363
1364  if (arrayProto.filter) {
1365    filter = Array.prototype.filter;
1366  }
1367
1368  function some(iterator) {
1369    if (this == null) throw new TypeError();
1370    iterator = iterator || Prototype.K;
1371    var context = arguments[1];
1372
1373    var object = Object(this);
1374    for (var i = 0, length = object.length >>> 0; i < length; i++) {
1375      if (i in object && iterator.call(context, object[i], i, object)) {
1376        return true;
1377      }
1378    }
1379
1380    return false;
1381  }
1382
1383  if (arrayProto.some) {
1384    some = wrapNative(Array.prototype.some);
1385  }
1386
1387  function every(iterator) {
1388    if (this == null) throw new TypeError();
1389    iterator = iterator || Prototype.K;
1390    var context = arguments[1];
1391
1392    var object = Object(this);
1393    for (var i = 0, length = object.length >>> 0; i < length; i++) {
1394      if (i in object && !iterator.call(context, object[i], i, object)) {
1395        return false;
1396      }
1397    }
1398
1399    return true;
1400  }
1401
1402  if (arrayProto.every) {
1403    every = wrapNative(Array.prototype.every);
1404  }
1405
1406
1407  Object.extend(arrayProto, Enumerable);
1408
1409  if (arrayProto.entries === Enumerable.entries) {
1410    delete arrayProto.entries;
1411  }
1412
1413  if (!arrayProto._reverse)
1414    arrayProto._reverse = arrayProto.reverse;
1415
1416  Object.extend(arrayProto, {
1417    _each:     _each,
1418
1419    map:       map,
1420    collect:   map,
1421    select:    filter,
1422    filter:    filter,
1423    findAll:   filter,
1424    some:      some,
1425    any:       some,
1426    every:     every,
1427    all:       every,
1428
1429    clear:     clear,
1430    first:     first,
1431    last:      last,
1432    compact:   compact,
1433    flatten:   flatten,
1434    without:   without,
1435    reverse:   reverse,
1436    uniq:      uniq,
1437    intersect: intersect,
1438    clone:     clone,
1439    toArray:   clone,
1440    size:      size,
1441    inspect:   inspect
1442  });
1443
1444  var CONCAT_ARGUMENTS_BUGGY = (function() {
1445    return [].concat(arguments)[0][0] !== 1;
1446  })(1,2);
1447
1448  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1449
1450  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1451  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1452})();
1453function $H(object) {
1454  return new Hash(object);
1455};
1456
1457var Hash = Class.create(Enumerable, (function() {
1458  function initialize(object) {
1459    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1460  }
1461
1462
1463  function _each(iterator, context) {
1464    var i = 0;
1465    for (var key in this._object) {
1466      var value = this._object[key], pair = [key, value];
1467      pair.key = key;
1468      pair.value = value;
1469      iterator.call(context, pair, i);
1470      i++;
1471    }
1472  }
1473
1474  function set(key, value) {
1475    return this._object[key] = value;
1476  }
1477
1478  function get(key) {
1479    if (this._object[key] !== Object.prototype[key])
1480      return this._object[key];
1481  }
1482
1483  function unset(key) {
1484    var value = this._object[key];
1485    delete this._object[key];
1486    return value;
1487  }
1488
1489  function toObject() {
1490    return Object.clone(this._object);
1491  }
1492
1493
1494
1495  function keys() {
1496    return this.pluck('key');
1497  }
1498
1499  function values() {
1500    return this.pluck('value');
1501  }
1502
1503  function index(value) {
1504    var match = this.detect(function(pair) {
1505      return pair.value === value;
1506    });
1507    return match && match.key;
1508  }
1509
1510  function merge(object) {
1511    return this.clone().update(object);
1512  }
1513
1514  function update(object) {
1515    return new Hash(object).inject(this, function(result, pair) {
1516      result.set(pair.key, pair.value);
1517      return result;
1518    });
1519  }
1520
1521  function toQueryPair(key, value) {
1522    if (Object.isUndefined(value)) return key;
1523
1524    value = String.interpret(value);
1525
1526    value = value.gsub(/(\r)?\n/, '\r\n');
1527    value = encodeURIComponent(value);
1528    value = value.gsub(/%20/, '+');
1529    return key + '=' + value;
1530  }
1531
1532  function toQueryString() {
1533    return this.inject([], function(results, pair) {
1534      var key = encodeURIComponent(pair.key), values = pair.value;
1535
1536      if (values && typeof values == 'object') {
1537        if (Object.isArray(values)) {
1538          var queryValues = [];
1539          for (var i = 0, len = values.length, value; i < len; i++) {
1540            value = values[i];
1541            queryValues.push(toQueryPair(key, value));
1542          }
1543          return results.concat(queryValues);
1544        }
1545      } else results.push(toQueryPair(key, values));
1546      return results;
1547    }).join('&');
1548  }
1549
1550  function inspect() {
1551    return '#<Hash:{' + this.map(function(pair) {
1552      return pair.map(Object.inspect).join(': ');
1553    }).join(', ') + '}>';
1554  }
1555
1556  function clone() {
1557    return new Hash(this);
1558  }
1559
1560  return {
1561    initialize:             initialize,
1562    _each:                  _each,
1563    set:                    set,
1564    get:                    get,
1565    unset:                  unset,
1566    toObject:               toObject,
1567    toTemplateReplacements: toObject,
1568    keys:                   keys,
1569    values:                 values,
1570    index:                  index,
1571    merge:                  merge,
1572    update:                 update,
1573    toQueryString:          toQueryString,
1574    inspect:                inspect,
1575    toJSON:                 toObject,
1576    clone:                  clone
1577  };
1578})());
1579
1580Hash.from = $H;
1581Object.extend(Number.prototype, (function() {
1582  function toColorPart() {
1583    return this.toPaddedString(2, 16);
1584  }
1585
1586  function succ() {
1587    return this + 1;
1588  }
1589
1590  function times(iterator, context) {
1591    $R(0, this, true).each(iterator, context);
1592    return this;
1593  }
1594
1595  function toPaddedString(length, radix) {
1596    var string = this.toString(radix || 10);
1597    return '0'.times(length - string.length) + string;
1598  }
1599
1600  function abs() {
1601    return Math.abs(this);
1602  }
1603
1604  function round() {
1605    return Math.round(this);
1606  }
1607
1608  function ceil() {
1609    return Math.ceil(this);
1610  }
1611
1612  function floor() {
1613    return Math.floor(this);
1614  }
1615
1616  return {
1617    toColorPart:    toColorPart,
1618    succ:           succ,
1619    times:          times,
1620    toPaddedString: toPaddedString,
1621    abs:            abs,
1622    round:          round,
1623    ceil:           ceil,
1624    floor:          floor
1625  };
1626})());
1627
1628function $R(start, end, exclusive) {
1629  return new ObjectRange(start, end, exclusive);
1630}
1631
1632var ObjectRange = Class.create(Enumerable, (function() {
1633  function initialize(start, end, exclusive) {
1634    this.start = start;
1635    this.end = end;
1636    this.exclusive = exclusive;
1637  }
1638
1639  function _each(iterator, context) {
1640    var value = this.start, i;
1641    for (i = 0; this.include(value); i++) {
1642      iterator.call(context, value, i);
1643      value = value.succ();
1644    }
1645  }
1646
1647  function include(value) {
1648    if (value < this.start)
1649      return false;
1650    if (this.exclusive)
1651      return value < this.end;
1652    return value <= this.end;
1653  }
1654
1655  return {
1656    initialize: initialize,
1657    _each:      _each,
1658    include:    include
1659  };
1660})());
1661
1662
1663
1664var Abstract = { };
1665
1666
1667var Try = {
1668  these: function() {
1669    var returnValue;
1670
1671    for (var i = 0, length = arguments.length; i < length; i++) {
1672      var lambda = arguments[i];
1673      try {
1674        returnValue = lambda();
1675        break;
1676      } catch (e) { }
1677    }
1678
1679    return returnValue;
1680  }
1681};
1682
1683var Ajax = {
1684  getTransport: function() {
1685    return Try.these(
1686      function() {return new XMLHttpRequest()},
1687      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1688      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1689    ) || false;
1690  },
1691
1692  activeRequestCount: 0
1693};
1694
1695Ajax.Responders = {
1696  responders: [],
1697
1698  _each: function(iterator, context) {
1699    this.responders._each(iterator, context);
1700  },
1701
1702  register: function(responder) {
1703    if (!this.include(responder))
1704      this.responders.push(responder);
1705  },
1706
1707  unregister: function(responder) {
1708    this.responders = this.responders.without(responder);
1709  },
1710
1711  dispatch: function(callback, request, transport, json) {
1712    this.each(function(responder) {
1713      if (Object.isFunction(responder[callback])) {
1714        try {
1715          responder[callback].apply(responder, [request, transport, json]);
1716        } catch (e) { }
1717      }
1718    });
1719  }
1720};
1721
1722Object.extend(Ajax.Responders, Enumerable);
1723
1724Ajax.Responders.register({
1725  onCreate:   function() { Ajax.activeRequestCount++ },
1726  onComplete: function() { Ajax.activeRequestCount-- }
1727});
1728Ajax.Base = Class.create({
1729  initialize: function(options) {
1730    this.options = {
1731      method:       'post',
1732      asynchronous: true,
1733      contentType:  'application/x-www-form-urlencoded',
1734      encoding:     'UTF-8',
1735      parameters:   '',
1736      evalJSON:     true,
1737      evalJS:       true
1738    };
1739    Object.extend(this.options, options || { });
1740
1741    this.options.method = this.options.method.toLowerCase();
1742
1743    if (Object.isHash(this.options.parameters))
1744      this.options.parameters = this.options.parameters.toObject();
1745  }
1746});
1747Ajax.Request = Class.create(Ajax.Base, {
1748  _complete: false,
1749
1750  initialize: function($super, url, options) {
1751    $super(options);
1752    this.transport = Ajax.getTransport();
1753    this.request(url);
1754  },
1755
1756  request: function(url) {
1757    this.url = url;
1758    this.method = this.options.method;
1759    var params = Object.isString(this.options.parameters) ?
1760          this.options.parameters :
1761          Object.toQueryString(this.options.parameters);
1762
1763    if (!['get', 'post'].include(this.method)) {
1764      params += (params ? '&' : '') + "_method=" + this.method;
1765      this.method = 'post';
1766    }
1767
1768    if (params && this.method === 'get') {
1769      this.url += (this.url.include('?') ? '&' : '?') + params;
1770    }
1771
1772    this.parameters = params.toQueryParams();
1773
1774    try {
1775      var response = new Ajax.Response(this);
1776      if (this.options.onCreate) this.options.onCreate(response);
1777      Ajax.Responders.dispatch('onCreate', this, response);
1778
1779      this.transport.open(this.method.toUpperCase(), this.url,
1780        this.options.asynchronous);
1781
1782      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1783
1784      this.transport.onreadystatechange = this.onStateChange.bind(this);
1785      this.setRequestHeaders();
1786
1787      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1788      this.transport.send(this.body);
1789
1790      /* Force Firefox to handle ready state 4 for synchronous requests */
1791      if (!this.options.asynchronous && this.transport.overrideMimeType)
1792        this.onStateChange();
1793
1794    }
1795    catch (e) {
1796      this.dispatchException(e);
1797    }
1798  },
1799
1800  onStateChange: function() {
1801    var readyState = this.transport.readyState;
1802    if (readyState > 1 && !((readyState == 4) && this._complete))
1803      this.respondToReadyState(this.transport.readyState);
1804  },
1805
1806  setRequestHeaders: function() {
1807    var headers = {
1808      'X-Requested-With': 'XMLHttpRequest',
1809      'X-Prototype-Version': Prototype.Version,
1810      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1811    };
1812
1813    if (this.method == 'post') {
1814      headers['Content-type'] = this.options.contentType +
1815        (this.options.encoding ? '; charset=' + this.options.encoding : '');
1816
1817      /* Force "Connection: close" for older Mozilla browsers to work
1818       * around a bug where XMLHttpRequest sends an incorrect
1819       * Content-length header. See Mozilla Bugzilla #246651.
1820       */
1821      if (this.transport.overrideMimeType &&
1822          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1823            headers['Connection'] = 'close';
1824    }
1825
1826    if (typeof this.options.requestHeaders == 'object') {
1827      var extras = this.options.requestHeaders;
1828
1829      if (Object.isFunction(extras.push))
1830        for (var i = 0, length = extras.length; i < length; i += 2)
1831          headers[extras[i]] = extras[i+1];
1832      else
1833        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1834    }
1835
1836    for (var name in headers)
1837      if (headers[name] != null)
1838        this.transport.setRequestHeader(name, headers[name]);
1839  },
1840
1841  success: function() {
1842    var status = this.getStatus();
1843    return !status || (status >= 200 && status < 300) || status == 304;
1844  },
1845
1846  getStatus: function() {
1847    try {
1848      if (this.transport.status === 1223) return 204;
1849      return this.transport.status || 0;
1850    } catch (e) { return 0 }
1851  },
1852
1853  respondToReadyState: function(readyState) {
1854    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1855
1856    if (state == 'Complete') {
1857      try {
1858        this._complete = true;
1859        (this.options['on' + response.status]
1860         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1861         || Prototype.emptyFunction)(response, response.headerJSON);
1862      } catch (e) {
1863        this.dispatchException(e);
1864      }
1865
1866      var contentType = response.getHeader('Content-type');
1867      if (this.options.evalJS == 'force'
1868          || (this.options.evalJS && this.isSameOrigin() && contentType
1869          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1870        this.evalResponse();
1871    }
1872
1873    try {
1874      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1875      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1876    } catch (e) {
1877      this.dispatchException(e);
1878    }
1879
1880    if (state == 'Complete') {
1881      this.transport.onreadystatechange = Prototype.emptyFunction;
1882    }
1883  },
1884
1885  isSameOrigin: function() {
1886    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1887    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1888      protocol: location.protocol,
1889      domain: document.domain,
1890      port: location.port ? ':' + location.port : ''
1891    }));
1892  },
1893
1894  getHeader: function(name) {
1895    try {
1896      return this.transport.getResponseHeader(name) || null;
1897    } catch (e) { return null; }
1898  },
1899
1900  evalResponse: function() {
1901    try {
1902      return eval((this.transport.responseText || '').unfilterJSON());
1903    } catch (e) {
1904      this.dispatchException(e);
1905    }
1906  },
1907
1908  dispatchException: function(exception) {
1909    (this.options.onException || Prototype.emptyFunction)(this, exception);
1910    Ajax.Responders.dispatch('onException', this, exception);
1911  }
1912});
1913
1914Ajax.Request.Events =
1915  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1916
1917
1918
1919
1920
1921
1922
1923
1924Ajax.Response = Class.create({
1925  initialize: function(request){
1926    this.request = request;
1927    var transport  = this.transport  = request.transport,
1928        readyState = this.readyState = transport.readyState;
1929
1930    if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1931      this.status       = this.getStatus();
1932      this.statusText   = this.getStatusText();
1933      this.responseText = String.interpret(transport.responseText);
1934      this.headerJSON   = this._getHeaderJSON();
1935    }
1936
1937    if (readyState == 4) {
1938      var xml = transport.responseXML;
1939      this.responseXML  = Object.isUndefined(xml) ? null : xml;
1940      this.responseJSON = this._getResponseJSON();
1941    }
1942  },
1943
1944  status:      0,
1945
1946  statusText: '',
1947
1948  getStatus: Ajax.Request.prototype.getStatus,
1949
1950  getStatusText: function() {
1951    try {
1952      return this.transport.statusText || '';
1953    } catch (e) { return '' }
1954  },
1955
1956  getHeader: Ajax.Request.prototype.getHeader,
1957
1958  getAllHeaders: function() {
1959    try {
1960      return this.getAllResponseHeaders();
1961    } catch (e) { return null }
1962  },
1963
1964  getResponseHeader: function(name) {
1965    return this.transport.getResponseHeader(name);
1966  },
1967
1968  getAllResponseHeaders: function() {
1969    return this.transport.getAllResponseHeaders();
1970  },
1971
1972  _getHeaderJSON: function() {
1973    var json = this.getHeader('X-JSON');
1974    if (!json) return null;
1975
1976    try {
1977      json = decodeURIComponent(escape(json));
1978    } catch(e) {
1979    }
1980
1981    try {
1982      return json.evalJSON(this.request.options.sanitizeJSON ||
1983        !this.request.isSameOrigin());
1984    } catch (e) {
1985      this.request.dispatchException(e);
1986    }
1987  },
1988
1989  _getResponseJSON: function() {
1990    var options = this.request.options;
1991    if (!options.evalJSON || (options.evalJSON != 'force' &&
1992      !(this.getHeader('Content-type') || '').include('application/json')) ||
1993        this.responseText.blank())
1994          return null;
1995    try {
1996      return this.responseText.evalJSON(options.sanitizeJSON ||
1997        !this.request.isSameOrigin());
1998    } catch (e) {
1999      this.request.dispatchException(e);
2000    }
2001  }
2002});
2003
2004Ajax.Updater = Class.create(Ajax.Request, {
2005  initialize: function($super, container, url, options) {
2006    this.container = {
2007      success: (container.success || container),
2008      failure: (container.failure || (container.success ? null : container))
2009    };
2010
2011    options = Object.clone(options);
2012    var onComplete = options.onComplete;
2013    options.onComplete = (function(response, json) {
2014      this.updateContent(response.responseText);
2015      if (Object.isFunction(onComplete)) onComplete(response, json);
2016    }).bind(this);
2017
2018    $super(url, options);
2019  },
2020
2021  updateContent: function(responseText) {
2022    var receiver = this.container[this.success() ? 'success' : 'failure'],
2023        options = this.options;
2024
2025    if (!options.evalScripts) responseText = responseText.stripScripts();
2026
2027    if (receiver = $$$(receiver)) {
2028      if (options.insertion) {
2029        if (Object.isString(options.insertion)) {
2030          var insertion = { }; insertion[options.insertion] = responseText;
2031          receiver.insert(insertion);
2032        }
2033        else options.insertion(receiver, responseText);
2034      }
2035      else receiver.update(responseText);
2036    }
2037  }
2038});
2039
2040Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
2041  initialize: function($super, container, url, options) {
2042    $super(options);
2043    this.onComplete = this.options.onComplete;
2044
2045    this.frequency = (this.options.frequency || 2);
2046    this.decay = (this.options.decay || 1);
2047
2048    this.updater = { };
2049    this.container = container;
2050    this.url = url;
2051
2052    this.start();
2053  },
2054
2055  start: function() {
2056    this.options.onComplete = this.updateComplete.bind(this);
2057    this.onTimerEvent();
2058  },
2059
2060  stop: function() {
2061    this.updater.options.onComplete = undefined;
2062    clearTimeout(this.timer);
2063    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
2064  },
2065
2066  updateComplete: function(response) {
2067    if (this.options.decay) {
2068      this.decay = (response.responseText == this.lastText ?
2069        this.decay * this.options.decay : 1);
2070
2071      this.lastText = response.responseText;
2072    }
2073    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
2074  },
2075
2076  onTimerEvent: function() {
2077    this.updater = new Ajax.Updater(this.container, this.url, this.options);
2078  }
2079});
2080
2081(function(GLOBAL) {
2082
2083  var UNDEFINED;
2084  var SLICE = Array.prototype.slice;
2085
2086  var DIV = document.createElement('div');
2087
2088
2089  function $$$(element) {
2090    if (arguments.length > 1) {
2091      for (var i = 0, elements = [], length = arguments.length; i < length; i++)
2092        elements.push($$$(arguments[i]));
2093      return elements;
2094    }
2095
2096    if (Object.isString(element))
2097      element = document.getElementById(element);
2098    return Element.extend(element);
2099  }
2100
2101  GLOBAL.$$$ = $$$;
2102
2103
2104  if (!GLOBAL.Node) GLOBAL.Node = {};
2105
2106  if (!GLOBAL.Node.ELEMENT_NODE) {
2107    Object.extend(GLOBAL.Node, {
2108      ELEMENT_NODE:                1,
2109      ATTRIBUTE_NODE:              2,
2110      TEXT_NODE:                   3,
2111      CDATA_SECTION_NODE:          4,
2112      ENTITY_REFERENCE_NODE:       5,
2113      ENTITY_NODE:                 6,
2114      PROCESSING_INSTRUCTION_NODE: 7,
2115      COMMENT_NODE:                8,
2116      DOCUMENT_NODE:               9,
2117      DOCUMENT_TYPE_NODE:         10,
2118      DOCUMENT_FRAGMENT_NODE:     11,
2119      NOTATION_NODE:              12
2120    });
2121  }
2122
2123  var ELEMENT_CACHE = {};
2124
2125  function shouldUseCreationCache(tagName, attributes) {
2126    if (tagName === 'select') return false;
2127    if ('type' in attributes) return false;
2128    return true;
2129  }
2130
2131  var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
2132    try {
2133      var el = document.createElement('<input name="x">');
2134      return el.tagName.toLowerCase() === 'input' && el.name === 'x';
2135    }
2136    catch(err) {
2137      return false;
2138    }
2139  })();
2140
2141
2142  var oldElement = GLOBAL.Element;
2143  function Element(tagName, attributes) {
2144    attributes = attributes || {};
2145    tagName = tagName.toLowerCase();
2146
2147    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
2148      tagName = '<' + tagName + ' name="' + attributes.name + '">';
2149      delete attributes.name;
2150      return Element.writeAttribute(document.createElement(tagName), attributes);
2151    }
2152
2153    if (!ELEMENT_CACHE[tagName])
2154      ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));
2155
2156    var node = shouldUseCreationCache(tagName, attributes) ?
2157     ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);
2158
2159    return Element.writeAttribute(node, attributes);
2160  }
2161
2162  GLOBAL.Element = Element;
2163
2164  Object.extend(GLOBAL.Element, oldElement || {});
2165  if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;
2166
2167  Element.Methods = { ByTag: {}, Simulated: {} };
2168
2169  var methods = {};
2170
2171  var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };
2172  function inspect(element) {
2173    element = $$$(element);
2174    var result = '<' + element.tagName.toLowerCase();
2175
2176    var attribute, value;
2177    for (var property in INSPECT_ATTRIBUTES) {
2178      attribute = INSPECT_ATTRIBUTES[property];
2179      value = (element[property] || '').toString();
2180      if (value) result += ' ' + attribute + '=' + value.inspect(true);
2181    }
2182
2183    return result + '>';
2184  }
2185
2186  methods.inspect = inspect;
2187
2188
2189  function visible(element) {
2190    return $$$(element).getStyle('display') !== 'none';
2191  }
2192
2193  function toggle(element, bool) {
2194    element = $$$(element);
2195    if (typeof bool !== 'boolean')
2196      bool = !Element.visible(element);
2197    Element[bool ? 'show' : 'hide'](element);
2198
2199    return element;
2200  }
2201
2202  function hide(element) {
2203    element = $$$(element);
2204    element.style.display = 'none';
2205    return element;
2206  }
2207
2208  function show(element) {
2209    element = $$$(element);
2210    element.style.display = '';
2211    return element;
2212  }
2213
2214
2215  Object.extend(methods, {
2216    visible: visible,
2217    toggle:  toggle,
2218    hide:    hide,
2219    show:    show
2220  });
2221
2222
2223  function remove(element) {
2224    element = $$$(element);
2225    element.parentNode.removeChild(element);
2226    return element;
2227  }
2228
2229  var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
2230    var el = document.createElement("select"),
2231        isBuggy = true;
2232    el.innerHTML = "<option value=\"test\">test</option>";
2233    if (el.options && el.options[0]) {
2234      isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
2235    }
2236    el = null;
2237    return isBuggy;
2238  })();
2239
2240  var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
2241    try {
2242      var el = document.createElement("table");
2243      if (el && el.tBodies) {
2244        el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
2245        var isBuggy = typeof el.tBodies[0] == "undefined";
2246        el = null;
2247        return isBuggy;
2248      }
2249    } catch (e) {
2250      return true;
2251    }
2252  })();
2253
2254  var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
2255    try {
2256      var el = document.createElement('div');
2257      el.innerHTML = "<link />";
2258      var isBuggy = (el.childNodes.length === 0);
2259      el = null;
2260      return isBuggy;
2261    } catch(e) {
2262      return true;
2263    }
2264  })();
2265
2266  var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
2267   TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
2268
2269  var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
2270    var s = document.createElement("script"),
2271        isBuggy = false;
2272    try {
2273      s.appendChild(document.createTextNode(""));
2274      isBuggy = !s.firstChild ||
2275        s.firstChild && s.firstChild.nodeType !== 3;
2276    } catch (e) {
2277      isBuggy = true;
2278    }
2279    s = null;
2280    return isBuggy;
2281  })();
2282
2283  function update(element, content) {
2284    element = $$$(element);
2285
2286    var descendants = element.getElementsByTagName('*'),
2287     i = descendants.length;
2288    while (i--) purgeElement(descendants[i]);
2289
2290    if (content && content.toElement)
2291      content = content.toElement();
2292
2293    if (Object.isElement(content))
2294      return element.update().insert(content);
2295
2296
2297    content = Object.toHTML(content);
2298    var tagName = element.tagName.toUpperCase();
2299
2300    if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
2301      element.text = content;
2302      return element;
2303    }
2304
2305    if (ANY_INNERHTML_BUGGY) {
2306      if (tagName in INSERTION_TRANSLATIONS.tags) {
2307        while (element.firstChild)
2308          element.removeChild(element.firstChild);
2309
2310        var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2311        for (var i = 0, node; node = nodes[i]; i++)
2312          element.appendChild(node);
2313
2314      } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
2315        while (element.firstChild)
2316          element.removeChild(element.firstChild);
2317
2318        var nodes = getContentFromAnonymousElement(tagName,
2319         content.stripScripts(), true);
2320
2321        for (var i = 0, node; node = nodes[i]; i++)
2322          element.appendChild(node);
2323      } else {
2324        element.innerHTML = content.stripScripts();
2325      }
2326    } else {
2327      element.innerHTML = content.stripScripts();
2328    }
2329
2330    content.evalScripts.bind(content).defer();
2331    return element;
2332  }
2333
2334  function replace(element, content) {
2335    element = $$$(element);
2336
2337    if (content && content.toElement) {
2338      content = content.toElement();
2339    } else if (!Object.isElement(content)) {
2340      content = Object.toHTML(content);
2341      var range = element.ownerDocument.createRange();
2342      range.selectNode(element);
2343      content.evalScripts.bind(content).defer();
2344      content = range.createContextualFragment(content.stripScripts());
2345    }
2346
2347    element.parentNode.replaceChild(content, element);
2348    return element;
2349  }
2350
2351  var INSERTION_TRANSLATIONS = {
2352    before: function(element, node) {
2353      element.parentNode.insertBefore(node, element);
2354    },
2355    top: function(element, node) {
2356      element.insertBefore(node, element.firstChild);
2357    },
2358    bottom: function(element, node) {
2359      element.appendChild(node);
2360    },
2361    after: function(element, node) {
2362      element.parentNode.insertBefore(node, element.nextSibling);
2363    },
2364
2365    tags: {
2366      TABLE:  ['<table>',                '</table>',                   1],
2367      TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
2368      TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
2369      TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2370      SELECT: ['<select>',               '</select>',                  1]
2371    }
2372  };
2373
2374  var tags = INSERTION_TRANSLATIONS.tags;
2375
2376  Object.extend(tags, {
2377    THEAD: tags.TBODY,
2378    TFOOT: tags.TBODY,
2379    TH:    tags.TD
2380  });
2381
2382  function replace_IE(element, content) {
2383    element = $$$(element);
2384    if (content && content.toElement)
2385      content = content.toElement();
2386    if (Object.isElement(content)) {
2387      element.parentNode.replaceChild(content, element);
2388      return element;
2389    }
2390
2391    content = Object.toHTML(content);
2392    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2393
2394    if (tagName in INSERTION_TRANSLATIONS.tags) {
2395      var nextSibling = Element.next(element);
2396      var fragments = getContentFromAnonymousElement(
2397       tagName, content.stripScripts());
2398
2399      parent.removeChild(element);
2400
2401      var iterator;
2402      if (nextSibling)
2403        iterator = function(node) { parent.insertBefore(node, nextSibling) };
2404      else
2405        iterator = function(node) { parent.appendChild(node); }
2406
2407      fragments.each(iterator);
2408    } else {
2409      element.outerHTML = content.stripScripts();
2410    }
2411
2412    content.evalScripts.bind(content).defer();
2413    return element;
2414  }
2415
2416  if ('outerHTML' in document.documentElement)
2417    replace = replace_IE;
2418
2419  function isContent(content) {
2420    if (Object.isUndefined(content) || content === null) return false;
2421
2422    if (Object.isString(content) || Object.isNumber(content)) return true;
2423    if (Object.isElement(content)) return true;
2424    if (content.toElement || content.toHTML) return true;
2425
2426    return false;
2427  }
2428
2429  function insertContentAt(element, content, position) {
2430    position   = position.toLowerCase();
2431    var method = INSERTION_TRANSLATIONS[position];
2432
2433    if (content && content.toElement) content = content.toElement();
2434    if (Object.isElement(content)) {
2435      method(element, content);
2436      return element;
2437    }
2438
2439    content = Object.toHTML(content);
2440    var tagName = ((position === 'before' || position === 'after') ?
2441     element.parentNode : element).tagName.toUpperCase();
2442
2443    var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2444
2445    if (position === 'top' || position === 'after') childNodes.reverse();
2446
2447    for (var i = 0, node; node = childNodes[i]; i++)
2448      method(element, node);
2449
2450    content.evalScripts.bind(content).defer();
2451  }
2452
2453  function insert(element, insertions) {
2454    element = $$$(element);
2455
2456    if (isContent(insertions))
2457      insertions = { bottom: insertions };
2458
2459    for (var position in insertions)
2460      insertContentAt(element, insertions[position], position);
2461
2462    return element;
2463  }
2464
2465  function wrap(element, wrapper, attributes) {
2466    element = $$$(element);
2467
2468    if (Object.isElement(wrapper)) {
2469      $$$(wrapper).writeAttribute(attributes || {});
2470    } else if (Object.isString(wrapper)) {
2471      wrapper = new Element(wrapper, attributes);
2472    } else {
2473      wrapper = new Element('div', wrapper);
2474    }
2475
2476    if (element.parentNode)
2477      element.parentNode.replaceChild(wrapper, element);
2478
2479    wrapper.appendChild(element);
2480
2481    return wrapper;
2482  }
2483
2484  function cleanWhitespace(element) {
2485    element = $$$(element);
2486    var node = element.firstChild;
2487
2488    while (node) {
2489      var nextNode = node.nextSibling;
2490      if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue))
2491        element.removeChild(node);
2492      node = nextNode;
2493    }
2494    return element;
2495  }
2496
2497  function empty(element) {
2498    return $$$(element).innerHTML.blank();
2499  }
2500
2501  function getContentFromAnonymousElement(tagName, html, force) {
2502    var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;
2503
2504    var workaround = !!t;
2505    if (!workaround && force) {
2506      workaround = true;
2507      t = ['', '', 0];
2508    }
2509
2510    if (workaround) {
2511      div.innerHTML = '&#160;' + t[0] + html + t[1];
2512      div.removeChild(div.firstChild);
2513      for (var i = t[2]; i--; )
2514        div = div.firstChild;
2515    } else {
2516      div.innerHTML = html;
2517    }
2518
2519    return $A(div.childNodes);
2520  }
2521
2522  function clone(element, deep) {
2523    if (!(element = $$$(element))) return;
2524    var clone = element.cloneNode(deep);
2525    if (!HAS_UNIQUE_ID_PROPERTY) {
2526      clone._prototypeUID = UNDEFINED;
2527      if (deep) {
2528        var descendants = Element.select(clone, '*'),
2529         i = descendants.length;
2530        while (i--)
2531          descendants[i]._prototypeUID = UNDEFINED;
2532      }
2533    }
2534    return Element.extend(clone);
2535  }
2536
2537  function purgeElement(element) {
2538    var uid = getUniqueElementID(element);
2539    if (uid) {
2540      Element.stopObserving(element);
2541      if (!HAS_UNIQUE_ID_PROPERTY)
2542        element._prototypeUID = UNDEFINED;
2543      delete Element.Storage[uid];
2544    }
2545  }
2546
2547  function purgeCollection(elements) {
2548    var i = elements.length;
2549    while (i--)
2550      purgeElement(elements[i]);
2551  }
2552
2553  function purgeCollection_IE(elements) {
2554    var i = elements.length, element, uid;
2555    while (i--) {
2556      element = elements[i];
2557      uid = getUniqueElementID(element);
2558      delete Element.Storage[uid];
2559      delete Event.cache[uid];
2560    }
2561  }
2562
2563  if (HAS_UNIQUE_ID_PROPERTY) {
2564    purgeCollection = purgeCollection_IE;
2565  }
2566
2567
2568  function purge(element) {
2569    if (!(element = $$$(element))) return;
2570    purgeElement(element);
2571
2572    var descendants = element.getElementsByTagName('*'),
2573     i = descendants.length;
2574
2575    while (i--) purgeElement(descendants[i]);
2576
2577    return null;
2578  }
2579
2580  Object.extend(methods, {
2581    remove:  remove,
2582    update:  update,
2583    replace: replace,
2584    insert:  insert,
2585    wrap:    wrap,
2586    cleanWhitespace: cleanWhitespace,
2587    empty:   empty,
2588    clone:   clone,
2589    purge:   purge
2590  });
2591
2592
2593
2594  function recursivelyCollect(element, property, maximumLength) {
2595    element = $$$(element);
2596    maximumLength = maximumLength || -1;
2597    var elements = [];
2598
2599    while (element = element[property]) {
2600      if (element.nodeType === Node.ELEMENT_NODE)
2601        elements.push(Element.extend(element));
2602
2603      if (elements.length === maximumLength) break;
2604    }
2605
2606    return elements;
2607  }
2608
2609
2610  function ancestors(element) {
2611    return recursivelyCollect(element, 'parentNode');
2612  }
2613
2614  function descendants(element) {
2615    return Element.select(element, '*');
2616  }
2617
2618  function firstDescendant(element) {
2619    element = $$$(element).firstChild;
2620    while (element && element.nodeType !== Node.ELEMENT_NODE)
2621      element = element.nextSibling;
2622
2623    return $$$(element);
2624  }
2625
2626  function immediateDescendants(element) {
2627    var results = [], child = $$$(element).firstChild;
2628
2629    while (child) {
2630      if (child.nodeType === Node.ELEMENT_NODE)
2631        results.push(Element.extend(child));
2632
2633      child = child.nextSibling;
2634    }
2635
2636    return results;
2637  }
2638
2639  function previousSiblings(element) {
2640    return recursivelyCollect(element, 'previousSibling');
2641  }
2642
2643  function nextSiblings(element) {
2644    return recursivelyCollect(element, 'nextSibling');
2645  }
2646
2647  function siblings(element) {
2648    element = $$$(element);
2649    var previous = previousSiblings(element),
2650     next = nextSiblings(element);
2651    return previous.reverse().concat(next);
2652  }
2653
2654  function match(element, selector) {
2655    element = $$$(element);
2656
2657    if (Object.isString(selector))
2658      return Prototype.Selector.match(element, selector);
2659
2660    return selector.match(element);
2661  }
2662
2663
2664  function _recursivelyFind(element, property, expression, index) {
2665    element = $$$(element), expression = expression || 0, index = index || 0;
2666    if (Object.isNumber(expression)) {
2667      index = expression, expression = null;
2668    }
2669
2670    while (element = element[property]) {
2671      if (element.nodeType !== 1) continue;
2672      if (expression && !Prototype.Selector.match(element, expression))
2673        continue;
2674      if (--index >= 0) continue;
2675
2676      return Element.extend(element);
2677    }
2678  }
2679
2680
2681  function up(element, expression, index) {
2682    element = $$$(element);
2683
2684    if (arguments.length === 1) return $$$(element.parentNode);
2685    return _recursivelyFind(element, 'parentNode', expression, index);
2686  }
2687
2688  function down(element, expression, index) {
2689    if (arguments.length === 1) return firstDescendant(element);
2690    element = $$$(element), expression = expression || 0, index = index || 0;
2691
2692    if (Object.isNumber(expression))
2693      index = expression, expression = '*';
2694
2695    var node = Prototype.Selector.select(expression, element)[index];
2696    return Element.extend(node);
2697  }
2698
2699  function previous(element, expression, index) {
2700    return _recursivelyFind(element, 'previousSibling', expression, index);
2701  }
2702
2703  function next(element, expression, index) {
2704    return _recursivelyFind(element, 'nextSibling', expression, index);
2705  }
2706
2707  function select(element) {
2708    element = $$$(element);
2709    var expressions = SLICE.call(arguments, 1).join(', ');
2710    return Prototype.Selector.select(expressions, element);
2711  }
2712
2713  function adjacent(element) {
2714    element = $$$(element);
2715    var expressions = SLICE.call(arguments, 1).join(', ');
2716    var siblings = Element.siblings(element), results = [];
2717    for (var i = 0, sibling; sibling = siblings[i]; i++) {
2718      if (Prototype.Selector.match(sibling, expressions))
2719        results.push(sibling);
2720    }
2721
2722    return results;
2723  }
2724
2725  function descendantOf_DOM(element, ancestor) {
2726    element = $$$(element), ancestor = $$$(ancestor);
2727    if (!element || !ancestor) return false;
2728    while (element = element.parentNode)
2729      if (element === ancestor) return true;
2730    return false;
2731  }
2732
2733  function descendantOf_contains(element, ancestor) {
2734    element = $$$(element), ancestor = $$$(ancestor);
2735    if (!element || !ancestor) return false;
2736    if (!ancestor.contains) return descendantOf_DOM(element, ancestor);
2737    return ancestor.contains(element) && ancestor !== element;
2738  }
2739
2740  function descendantOf_compareDocumentPosition(element, ancestor) {
2741    element = $$$(element), ancestor = $$$(ancestor);
2742    if (!element || !ancestor) return false;
2743    return (element.compareDocumentPosition(ancestor) & 8) === 8;
2744  }
2745
2746  var descendantOf;
2747  if (DIV.compareDocumentPosition) {
2748    descendantOf = descendantOf_compareDocumentPosition;
2749  } else if (DIV.contains) {
2750    descendantOf = descendantOf_contains;
2751  } else {
2752    descendantOf = descendantOf_DOM;
2753  }
2754
2755
2756  Object.extend(methods, {
2757    recursivelyCollect:   recursivelyCollect,
2758    ancestors:            ancestors,
2759    descendants:          descendants,
2760    firstDescendant:      firstDescendant,
2761    immediateDescendants: immediateDescendants,
2762    previousSiblings:     previousSiblings,
2763    nextSiblings:         nextSiblings,
2764    siblings:             siblings,
2765    match:                match,
2766    up:                   up,
2767    down:                 down,
2768    previous:             previous,
2769    next:                 next,
2770    select:               select,
2771    adjacent:             adjacent,
2772    descendantOf:         descendantOf,
2773
2774    getElementsBySelector: select,
2775
2776    childElements:         immediateDescendants
2777  });
2778
2779
2780  var idCounter = 1;
2781  function identify(element) {
2782    element = $$$(element);
2783    var id = Element.readAttribute(element, 'id');
2784    if (id) return id;
2785
2786    do { id = 'anonymous_element_' + idCounter++ } while ($$$(id));
2787
2788    Element.writeAttribute(element, 'id', id);
2789    return id;
2790  }
2791
2792
2793  function readAttribute(element, name) {
2794    return $$$(element).getAttribute(name);
2795  }
2796
2797  function readAttribute_IE(element, name) {
2798    element = $$$(element);
2799
2800    var table = ATTRIBUTE_TRANSLATIONS.read;
2801    if (table.values[name])
2802      return table.values[name](element, name);
2803
2804    if (table.names[name]) name = table.names[name];
2805
2806    if (name.include(':')) {
2807      if (!element.attributes || !element.attributes[name]) return null;
2808      return element.attributes[name].value;
2809    }
2810
2811    return element.getAttribute(name);
2812  }
2813
2814  function readAttribute_Opera(element, name) {
2815    if (name === 'title') return element.title;
2816    return element.getAttribute(name);
2817  }
2818
2819  var PROBLEMATIC_ATTRIBUTE_READING = (function() {
2820    DIV.setAttribute('onclick', []);
2821    var value = DIV.getAttribute('onclick');
2822    var isFunction = Object.isArray(value);
2823    DIV.removeAttribute('onclick');
2824    return isFunction;
2825  })();
2826
2827  if (PROBLEMATIC_ATTRIBUTE_READING) {
2828    readAttribute = readAttribute_IE;
2829  } else if (Prototype.Browser.Opera) {
2830    readAttribute = readAttribute_Opera;
2831  }
2832
2833
2834  function writeAttribute(element, name, value) {
2835    element = $$$(element);
2836    var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;
2837
2838    if (typeof name === 'object') {
2839      attributes = name;
2840    } else {
2841      attributes[name] = Object.isUndefined(value) ? true : value;
2842    }
2843
2844    for (var attr in attributes) {
2845      name = table.names[attr] || attr;
2846      value = attributes[attr];
2847      if (table.values[attr]) {
2848        value = table.values[attr](element, value);
2849        if (Object.isUndefined(value)) continue;
2850      }
2851      if (value === false || value === null)
2852        element.removeAttribute(name);
2853      else if (value === true)
2854        element.setAttribute(name, name);
2855      else element.setAttribute(name, value);
2856    }
2857
2858    return element;
2859  }
2860
2861  var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () {
2862    if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) {
2863      return false;
2864    }
2865    var checkbox = document.createElement('<input type="checkbox">');
2866    checkbox.checked = true;
2867    var node = checkbox.getAttributeNode('checked');
2868    return !node || !node.specified;
2869  })();
2870
2871  function hasAttribute(element, attribute) {
2872    attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;
2873    var node = $$$(element).getAttributeNode(attribute);
2874    return !!(node && node.specified);
2875  }
2876
2877  function hasAttribute_IE(element, attribute) {
2878    if (attribute === 'checked') {
2879      return element.checked;
2880    }
2881    return hasAttribute(element, attribute);
2882  }
2883
2884  GLOBAL.Element.Methods.Simulated.hasAttribute =
2885   PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ?
2886   hasAttribute_IE : hasAttribute;
2887
2888  function classNames(element) {
2889    return new Element.ClassNames(element);
2890  }
2891
2892  var regExpCache = {};
2893  function getRegExpForClassName(className) {
2894    if (regExpCache[className]) return regExpCache[className];
2895
2896    var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
2897    regExpCache[className] = re;
2898    return re;
2899  }
2900
2901  function hasClassName(element, className) {
2902    if (!(element = $$$(element))) return;
2903
2904    var elementClassName = element.className;
2905
2906    if (elementClassName.length === 0) return false;
2907    if (elementClassName === className) return true;
2908
2909    return getRegExpForClassName(className).test(elementClassName);
2910  }
2911
2912  function addClassName(element, className) {
2913    if (!(element = $$$(element))) return;
2914
2915    if (!hasClassName(element, className))
2916      element.className += (element.className ? ' ' : '') + className;
2917
2918    return element;
2919  }
2920
2921  function removeClassName(element, className) {
2922    if (!(element = $$$(element))) return;
2923
2924    element.className = element.className.replace(
2925     getRegExpForClassName(className), ' ').strip();
2926
2927    return element;
2928  }
2929
2930  function toggleClassName(element, className, bool) {
2931    if (!(element = $$$(element))) return;
2932
2933    if (Object.isUndefined(bool))
2934      bool = !hasClassName(element, className);
2935
2936    var method = Element[bool ? 'addClassName' : 'removeClassName'];
2937    return method(element, className);
2938  }
2939
2940  var ATTRIBUTE_TRANSLATIONS = {};
2941
2942  var classProp = 'className', forProp = 'for';
2943
2944  DIV.setAttribute(classProp, 'x');
2945  if (DIV.className !== 'x') {
2946    DIV.setAttribute('class', 'x');
2947    if (DIV.className === 'x')
2948      classProp = 'class';
2949  }
2950
2951  var LABEL = document.createElement('label');
2952  LABEL.setAttribute(forProp, 'x');
2953  if (LABEL.htmlFor !== 'x') {
2954    LABEL.setAttribute('htmlFor', 'x');
2955    if (LABEL.htmlFor === 'x')
2956      forProp = 'htmlFor';
2957  }
2958  LABEL = null;
2959
2960  function _getAttr(element, attribute) {
2961    return element.getAttribute(attribute);
2962  }
2963
2964  function _getAttr2(element, attribute) {
2965    return element.getAttribute(attribute, 2);
2966  }
2967
2968  function _getAttrNode(element, attribute) {
2969    var node = element.getAttributeNode(attribute);
2970    return node ? node.value : '';
2971  }
2972
2973  function _getFlag(element, attribute) {
2974    return $$$(element).hasAttribute(attribute) ? attribute : null;
2975  }
2976
2977  DIV.onclick = Prototype.emptyFunction;
2978  var onclickValue = DIV.getAttribute('onclick');
2979
2980  var _getEv;
2981
2982  if (String(onclickValue).indexOf('{') > -1) {
2983    _getEv = function(element, attribute) {
2984      var value = element.getAttribute(attribute);
2985      if (!value) return null;
2986      value = value.toString();
2987      value = value.split('{')[1];
2988      value = value.split('}')[0];
2989      return value.strip();
2990    };
2991  }
2992  else if (onclickValue === '') {
2993    _getEv = function(element, attribute) {
2994      var value = element.getAttribute(attribute);
2995      if (!value) return null;
2996      return value.strip();
2997    };
2998  }
2999
3000  ATTRIBUTE_TRANSLATIONS.read = {
3001    names: {
3002      'class':     classProp,
3003      'className': classProp,
3004      'for':       forProp,
3005      'htmlFor':   forProp
3006    },
3007
3008    values: {
3009      style: function(element) {
3010        return element.style.cssText.toLowerCase();
3011      },
3012      title: function(element) {
3013        return element.title;
3014      }
3015    }
3016  };
3017
3018  ATTRIBUTE_TRANSLATIONS.write = {
3019    names: {
3020      className:   'class',
3021      htmlFor:     'for',
3022      cellpadding: 'cellPadding',
3023      cellspacing: 'cellSpacing'
3024    },
3025
3026    values: {
3027      checked: function(element, value) {
3028        value = !!value;
3029        element.checked = value;
3030        return value ? 'checked' : null;
3031      },
3032
3033      style: function(element, value) {
3034        element.style.cssText = value ? value : '';
3035      }
3036    }
3037  };
3038
3039  ATTRIBUTE_TRANSLATIONS.has = { names: {} };
3040
3041  Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,
3042   ATTRIBUTE_TRANSLATIONS.read.names);
3043
3044  var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +
3045   'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');
3046
3047  for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {
3048    ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;
3049    ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()]   = attr;
3050  }
3051
3052  Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {
3053    href:        _getAttr2,
3054    src:         _getAttr2,
3055    type:        _getAttr,
3056    action:      _getAttrNode,
3057    disabled:    _getFlag,
3058    checked:     _getFlag,
3059    readonly:    _getFlag,
3060    multiple:    _getFlag,
3061    onload:      _getEv,
3062    onunload:    _getEv,
3063    onclick:     _getEv,
3064    ondblclick:  _getEv,
3065    onmousedown: _getEv,
3066    onmouseup:   _getEv,
3067    onmouseover: _getEv,
3068    onmousemove: _getEv,
3069    onmouseout:  _getEv,
3070    onfocus:     _getEv,
3071    onblur:      _getEv,
3072    onkeypress:  _getEv,
3073    onkeydown:   _getEv,
3074    onkeyup:     _getEv,
3075    onsubmit:    _getEv,
3076    onreset:     _getEv,
3077    onselect:    _getEv,
3078    onchange:    _getEv
3079  });
3080
3081
3082  Object.extend(methods, {
3083    identify:        identify,
3084    readAttribute:   readAttribute,
3085    writeAttribute:  writeAttribute,
3086    classNames:      classNames,
3087    hasClassName:    hasClassName,
3088    addClassName:    addClassName,
3089    removeClassName: removeClassName,
3090    toggleClassName: toggleClassName
3091  });
3092
3093
3094  function normalizeStyleName(style) {
3095    if (style === 'float' || style === 'styleFloat')
3096      return 'cssFloat';
3097    return style.camelize();
3098  }
3099
3100  function normalizeStyleName_IE(style) {
3101    if (style === 'float' || style === 'cssFloat')
3102      return 'styleFloat';
3103    return style.camelize();
3104  }
3105
3106  function setStyle(element, styles) {
3107    element = $$$(element);
3108    var elementStyle = element.style, match;
3109
3110    if (Object.isString(styles)) {
3111      elementStyle.cssText += ';' + styles;
3112      if (styles.include('opacity')) {
3113        var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1];
3114        Element.setOpacity(element, opacity);
3115      }
3116      return element;
3117    }
3118
3119    for (var property in styles) {
3120      if (property === 'opacity') {
3121        Element.setOpacity(element, styles[property]);
3122      } else {
3123        var value = styles[property];
3124        if (property === 'float' || property === 'cssFloat') {
3125          property = Object.isUndefined(elementStyle.styleFloat) ?
3126           'cssFloat' : 'styleFloat';
3127        }
3128        elementStyle[property] = value;
3129      }
3130    }
3131
3132    return element;
3133  }
3134
3135
3136  function getStyle(element, style) {
3137    element = $$$(element);
3138    style = normalizeStyleName(style);
3139
3140    var value = element.style[style];
3141    if (!value || value === 'auto') {
3142      var css = document.defaultView.getComputedStyle(element, null);
3143      value = css ? css[style] : null;
3144    }
3145
3146    if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3147    return value === 'auto' ? null : value;
3148  }
3149
3150  function getStyle_Opera(element, style) {
3151    switch (style) {
3152      case 'height': case 'width':
3153        if (!Element.visible(element)) return null;
3154
3155        var dim = parseInt(getStyle(element, style), 10);
3156
3157        if (dim !== element['offset' + style.capitalize()])
3158          return dim + 'px';
3159
3160        return Element.measure(element, style);
3161
3162      default: return getStyle(element, style);
3163    }
3164  }
3165
3166  function getStyle_IE(element, style) {
3167    element = $$$(element);
3168    style = normalizeStyleName_IE(style);
3169
3170    var value = element.style[style];
3171    if (!value && element.currentStyle) {
3172      value = element.currentStyle[style];
3173    }
3174
3175    if (style === 'opacity') {
3176      if (!STANDARD_CSS_OPACITY_SUPPORTED)
3177        return getOpacity_IE(element);
3178      else return value ? parseFloat(value) : 1.0;
3179    }
3180
3181    if (value === 'auto') {
3182      if ((style === 'width' || style === 'height') && Element.visible(element))
3183        return Element.measure(element, style) + 'px';
3184      return null;
3185    }
3186
3187    return value;
3188  }
3189
3190  function stripAlphaFromFilter_IE(filter) {
3191    return (filter || '').replace(/alpha\([^\)]*\)/gi, '');
3192  }
3193
3194  function hasLayout_IE(element) {
3195    if (!element.currentStyle || !element.currentStyle.hasLayout)
3196      element.style.zoom = 1;
3197    return element;
3198  }
3199
3200  var STANDARD_CSS_OPACITY_SUPPORTED = (function() {
3201    DIV.style.cssText = "opacity:.55";
3202    return /^0.55/.test(DIV.style.opacity);
3203  })();
3204
3205  function setOpacity(element, value) {
3206    element = $$$(element);
3207    if (value == 1 || value === '') value = '';
3208    else if (value < 0.00001) value = 0;
3209    element.style.opacity = value;
3210    return element;
3211  }
3212
3213  function setOpacity_IE(element, value) {
3214    if (STANDARD_CSS_OPACITY_SUPPORTED)
3215      return setOpacity(element, value);
3216
3217    element = hasLayout_IE($$$(element));
3218    var filter = Element.getStyle(element, 'filter'),
3219     style = element.style;
3220
3221    if (value == 1 || value === '') {
3222      filter = stripAlphaFromFilter_IE(filter);
3223      if (filter) style.filter = filter;
3224      else style.removeAttribute('filter');
3225      return element;
3226    }
3227
3228    if (value < 0.00001) value = 0;
3229
3230    style.filter = stripAlphaFromFilter_IE(filter) +
3231     ' alpha(opacity=' + (value * 100) + ')';
3232
3233    return element;
3234  }
3235
3236
3237  function getOpacity(element) {
3238    return Element.getStyle(element, 'opacity');
3239  }
3240
3241  function getOpacity_IE(element) {
3242    if (STANDARD_CSS_OPACITY_SUPPORTED)
3243      return getOpacity(element);
3244
3245    var filter = Element.getStyle(element, 'filter');
3246    if (filter.length === 0) return 1.0;
3247    var match = (filter || '').match(/alpha\(opacity=(.*)\)/i);
3248    if (match && match[1]) return parseFloat(match[1]) / 100;
3249    return 1.0;
3250  }
3251
3252
3253  Object.extend(methods, {
3254    setStyle:   setStyle,
3255    getStyle:   getStyle,
3256    setOpacity: setOpacity,
3257    getOpacity: getOpacity
3258  });
3259
3260  if ('styleFloat' in DIV.style) {
3261    methods.getStyle = getStyle_IE;
3262    methods.setOpacity = setOpacity_IE;
3263    methods.getOpacity = getOpacity_IE;
3264  }
3265
3266  var UID = 0;
3267
3268  GLOBAL.Element.Storage = { UID: 1 };
3269
3270  function getUniqueElementID(element) {
3271    if (element === window) return 0;
3272
3273    if (typeof element._prototypeUID === 'undefined')
3274      element._prototypeUID = Element.Storage.UID++;
3275    return element._prototypeUID;
3276  }
3277
3278  function getUniqueElementID_IE(element) {
3279    if (element === window) return 0;
3280    if (element == document) return 1;
3281    return element.uniqueID;
3282  }
3283
3284  var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);
3285  if (HAS_UNIQUE_ID_PROPERTY)
3286    getUniqueElementID = getUniqueElementID_IE;
3287
3288  function getStorage(element) {
3289    if (!(element = $$$(element))) return;
3290
3291    var uid = getUniqueElementID(element);
3292
3293    if (!Element.Storage[uid])
3294      Element.Storage[uid] = $H();
3295
3296    return Element.Storage[uid];
3297  }
3298
3299  function store(element, key, value) {
3300    if (!(element = $$$(element))) return;
3301    var storage = getStorage(element);
3302    if (arguments.length === 2) {
3303      storage.update(key);
3304    } else {
3305      storage.set(key, value);
3306    }
3307    return element;
3308  }
3309
3310  function retrieve(element, key, defaultValue) {
3311    if (!(element = $$$(element))) return;
3312    var storage = getStorage(element), value = storage.get(key);
3313
3314    if (Object.isUndefined(value)) {
3315      storage.set(key, defaultValue);
3316      value = defaultValue;
3317    }
3318
3319    return value;
3320  }
3321
3322
3323  Object.extend(methods, {
3324    getStorage: getStorage,
3325    store:      store,
3326    retrieve:   retrieve
3327  });
3328
3329
3330  var Methods = {}, ByTag = Element.Methods.ByTag,
3331   F = Prototype.BrowserFeatures;
3332
3333  if (!F.ElementExtensions && ('__proto__' in DIV)) {
3334    GLOBAL.HTMLElement = {};
3335    GLOBAL.HTMLElement.prototype = DIV['__proto__'];
3336    F.ElementExtensions = true;
3337  }
3338
3339  function checkElementPrototypeDeficiency(tagName) {
3340    if (typeof window.Element === 'undefined') return false;
3341    if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false;
3342    var proto = window.Element.prototype;
3343    if (proto) {
3344      var id = '_' + (Math.random() + '').slice(2),
3345       el = document.createElement(tagName);
3346      proto[id] = 'x';
3347      var isBuggy = (el[id] !== 'x');
3348      delete proto[id];
3349      el = null;
3350      return isBuggy;
3351    }
3352
3353    return false;
3354  }
3355
3356  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =
3357   checkElementPrototypeDeficiency('object');
3358
3359  function extendElementWith(element, methods) {
3360    for (var property in methods) {
3361      var value = methods[property];
3362      if (Object.isFunction(value) && !(property in element))
3363        element[property] = value.methodize();
3364    }
3365  }
3366
3367  var EXTENDED = {};
3368  function elementIsExtended(element) {
3369    var uid = getUniqueElementID(element);
3370    return (uid in EXTENDED);
3371  }
3372
3373  function extend(element) {
3374    if (!element || elementIsExtended(element)) return element;
3375    if (element.nodeType !== Node.ELEMENT_NODE || element == window)
3376      return element;
3377
3378    var methods = Object.clone(Methods),
3379     tagName = element.tagName.toUpperCase();
3380
3381    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
3382
3383    extendElementWith(element, methods);
3384    EXTENDED[getUniqueElementID(element)] = true;
3385    return element;
3386  }
3387
3388  function extend_IE8(element) {
3389    if (!element || elementIsExtended(element)) return element;
3390
3391    var t = element.tagName;
3392    if (t && (/^(?:object|applet|embed)$/i.test(t))) {
3393      extendElementWith(element, Element.Methods);
3394      extendElementWith(element, Element.Methods.Simulated);
3395      extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
3396    }
3397
3398    return element;
3399  }
3400
3401  if (F.SpecificElementExtensions) {
3402    extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;
3403  }
3404
3405  function addMethodsToTagName(tagName, methods) {
3406    tagName = tagName.toUpperCase();
3407    if (!ByTag[tagName]) ByTag[tagName] = {};
3408    Object.extend(ByTag[tagName], methods);
3409  }
3410
3411  function mergeMethods(destination, methods, onlyIfAbsent) {
3412    if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;
3413    for (var property in methods) {
3414      var value = methods[property];
3415      if (!Object.isFunction(value)) continue;
3416      if (!onlyIfAbsent || !(property in destination))
3417        destination[property] = value.methodize();
3418    }
3419  }
3420
3421  function findDOMClass(tagName) {
3422    var klass;
3423    var trans = {
3424      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3425      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3426      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3427      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3428      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3429      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3430      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3431      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3432      "FrameSet", "IFRAME": "IFrame"
3433    };
3434    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3435    if (window[klass]) return window[klass];
3436    klass = 'HTML' + tagName + 'Element';
3437    if (window[klass]) return window[klass];
3438    klass = 'HTML' + tagName.capitalize() + 'Element';
3439    if (window[klass]) return window[klass];
3440
3441    var element = document.createElement(tagName),
3442     proto = element['__proto__'] || element.constructor.prototype;
3443
3444    element = null;
3445    return proto;
3446  }
3447
3448  function addMethods(methods) {
3449    if (arguments.length === 0) addFormMethods();
3450
3451    if (arguments.length === 2) {
3452      var tagName = methods;
3453      methods = arguments[1];
3454    }
3455
3456    if (!tagName) {
3457      Object.extend(Element.Methods, methods || {});
3458    } else {
3459      if (Object.isArray(tagName)) {
3460        for (var i = 0, tag; tag = tagName[i]; i++)
3461          addMethodsToTagName(tag, methods);
3462      } else {
3463        addMethodsToTagName(tagName, methods);
3464      }
3465    }
3466
3467    var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
3468     Element.prototype;
3469
3470    if (F.ElementExtensions) {
3471      mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
3472      mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
3473    }
3474
3475    if (F.SpecificElementExtensions) {
3476      for (var tag in Element.Methods.ByTag) {
3477        var klass = findDOMClass(tag);
3478        if (Object.isUndefined(klass)) continue;
3479        mergeMethods(klass.prototype, ByTag[tag]);
3480      }
3481    }
3482
3483    Object.extend(Element, Element.Methods);
3484    Object.extend(Element, Element.Methods.Simulated);
3485    delete Element.ByTag;
3486    delete Element.Simulated;
3487
3488    Element.extend.refresh();
3489
3490    ELEMENT_CACHE = {};
3491  }
3492
3493  Object.extend(GLOBAL.Element, {
3494    extend:     extend,
3495    addMethods: addMethods
3496  });
3497
3498  if (extend === Prototype.K) {
3499    GLOBAL.Element.extend.refresh = Prototype.emptyFunction;
3500  } else {
3501    GLOBAL.Element.extend.refresh = function() {
3502      if (Prototype.BrowserFeatures.ElementExtensions) return;
3503      Object.extend(Methods, Element.Methods);
3504      Object.extend(Methods, Element.Methods.Simulated);
3505
3506      EXTENDED = {};
3507    };
3508  }
3509
3510  function addFormMethods() {
3511    Object.extend(Form, Form.Methods);
3512    Object.extend(Form.Element, Form.Element.Methods);
3513    Object.extend(Element.Methods.ByTag, {
3514      "FORM":     Object.clone(Form.Methods),
3515      "INPUT":    Object.clone(Form.Element.Methods),
3516      "SELECT":   Object.clone(Form.Element.Methods),
3517      "TEXTAREA": Object.clone(Form.Element.Methods),
3518      "BUTTON":   Object.clone(Form.Element.Methods)
3519    });
3520  }
3521
3522  Element.addMethods(methods);
3523
3524  function destroyCache_IE() {
3525    DIV = null;
3526    ELEMENT_CACHE = null;
3527  }
3528
3529  if (window.attachEvent)
3530    window.attachEvent('onunload', destroyCache_IE);
3531
3532})(this);
3533(function() {
3534
3535  function toDecimal(pctString) {
3536    var match = pctString.match(/^(\d+)%?$/i);
3537    if (!match) return null;
3538    return (Number(match[1]) / 100);
3539  }
3540
3541  function getRawStyle(element, style) {
3542    element = $$$(element);
3543
3544    var value = element.style[style];
3545    if (!value || value === 'auto') {
3546      var css = document.defaultView.getComputedStyle(element, null);
3547      value = css ? css[style] : null;
3548    }
3549
3550    if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3551    return value === 'auto' ? null : value;
3552  }
3553
3554  function getRawStyle_IE(element, style) {
3555    var value = element.style[style];
3556    if (!value && element.currentStyle) {
3557      value = element.currentStyle[style];
3558    }
3559    return value;
3560  }
3561
3562  function getContentWidth(element, context) {
3563    var boxWidth = element.offsetWidth;
3564
3565    var bl = getPixelValue(element, 'borderLeftWidth',  context) || 0;
3566    var br = getPixelValue(element, 'borderRightWidth', context) || 0;
3567    var pl = getPixelValue(element, 'paddingLeft',      context) || 0;
3568    var pr = getPixelValue(element, 'paddingRight',     context) || 0;
3569
3570    return boxWidth - bl - br - pl - pr;
3571  }
3572
3573  if (!Object.isUndefined(document.documentElement.currentStyle) && !Prototype.Browser.Opera) {
3574    getRawStyle = getRawStyle_IE;
3575  }
3576
3577
3578  function getPixelValue(value, property, context) {
3579    var element = null;
3580    if (Object.isElement(value)) {
3581      element = value;
3582      value = getRawStyle(element, property);
3583    }
3584
3585    if (value === null || Object.isUndefined(value)) {
3586      return null;
3587    }
3588
3589    if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
3590      return window.parseFloat(value);
3591    }
3592
3593    var isPercentage = value.include('%'), isViewport = (context === document.viewport);
3594
3595    if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
3596      var style = element.style.left, rStyle = element.runtimeStyle.left;
3597      element.runtimeStyle.left = element.currentStyle.left;
3598      element.style.left = value || 0;
3599      value = element.style.pixelLeft;
3600      element.style.left = style;
3601      element.runtimeStyle.left = rStyle;
3602
3603      return value;
3604    }
3605
3606    if (element && isPercentage) {
3607      context = context || element.parentNode;
3608      var decimal = toDecimal(value), whole = null;
3609
3610      var isHorizontal = property.include('left') || property.include('right') ||
3611       property.include('width');
3612
3613      var isVertical   = property.include('top') || property.include('bottom') ||
3614        property.include('height');
3615
3616      if (context === document.viewport) {
3617        if (isHorizontal) {
3618          whole = document.viewport.getWidth();
3619        } else if (isVertical) {
3620          whole = document.viewport.getHeight();
3621        }
3622      } else {
3623        if (isHorizontal) {
3624          whole = $$$(context).measure('width');
3625        } else if (isVertical) {
3626          whole = $$$(context).measure('height');
3627        }
3628      }
3629
3630      return (whole === null) ? 0 : whole * decimal;
3631    }
3632
3633    return 0;
3634  }
3635
3636  function toCSSPixels(number) {
3637    if (Object.isString(number) && number.endsWith('px'))
3638      return number;
3639    return number + 'px';
3640  }
3641
3642  function isDisplayed(element) {
3643    while (element && element.parentNode) {
3644      var display = element.getStyle('display');
3645      if (display === 'none') {
3646        return false;
3647      }
3648      element = $$$(element.parentNode);
3649    }
3650    return true;
3651  }
3652
3653  var hasLayout = Prototype.K;
3654  if ('currentStyle' in document.documentElement) {
3655    hasLayout = function(element) {
3656      if (!element.currentStyle.hasLayout) {
3657        element.style.zoom = 1;
3658      }
3659      return element;
3660    };
3661  }
3662
3663  function cssNameFor(key) {
3664    if (key.include('border')) key = key + '-width';
3665    return key.camelize();
3666  }
3667
3668  Element.Layout = Class.create(Hash, {
3669    initialize: function($super, element, preCompute) {
3670      $super();
3671      this.element = $$$(element);
3672
3673      Element.Layout.PROPERTIES.each( function(property) {
3674        this._set(property, null);
3675      }, this);
3676
3677      if (preCompute) {
3678        this._preComputing = true;
3679        this._begin();
3680        Element.Layout.PROPERTIES.each( this._compute, this );
3681        this._end();
3682        this._preComputing = false;
3683      }
3684    },
3685
3686    _set: function(property, value) {
3687      return Hash.prototype.set.call(this, property, value);
3688    },
3689
3690    set: function(property, value) {
3691      throw "Properties of Element.Layout are read-only.";
3692    },
3693
3694    get: function($super, property) {
3695      var value = $super(property);
3696      return value === null ? this._compute(property) : value;
3697    },
3698
3699    _begin: function() {
3700      if (this._isPrepared()) return;
3701
3702      var element = this.element;
3703      if (isDisplayed(element)) {
3704        this._setPrepared(true);
3705        return;
3706      }
3707
3708
3709      var originalStyles = {
3710        position:   element.style.position   || '',
3711        width:      element.style.width      || '',
3712        visibility: element.style.visibility || '',
3713        display:    element.style.display    || ''
3714      };
3715
3716      element.store('prototype_original_styles', originalStyles);
3717
3718      var position = getRawStyle(element, 'position'), width = element.offsetWidth;
3719
3720      if (width === 0 || width === null) {
3721        element.style.display = 'block';
3722        width = element.offsetWidth;
3723      }
3724
3725      var context = (position === 'fixed') ? document.viewport :
3726       element.parentNode;
3727
3728      var tempStyles = {
3729        visibility: 'hidden',
3730        display:    'block'
3731      };
3732
3733      if (position !== 'fixed') tempStyles.position = 'absolute';
3734
3735      element.setStyle(tempStyles);
3736
3737      var positionedWidth = element.offsetWidth, newWidth;
3738      if (width && (positionedWidth === width)) {
3739        newWidth = getContentWidth(element, context);
3740      } else if (position === 'absolute' || position === 'fixed') {
3741        newWidth = getContentWidth(element, context);
3742      } else {
3743        var parent = element.parentNode, pLayout = $$$(parent).getLayout();
3744
3745        newWidth = pLayout.get('width') -
3746         this.get('margin-left') -
3747         this.get('border-left') -
3748         this.get('padding-left') -
3749         this.get('padding-right') -
3750         this.get('border-right') -
3751         this.get('margin-right');
3752      }
3753
3754      element.setStyle({ width: newWidth + 'px' });
3755
3756      this._setPrepared(true);
3757    },
3758
3759    _end: function() {
3760      var element = this.element;
3761      var originalStyles = element.retrieve('prototype_original_styles');
3762      element.store('prototype_original_styles', null);
3763      element.setStyle(originalStyles);
3764      this._setPrepared(false);
3765    },
3766
3767    _compute: function(property) {
3768      var COMPUTATIONS = Element.Layout.COMPUTATIONS;
3769      if (!(property in COMPUTATIONS)) {
3770        throw "Property not found.";
3771      }
3772
3773      return this._set(property, COMPUTATIONS[property].call(this, this.element));
3774    },
3775
3776    _isPrepared: function() {
3777      return this.element.retrieve('prototype_element_layout_prepared', false);
3778    },
3779
3780    _setPrepared: function(bool) {
3781      return this.element.store('prototype_element_layout_prepared', bool);
3782    },
3783
3784    toObject: function() {
3785      var args = $A(arguments);
3786      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3787       args.join(' ').split(' ');
3788      var obj = {};
3789      keys.each( function(key) {
3790        if (!Element.Layout.PROPERTIES.include(key)) return;
3791        var value = this.get(key);
3792        if (value != null) obj[key] = value;
3793      }, this);
3794      return obj;
3795    },
3796
3797    toHash: function() {
3798      var obj = this.toObject.apply(this, arguments);
3799      return new Hash(obj);
3800    },
3801
3802    toCSS: function() {
3803      var args = $A(arguments);
3804      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3805       args.join(' ').split(' ');
3806      var css = {};
3807
3808      keys.each( function(key) {
3809        if (!Element.Layout.PROPERTIES.include(key)) return;
3810        if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
3811
3812        var value = this.get(key);
3813        if (value != null) css[cssNameFor(key)] = value + 'px';
3814      }, this);
3815      return css;
3816    },
3817
3818    inspect: function() {
3819      return "#<Element.Layout>";
3820    }
3821  });
3822
3823  Object.extend(Element.Layout, {
3824    PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
3825
3826    COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
3827
3828    COMPUTATIONS: {
3829      'height': function(element) {
3830        if (!this._preComputing) this._begin();
3831
3832        var bHeight = this.get('border-box-height');
3833        if (bHeight <= 0) {
3834          if (!this._preComputing) this._end();
3835          return 0;
3836        }
3837
3838        var bTop = this.get('border-top'),
3839         bBottom = this.get('border-bottom');
3840
3841        var pTop = this.get('padding-top'),
3842         pBottom = this.get('padding-bottom');
3843
3844        if (!this._preComputing) this._end();
3845
3846        return bHeight - bTop - bBottom - pTop - pBottom;
3847      },
3848
3849      'width': function(element) {
3850        if (!this._preComputing) this._begin();
3851
3852        var bWidth = this.get('border-box-width');
3853        if (bWidth <= 0) {
3854          if (!this._preComputing) this._end();
3855          return 0;
3856        }
3857
3858        var bLeft = this.get('border-left'),
3859         bRight = this.get('border-right');
3860
3861        var pLeft = this.get('padding-left'),
3862         pRight = this.get('padding-right');
3863
3864        if (!this._preComputing) this._end();
3865        return bWidth - bLeft - bRight - pLeft - pRight;
3866      },
3867
3868      'padding-box-height': function(element) {
3869        var height = this.get('height'),
3870         pTop = this.get('padding-top'),
3871         pBottom = this.get('padding-bottom');
3872
3873        return height + pTop + pBottom;
3874      },
3875
3876      'padding-box-width': function(element) {
3877        var width = this.get('width'),
3878         pLeft = this.get('padding-left'),
3879         pRight = this.get('padding-right');
3880
3881        return width + pLeft + pRight;
3882      },
3883
3884      'border-box-height': function(element) {
3885        if (!this._preComputing) this._begin();
3886        var height = element.offsetHeight;
3887        if (!this._preComputing) this._end();
3888        return height;
3889      },
3890
3891      'border-box-width': function(element) {
3892        if (!this._preComputing) this._begin();
3893        var width = element.offsetWidth;
3894        if (!this._preComputing) this._end();
3895        return width;
3896      },
3897
3898      'margin-box-height': function(element) {
3899        var bHeight = this.get('border-box-height'),
3900         mTop = this.get('margin-top'),
3901         mBottom = this.get('margin-bottom');
3902
3903        if (bHeight <= 0) return 0;
3904
3905        return bHeight + mTop + mBottom;
3906      },
3907
3908      'margin-box-width': function(element) {
3909        var bWidth = this.get('border-box-width'),
3910         mLeft = this.get('margin-left'),
3911         mRight = this.get('margin-right');
3912
3913        if (bWidth <= 0) return 0;
3914
3915        return bWidth + mLeft + mRight;
3916      },
3917
3918      'top': function(element) {
3919        var offset = element.positionedOffset();
3920        return offset.top;
3921      },
3922
3923      'bottom': function(element) {
3924        var offset = element.positionedOffset(),
3925         parent = element.getOffsetParent(),
3926         pHeight = parent.measure('height');
3927
3928        var mHeight = this.get('border-box-height');
3929
3930        return pHeight - mHeight - offset.top;
3931      },
3932
3933      'left': function(element) {
3934        var offset = element.positionedOffset();
3935        return offset.left;
3936      },
3937
3938      'right': function(element) {
3939        var offset = element.positionedOffset(),
3940         parent = element.getOffsetParent(),
3941         pWidth = parent.measure('width');
3942
3943        var mWidth = this.get('border-box-width');
3944
3945        return pWidth - mWidth - offset.left;
3946      },
3947
3948      'padding-top': function(element) {
3949        return getPixelValue(element, 'paddingTop');
3950      },
3951
3952      'padding-bottom': function(element) {
3953        return getPixelValue(element, 'paddingBottom');
3954      },
3955
3956      'padding-left': function(element) {
3957        return getPixelValue(element, 'paddingLeft');
3958      },
3959
3960      'padding-right': function(element) {
3961        return getPixelValue(element, 'paddingRight');
3962      },
3963
3964      'border-top': function(element) {
3965        return getPixelValue(element, 'borderTopWidth');
3966      },
3967
3968      'border-bottom': function(element) {
3969        return getPixelValue(element, 'borderBottomWidth');
3970      },
3971
3972      'border-left': function(element) {
3973        return getPixelValue(element, 'borderLeftWidth');
3974      },
3975
3976      'border-right': function(element) {
3977        return getPixelValue(element, 'borderRightWidth');
3978      },
3979
3980      'margin-top': function(element) {
3981        return getPixelValue(element, 'marginTop');
3982      },
3983
3984      'margin-bottom': function(element) {
3985        return getPixelValue(element, 'marginBottom');
3986      },
3987
3988      'margin-left': function(element) {
3989        return getPixelValue(element, 'marginLeft');
3990      },
3991
3992      'margin-right': function(element) {
3993        return getPixelValue(element, 'marginRight');
3994      }
3995    }
3996  });
3997
3998  if ('getBoundingClientRect' in document.documentElement) {
3999    Object.extend(Element.Layout.COMPUTATIONS, {
4000      'right': function(element) {
4001        var parent = hasLayout(element.getOffsetParent());
4002        var rect = element.getBoundingClientRect(),
4003         pRect = parent.getBoundingClientRect();
4004
4005        return (pRect.right - rect.right).round();
4006      },
4007
4008      'bottom': function(element) {
4009        var parent = hasLayout(element.getOffsetParent());
4010        var rect = element.getBoundingClientRect(),
4011         pRect = parent.getBoundingClientRect();
4012
4013        return (pRect.bottom - rect.bottom).round();
4014      }
4015    });
4016  }
4017
4018  Element.Offset = Class.create({
4019    initialize: function(left, top) {
4020      this.left = left.round();
4021      this.top  = top.round();
4022
4023      this[0] = this.left;
4024      this[1] = this.top;
4025    },
4026
4027    relativeTo: function(offset) {
4028      return new Element.Offset(
4029        this.left - offset.left,
4030        this.top  - offset.top
4031      );
4032    },
4033
4034    inspect: function() {
4035      return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
4036    },
4037
4038    toString: function() {
4039      return "[#{left}, #{top}]".interpolate(this);
4040    },
4041
4042    toArray: function() {
4043      return [this.left, this.top];
4044    }
4045  });
4046
4047  function getLayout(element, preCompute) {
4048    return new Element.Layout(element, preCompute);
4049  }
4050
4051  function measure(element, property) {
4052    return $$$(element).getLayout().get(property);
4053  }
4054
4055  function getHeight(element) {
4056    return Element.getDimensions(element).height;
4057  }
4058
4059  function getWidth(element) {
4060    return Element.getDimensions(element).width;
4061  }
4062
4063  function getDimensions(element) {
4064    element = $$$(element);
4065    var display = Element.getStyle(element, 'display');
4066
4067    if (display && display !== 'none') {
4068      return { width: element.offsetWidth, height: element.offsetHeight };
4069    }
4070
4071    var style = element.style;
4072    var originalStyles = {
4073      visibility: style.visibility,
4074      position:   style.position,
4075      display:    style.display
4076    };
4077
4078    var newStyles = {
4079      visibility: 'hidden',
4080      display:    'block'
4081    };
4082
4083    if (originalStyles.position !== 'fixed')
4084      newStyles.position = 'absolute';
4085
4086    Element.setStyle(element, newStyles);
4087
4088    var dimensions = {
4089      width:  element.offsetWidth,
4090      height: element.offsetHeight
4091    };
4092
4093    Element.setStyle(element, originalStyles);
4094
4095    return dimensions;
4096  }
4097
4098  function getOffsetParent(element) {
4099    element = $$$(element);
4100
4101    function selfOrBody(element) {
4102      return isHtml(element) ? $$$(document.body) : $$$(element);
4103    }
4104
4105    if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4106      return $$$(document.body);
4107
4108    var isInline = (Element.getStyle(element, 'display') === 'inline');
4109    if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent);
4110
4111    while ((element = element.parentNode) && element !== document.body) {
4112      if (Element.getStyle(element, 'position') !== 'static') {
4113        return selfOrBody(element);
4114      }
4115    }
4116
4117    return $$$(document.body);
4118  }
4119
4120
4121  function cumulativeOffset(element) {
4122    element = $$$(element);
4123    var valueT = 0, valueL = 0;
4124    if (element.parentNode) {
4125      do {
4126        valueT += element.offsetTop  || 0;
4127        valueL += element.offsetLeft || 0;
4128        element = element.offsetParent;
4129      } while (element);
4130    }
4131    return new Element.Offset(valueL, valueT);
4132  }
4133
4134  function positionedOffset(element) {
4135    element = $$$(element);
4136
4137    var layout = element.getLayout();
4138
4139    var valueT = 0, valueL = 0;
4140    do {
4141      valueT += element.offsetTop  || 0;
4142      valueL += element.offsetLeft || 0;
4143      element = element.offsetParent;
4144      if (element) {
4145        if (isBody(element)) break;
4146        var p = Element.getStyle(element, 'position');
4147        if (p !== 'static') break;
4148      }
4149    } while (element);
4150
4151    valueL -= layout.get('margin-left');
4152    valueT -= layout.get('margin-top');
4153
4154    return new Element.Offset(valueL, valueT);
4155  }
4156
4157  function cumulativeScrollOffset(element) {
4158    var valueT = 0, valueL = 0;
4159    do {
4160      if (element === document.body) {
4161        var bodyScrollNode = document.documentElement || document.body.parentNode || document.body;
4162        valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0;
4163        valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0;
4164        break;
4165      } else {
4166        valueT += element.scrollTop  || 0;
4167        valueL += element.scrollLeft || 0;
4168        element = element.parentNode;
4169      }
4170    } while (element);
4171    return new Element.Offset(valueL, valueT);
4172  }
4173
4174  function viewportOffset(forElement) {
4175    var valueT = 0, valueL = 0, docBody = document.body;
4176
4177    forElement = $$$(forElement);
4178    var element = forElement;
4179    do {
4180      valueT += element.offsetTop  || 0;
4181      valueL += element.offsetLeft || 0;
4182      if (element.offsetParent == docBody &&
4183        Element.getStyle(element, 'position') == 'absolute') break;
4184    } while (element = element.offsetParent);
4185
4186    element = forElement;
4187    do {
4188      if (element != docBody) {
4189        valueT -= element.scrollTop  || 0;
4190        valueL -= element.scrollLeft || 0;
4191      }
4192    } while (element = element.parentNode);
4193    return new Element.Offset(valueL, valueT);
4194  }
4195
4196  function absolutize(element) {
4197    element = $$$(element);
4198
4199    if (Element.getStyle(element, 'position') === 'absolute') {
4200      return element;
4201    }
4202
4203    var offsetParent = getOffsetParent(element);
4204    var eOffset = element.viewportOffset(),
4205     pOffset = offsetParent.viewportOffset();
4206
4207    var offset = eOffset.relativeTo(pOffset);
4208    var layout = element.getLayout();
4209
4210    element.store('prototype_absolutize_original_styles', {
4211      position: element.getStyle('position'),
4212      left:     element.getStyle('left'),
4213      top:      element.getStyle('top'),
4214      width:    element.getStyle('width'),
4215      height:   element.getStyle('height')
4216    });
4217
4218    element.setStyle({
4219      position: 'absolute',
4220      top:    offset.top + 'px',
4221      left:   offset.left + 'px',
4222      width:  layout.get('width') + 'px',
4223      height: layout.get('height') + 'px'
4224    });
4225
4226    return element;
4227  }
4228
4229  function relativize(element) {
4230    element = $$$(element);
4231    if (Element.getStyle(element, 'position') === 'relative') {
4232      return element;
4233    }
4234
4235    var originalStyles =
4236     element.retrieve('prototype_absolutize_original_styles');
4237
4238    if (originalStyles) element.setStyle(originalStyles);
4239    return element;
4240  }
4241
4242  function makePositioned(element) {
4243    element = $$$(element);
4244    var position = Element.getStyle(element, 'position'), styles = {};
4245    if (position === 'static' || !position) {
4246      styles.position = 'relative';
4247      if (Prototype.Browser.Opera) {
4248        styles.top  = 0;
4249        styles.left = 0;
4250      }
4251      Element.setStyle(element, styles);
4252      Element.store(element, 'prototype_made_positioned', true);
4253    }
4254    return element;
4255  }
4256
4257  function undoPositioned(element) {
4258    element = $$$(element);
4259    var storage = Element.getStorage(element),
4260     madePositioned = storage.get('prototype_made_positioned');
4261
4262    if (madePositioned) {
4263      storage.unset('prototype_made_positioned');
4264      Element.setStyle(element, {
4265        position: '',
4266        top:      '',
4267        bottom:   '',
4268        left:     '',
4269        right:    ''
4270      });
4271    }
4272    return element;
4273  }
4274
4275  function makeClipping(element) {
4276    element = $$$(element);
4277
4278    var storage = Element.getStorage(element),
4279     madeClipping = storage.get('prototype_made_clipping');
4280
4281    if (Object.isUndefined(madeClipping)) {
4282      var overflow = Element.getStyle(element, 'overflow');
4283      storage.set('prototype_made_clipping', overflow);
4284      if (overflow !== 'hidden')
4285        element.style.overflow = 'hidden';
4286    }
4287
4288    return element;
4289  }
4290
4291  function undoClipping(element) {
4292    element = $$$(element);
4293    var storage = Element.getStorage(element),
4294     overflow = storage.get('prototype_made_clipping');
4295
4296    if (!Object.isUndefined(overflow)) {
4297      storage.unset('prototype_made_clipping');
4298      element.style.overflow = overflow || '';
4299    }
4300
4301    return element;
4302  }
4303
4304  function clonePosition(element, source, options) {
4305    options = Object.extend({
4306      setLeft:    true,
4307      setTop:     true,
4308      setWidth:   true,
4309      setHeight:  true,
4310      offsetTop:  0,
4311      offsetLeft: 0
4312    }, options || {});
4313
4314    var docEl = document.documentElement;
4315
4316    source  = $$$(source);
4317    element = $$$(element);
4318    var p, delta, layout, styles = {};
4319
4320    if (options.setLeft || options.setTop) {
4321      p = Element.viewportOffset(source);
4322      delta = [0, 0];
4323      if (Element.getStyle(element, 'position') === 'absolute') {
4324        var parent = Element.getOffsetParent(element);
4325        if (parent !== document.body) delta = Element.viewportOffset(parent);
4326      }
4327    }
4328
4329    function pageScrollXY() {
4330      var x = 0, y = 0;
4331      if (Object.isNumber(window.pageXOffset)) {
4332        x = window.pageXOffset;
4333        y = window.pageYOffset;
4334      } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
4335        x = document.body.scrollLeft;
4336        y = document.body.scrollTop;
4337      } else if (docEl && (docEl.scrollLeft || docEl.scrollTop)) {
4338        x = docEl.scrollLeft;
4339        y = docEl.scrollTop;
4340      }
4341      return { x: x, y: y };
4342    }
4343
4344    var pageXY = pageScrollXY();
4345
4346
4347    if (options.setWidth || options.setHeight) {
4348      layout = Element.getLayout(source);
4349    }
4350
4351    if (options.setLeft)
4352      styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px';
4353    if (options.setTop)
4354      styles.top  = (p[1] + pageXY.y - delta[1] + options.offsetTop)  + 'px';
4355
4356    var currentLayout = element.getLayout();
4357
4358    if (options.setWidth) {
4359      styles.width = layout.get('width')  + 'px';
4360    }
4361    if (options.setHeight) {
4362      styles.height = layout.get('height') + 'px';
4363    }
4364
4365    return Element.setStyle(element, styles);
4366  }
4367
4368
4369  if (Prototype.Browser.IE) {
4370    getOffsetParent = getOffsetParent.wrap(
4371      function(proceed, element) {
4372        element = $$$(element);
4373
4374        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4375          return $$$(document.body);
4376
4377        var position = element.getStyle('position');
4378        if (position !== 'static') return proceed(element);
4379
4380        element.setStyle({ position: 'relative' });
4381        var value = proceed(element);
4382        element.setStyle({ position: position });
4383        return value;
4384      }
4385    );
4386
4387    positionedOffset = positionedOffset.wrap(function(proceed, element) {
4388      element = $$$(element);
4389      if (!element.parentNode) return new Element.Offset(0, 0);
4390      var position = element.getStyle('position');
4391      if (position !== 'static') return proceed(element);
4392
4393      var offsetParent = element.getOffsetParent();
4394      if (offsetParent && offsetParent.getStyle('position') === 'fixed')
4395        hasLayout(offsetParent);
4396
4397      element.setStyle({ position: 'relative' });
4398      var value = proceed(element);
4399      element.setStyle({ position: position });
4400      return value;
4401    });
4402  } else if (Prototype.Browser.Webkit) {
4403    cumulativeOffset = function(element) {
4404      element = $$$(element);
4405      var valueT = 0, valueL = 0;
4406      do {
4407        valueT += element.offsetTop  || 0;
4408        valueL += element.offsetLeft || 0;
4409        if (element.offsetParent == document.body) {
4410          if (Element.getStyle(element, 'position') == 'absolute') break;
4411        }
4412
4413        element = element.offsetParent;
4414      } while (element);
4415
4416      return new Element.Offset(valueL, valueT);
4417    };
4418  }
4419
4420
4421  Element.addMethods({
4422    getLayout:              getLayout,
4423    measure:                measure,
4424    getWidth:               getWidth,
4425    getHeight:              getHeight,
4426    getDimensions:          getDimensions,
4427    getOffsetParent:        getOffsetParent,
4428    cumulativeOffset:       cumulativeOffset,
4429    positionedOffset:       positionedOffset,
4430    cumulativeScrollOffset: cumulativeScrollOffset,
4431    viewportOffset:         viewportOffset,
4432    absolutize:             absolutize,
4433    relativize:             relativize,
4434    makePositioned:         makePositioned,
4435    undoPositioned:         undoPositioned,
4436    makeClipping:           makeClipping,
4437    undoClipping:           undoClipping,
4438    clonePosition:          clonePosition
4439  });
4440
4441  function isBody(element) {
4442    return element.nodeName.toUpperCase() === 'BODY';
4443  }
4444
4445  function isHtml(element) {
4446    return element.nodeName.toUpperCase() === 'HTML';
4447  }
4448
4449  function isDocument(element) {
4450    return element.nodeType === Node.DOCUMENT_NODE;
4451  }
4452
4453  function isDetached(element) {
4454    return element !== document.body &&
4455     !Element.descendantOf(element, document.body);
4456  }
4457
4458  if ('getBoundingClientRect' in document.documentElement) {
4459    Element.addMethods({
4460      viewportOffset: function(element) {
4461        element = $$$(element);
4462        if (isDetached(element)) return new Element.Offset(0, 0);
4463
4464        var rect = element.getBoundingClientRect(),
4465         docEl = document.documentElement;
4466        return new Element.Offset(rect.left - docEl.clientLeft,
4467         rect.top - docEl.clientTop);
4468      }
4469    });
4470  }
4471
4472
4473})();
4474
4475(function() {
4476
4477  var IS_OLD_OPERA = Prototype.Browser.Opera &&
4478   (window.parseFloat(window.opera.version()) < 9.5);
4479  var ROOT = null;
4480  function getRootElement() {
4481    if (ROOT) return ROOT;
4482    ROOT = IS_OLD_OPERA ? document.body : document.documentElement;
4483    return ROOT;
4484  }
4485
4486  function getDimensions() {
4487    return { width: this.getWidth(), height: this.getHeight() };
4488  }
4489
4490  function getWidth() {
4491    return getRootElement().clientWidth;
4492  }
4493
4494  function getHeight() {
4495    return getRootElement().clientHeight;
4496  }
4497
4498  function getScrollOffsets() {
4499    var x = window.pageXOffset || document.documentElement.scrollLeft ||
4500     document.body.scrollLeft;
4501    var y = window.pageYOffset || document.documentElement.scrollTop ||
4502     document.body.scrollTop;
4503
4504    return new Element.Offset(x, y);
4505  }
4506
4507  document.viewport = {
4508    getDimensions:    getDimensions,
4509    getWidth:         getWidth,
4510    getHeight:        getHeight,
4511    getScrollOffsets: getScrollOffsets
4512  };
4513
4514})();
4515window.$$ = function() {
4516  var expression = $A(arguments).join(', ');
4517  return Prototype.Selector.select(expression, document);
4518};
4519
4520Prototype.Selector = (function() {
4521
4522  function select() {
4523    throw new Error('Method "Prototype.Selector.select" must be defined.');
4524  }
4525
4526  function match() {
4527    throw new Error('Method "Prototype.Selector.match" must be defined.');
4528  }
4529
4530  function find(elements, expression, index) {
4531    index = index || 0;
4532    var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
4533
4534    for (i = 0; i < length; i++) {
4535      if (match(elements[i], expression) && index == matchIndex++) {
4536        return Element.extend(elements[i]);
4537      }
4538    }
4539  }
4540
4541  function extendElements(elements) {
4542    for (var i = 0, length = elements.length; i < length; i++) {
4543      Element.extend(elements[i]);
4544    }
4545    return elements;
4546  }
4547
4548
4549  var K = Prototype.K;
4550
4551  return {
4552    select: select,
4553    match: match,
4554    find: find,
4555    extendElements: (Element.extend === K) ? K : extendElements,
4556    extendElement: Element.extend
4557  };
4558})();
4559Prototype._original_property = window.Sizzle;
4560
4561;(function () {
4562  function fakeDefine(fn) {
4563    Prototype._actual_sizzle = fn();
4564  }
4565  fakeDefine.amd = true;
4566
4567  if (typeof define !== 'undefined' && define.amd) {
4568    Prototype._original_define = define;
4569    Prototype._actual_sizzle = null;
4570    window.define = fakeDefine;
4571  }
4572})();
4573
4574/*!
4575 * Sizzle CSS Selector Engine v1.10.18
4576 * http://sizzlejs.com/
4577 *
4578 * Copyright 2013 jQuery Foundation, Inc. and other contributors
4579 * Released under the MIT license
4580 * http://jquery.org/license
4581 *
4582 * Date: 2014-02-05
4583 */
4584(function( window ) {
4585
4586var i,
4587	support,
4588	Expr,
4589	getText,
4590	isXML,
4591	compile,
4592	select,
4593	outermostContext,
4594	sortInput,
4595	hasDuplicate,
4596
4597	setDocument,
4598	document,
4599	docElem,
4600	documentIsHTML,
4601	rbuggyQSA,
4602	rbuggyMatches,
4603	matches,
4604	contains,
4605
4606	expando = "sizzle" + -(new Date()),
4607	preferredDoc = window.document,
4608	dirruns = 0,
4609	done = 0,
4610	classCache = createCache(),
4611	tokenCache = createCache(),
4612	compilerCache = createCache(),
4613	sortOrder = function( a, b ) {
4614		if ( a === b ) {
4615			hasDuplicate = true;
4616		}
4617		return 0;
4618	},
4619
4620	strundefined = typeof undefined,
4621	MAX_NEGATIVE = 1 << 31,
4622
4623	hasOwn = ({}).hasOwnProperty,
4624	arr = [],
4625	pop = arr.pop,
4626	push_native = arr.push,
4627	push = arr.push,
4628	slice = arr.slice,
4629	indexOf = arr.indexOf || function( elem ) {
4630		var i = 0,
4631			len = this.length;
4632		for ( ; i < len; i++ ) {
4633			if ( this[i] === elem ) {
4634				return i;
4635			}
4636		}
4637		return -1;
4638	},
4639
4640	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
4641
4642
4643	whitespace = "[\\x20\\t\\r\\n\\f]",
4644	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
4645
4646	identifier = characterEncoding.replace( "w", "w#" ),
4647
4648	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
4649		"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
4650
4651	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
4652
4653	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
4654
4655	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
4656	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
4657
4658	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
4659
4660	rpseudo = new RegExp( pseudos ),
4661	ridentifier = new RegExp( "^" + identifier + "$" ),
4662
4663	matchExpr = {
4664		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
4665		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
4666		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
4667		"ATTR": new RegExp( "^" + attributes ),
4668		"PSEUDO": new RegExp( "^" + pseudos ),
4669		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
4670			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
4671			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
4672		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
4673		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
4674			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
4675	},
4676
vendor: 38,600 bytes, lines 4677-6230
4677	rinputs = /^(?:input|select|textarea|button)$/i,
4678	rheader = /^h\d$/i,
4679
4680	rnative = /^[^{]+\{\s*\[native \w/,
4681
4682	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
4683
4684	rsibling = /[+~]/,
4685	rescape = /'|\\/g,
4686
4687	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
4688	funescape = function( _, escaped, escapedWhitespace ) {
4689		var high = "0x" + escaped - 0x10000;
4690		return high !== high || escapedWhitespace ?
4691			escaped :
4692			high < 0 ?
4693				String.fromCharCode( high + 0x10000 ) :
4694				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
4695	};
4696
4697try {
4698	push.apply(
4699		(arr = slice.call( preferredDoc.childNodes )),
4700		preferredDoc.childNodes
4701	);
4702	arr[ preferredDoc.childNodes.length ].nodeType;
4703} catch ( e ) {
4704	push = { apply: arr.length ?
4705
4706		function( target, els ) {
4707			push_native.apply( target, slice.call(els) );
4708		} :
4709
4710		function( target, els ) {
4711			var j = target.length,
4712				i = 0;
4713			while ( (target[j++] = els[i++]) ) {}
4714			target.length = j - 1;
4715		}
4716	};
4717}
4718
4719function Sizzle( selector, context, results, seed ) {
4720	var match, elem, m, nodeType,
4721		i, groups, old, nid, newContext, newSelector;
4722
4723	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
4724		setDocument( context );
4725	}
4726
4727	context = context || document;
4728	results = results || [];
4729
4730	if ( !selector || typeof selector !== "string" ) {
4731		return results;
4732	}
4733
4734	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
4735		return [];
4736	}
4737
4738	if ( documentIsHTML && !seed ) {
4739
4740		if ( (match = rquickExpr.exec( selector )) ) {
4741			if ( (m = match[1]) ) {
4742				if ( nodeType === 9 ) {
4743					elem = context.getElementById( m );
4744					if ( elem && elem.parentNode ) {
4745						if ( elem.id === m ) {
4746							results.push( elem );
4747							return results;
4748						}
4749					} else {
4750						return results;
4751					}
4752				} else {
4753					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
4754						contains( context, elem ) && elem.id === m ) {
4755						results.push( elem );
4756						return results;
4757					}
4758				}
4759
4760			} else if ( match[2] ) {
4761				push.apply( results, context.getElementsByTagName( selector ) );
4762				return results;
4763
4764			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
4765				push.apply( results, context.getElementsByClassName( m ) );
4766				return results;
4767			}
4768		}
4769
4770		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
4771			nid = old = expando;
4772			newContext = context;
4773			newSelector = nodeType === 9 && selector;
4774
4775			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4776				groups = tokenize( selector );
4777
4778				if ( (old = context.getAttribute("id")) ) {
4779					nid = old.replace( rescape, "\\$&" );
4780				} else {
4781					context.setAttribute( "id", nid );
4782				}
4783				nid = "[id='" + nid + "'] ";
4784
4785				i = groups.length;
4786				while ( i-- ) {
4787					groups[i] = nid + toSelector( groups[i] );
4788				}
4789				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
4790				newSelector = groups.join(",");
4791			}
4792
4793			if ( newSelector ) {
4794				try {
4795					push.apply( results,
4796						newContext.querySelectorAll( newSelector )
4797					);
4798					return results;
4799				} catch(qsaError) {
4800				} finally {
4801					if ( !old ) {
4802						context.removeAttribute("id");
4803					}
4804				}
4805			}
4806		}
4807	}
4808
4809	return select( selector.replace( rtrim, "$1" ), context, results, seed );
4810}
4811
4812/**
4813 * Create key-value caches of limited size
4814 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
4815 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
4816 *	deleting the oldest entry
4817 */
4818function createCache() {
4819	var keys = [];
4820
4821	function cache( key, value ) {
4822		if ( keys.push( key + " " ) > Expr.cacheLength ) {
4823			delete cache[ keys.shift() ];
4824		}
4825		return (cache[ key + " " ] = value);
4826	}
4827	return cache;
4828}
4829
4830/**
4831 * Mark a function for special use by Sizzle
4832 * @param {Function} fn The function to mark
4833 */
4834function markFunction( fn ) {
4835	fn[ expando ] = true;
4836	return fn;
4837}
4838
4839/**
4840 * Support testing using an element
4841 * @param {Function} fn Passed the created div and expects a boolean result
4842 */
4843function assert( fn ) {
4844	var div = document.createElement("div");
4845
4846	try {
4847		return !!fn( div );
4848	} catch (e) {
4849		return false;
4850	} finally {
4851		if ( div.parentNode ) {
4852			div.parentNode.removeChild( div );
4853		}
4854		div = null;
4855	}
4856}
4857
4858/**
4859 * Adds the same handler for all of the specified attrs
4860 * @param {String} attrs Pipe-separated list of attributes
4861 * @param {Function} handler The method that will be applied
4862 */
4863function addHandle( attrs, handler ) {
4864	var arr = attrs.split("|"),
4865		i = attrs.length;
4866
4867	while ( i-- ) {
4868		Expr.attrHandle[ arr[i] ] = handler;
4869	}
4870}
4871
4872/**
4873 * Checks document order of two siblings
4874 * @param {Element} a
4875 * @param {Element} b
4876 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
4877 */
4878function siblingCheck( a, b ) {
4879	var cur = b && a,
4880		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
4881			( ~b.sourceIndex || MAX_NEGATIVE ) -
4882			( ~a.sourceIndex || MAX_NEGATIVE );
4883
4884	if ( diff ) {
4885		return diff;
4886	}
4887
4888	if ( cur ) {
4889		while ( (cur = cur.nextSibling) ) {
4890			if ( cur === b ) {
4891				return -1;
4892			}
4893		}
4894	}
4895
4896	return a ? 1 : -1;
4897}
4898
4899/**
4900 * Returns a function to use in pseudos for input types
4901 * @param {String} type
4902 */
4903function createInputPseudo( type ) {
4904	return function( elem ) {
4905		var name = elem.nodeName.toLowerCase();
4906		return name === "input" && elem.type === type;
4907	};
4908}
4909
4910/**
4911 * Returns a function to use in pseudos for buttons
4912 * @param {String} type
4913 */
4914function createButtonPseudo( type ) {
4915	return function( elem ) {
4916		var name = elem.nodeName.toLowerCase();
4917		return (name === "input" || name === "button") && elem.type === type;
4918	};
4919}
4920
4921/**
4922 * Returns a function to use in pseudos for positionals
4923 * @param {Function} fn
4924 */
4925function createPositionalPseudo( fn ) {
4926	return markFunction(function( argument ) {
4927		argument = +argument;
4928		return markFunction(function( seed, matches ) {
4929			var j,
4930				matchIndexes = fn( [], seed.length, argument ),
4931				i = matchIndexes.length;
4932
4933			while ( i-- ) {
4934				if ( seed[ (j = matchIndexes[i]) ] ) {
4935					seed[j] = !(matches[j] = seed[j]);
4936				}
4937			}
4938		});
4939	});
4940}
4941
4942/**
4943 * Checks a node for validity as a Sizzle context
4944 * @param {Element|Object=} context
4945 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
4946 */
4947function testContext( context ) {
4948	return context && typeof context.getElementsByTagName !== strundefined && context;
4949}
4950
4951support = Sizzle.support = {};
4952
4953/**
4954 * Detects XML nodes
4955 * @param {Element|Object} elem An element or a document
4956 * @returns {Boolean} True iff elem is a non-HTML XML node
4957 */
4958isXML = Sizzle.isXML = function( elem ) {
4959	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4960	return documentElement ? documentElement.nodeName !== "HTML" : false;
4961};
4962
4963/**
4964 * Sets document-related variables once based on the current document
4965 * @param {Element|Object} [doc] An element or document object to use to set the document
4966 * @returns {Object} Returns the current document
4967 */
4968setDocument = Sizzle.setDocument = function( node ) {
4969	var hasCompare,
4970		doc = node ? node.ownerDocument || node : preferredDoc,
4971		parent = doc.defaultView;
4972
4973	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4974		return document;
4975	}
4976
4977	document = doc;
4978	docElem = doc.documentElement;
4979
4980	documentIsHTML = !isXML( doc );
4981
4982	if ( parent && parent !== parent.top ) {
4983		if ( parent.addEventListener ) {
4984			parent.addEventListener( "unload", function() {
4985				setDocument();
4986			}, false );
4987		} else if ( parent.attachEvent ) {
4988			parent.attachEvent( "onunload", function() {
4989				setDocument();
4990			});
4991		}
4992	}
4993
4994	/* Attributes
4995	---------------------------------------------------------------------- */
4996
4997	support.attributes = assert(function( div ) {
4998		div.className = "i";
4999		return !div.getAttribute("className");
5000	});
5001
5002	/* getElement(s)By*
5003	---------------------------------------------------------------------- */
5004
5005	support.getElementsByTagName = assert(function( div ) {
5006		div.appendChild( doc.createComment("") );
5007		return !div.getElementsByTagName("*").length;
5008	});
5009
5010	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
5011		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
5012
5013		div.firstChild.className = "i";
5014		return div.getElementsByClassName("i").length === 2;
5015	});
5016
5017	support.getById = assert(function( div ) {
5018		docElem.appendChild( div ).id = expando;
5019		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
5020	});
5021
5022	if ( support.getById ) {
5023		Expr.find["ID"] = function( id, context ) {
5024			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
5025				var m = context.getElementById( id );
5026				return m && m.parentNode ? [m] : [];
5027			}
5028		};
5029		Expr.filter["ID"] = function( id ) {
5030			var attrId = id.replace( runescape, funescape );
5031			return function( elem ) {
5032				return elem.getAttribute("id") === attrId;
5033			};
5034		};
5035	} else {
5036		delete Expr.find["ID"];
5037
5038		Expr.filter["ID"] =  function( id ) {
5039			var attrId = id.replace( runescape, funescape );
5040			return function( elem ) {
5041				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
5042				return node && node.value === attrId;
5043			};
5044		};
5045	}
5046
5047	Expr.find["TAG"] = support.getElementsByTagName ?
5048		function( tag, context ) {
5049			if ( typeof context.getElementsByTagName !== strundefined ) {
5050				return context.getElementsByTagName( tag );
5051			}
5052		} :
5053		function( tag, context ) {
5054			var elem,
5055				tmp = [],
5056				i = 0,
5057				results = context.getElementsByTagName( tag );
5058
5059			if ( tag === "*" ) {
5060				while ( (elem = results[i++]) ) {
5061					if ( elem.nodeType === 1 ) {
5062						tmp.push( elem );
5063					}
5064				}
5065
5066				return tmp;
5067			}
5068			return results;
5069		};
5070
5071	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
5072		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
5073			return context.getElementsByClassName( className );
5074		}
5075	};
5076
5077	/* QSA/matchesSelector
5078	---------------------------------------------------------------------- */
5079
5080
5081	rbuggyMatches = [];
5082
5083	rbuggyQSA = [];
5084
5085	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
5086		assert(function( div ) {
5087			div.innerHTML = "<select t=''><option selected=''></option></select>";
5088
5089			if ( div.querySelectorAll("[t^='']").length ) {
5090				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
5091			}
5092
5093			if ( !div.querySelectorAll("[selected]").length ) {
5094				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
5095			}
5096
5097			if ( !div.querySelectorAll(":checked").length ) {
5098				rbuggyQSA.push(":checked");
5099			}
5100		});
5101
5102		assert(function( div ) {
5103			var input = doc.createElement("input");
5104			input.setAttribute( "type", "hidden" );
5105			div.appendChild( input ).setAttribute( "name", "D" );
5106
5107			if ( div.querySelectorAll("[name=d]").length ) {
5108				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
5109			}
5110
5111			if ( !div.querySelectorAll(":enabled").length ) {
5112				rbuggyQSA.push( ":enabled", ":disabled" );
5113			}
5114
5115			div.querySelectorAll("*,:x");
5116			rbuggyQSA.push(",.*:");
5117		});
5118	}
5119
5120	if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
5121		docElem.mozMatchesSelector ||
5122		docElem.oMatchesSelector ||
5123		docElem.msMatchesSelector) )) ) {
5124
5125		assert(function( div ) {
5126			support.disconnectedMatch = matches.call( div, "div" );
5127
5128			matches.call( div, "[s!='']:x" );
5129			rbuggyMatches.push( "!=", pseudos );
5130		});
5131	}
5132
5133	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
5134	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
5135
5136	/* Contains
5137	---------------------------------------------------------------------- */
5138	hasCompare = rnative.test( docElem.compareDocumentPosition );
5139
5140	contains = hasCompare || rnative.test( docElem.contains ) ?
5141		function( a, b ) {
5142			var adown = a.nodeType === 9 ? a.documentElement : a,
5143				bup = b && b.parentNode;
5144			return a === bup || !!( bup && bup.nodeType === 1 && (
5145				adown.contains ?
5146					adown.contains( bup ) :
5147					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
5148			));
5149		} :
5150		function( a, b ) {
5151			if ( b ) {
5152				while ( (b = b.parentNode) ) {
5153					if ( b === a ) {
5154						return true;
5155					}
5156				}
5157			}
5158			return false;
5159		};
5160
5161	/* Sorting
5162	---------------------------------------------------------------------- */
5163
5164	sortOrder = hasCompare ?
5165	function( a, b ) {
5166
5167		if ( a === b ) {
5168			hasDuplicate = true;
5169			return 0;
5170		}
5171
5172		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
5173		if ( compare ) {
5174			return compare;
5175		}
5176
5177		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
5178			a.compareDocumentPosition( b ) :
5179
5180			1;
5181
5182		if ( compare & 1 ||
5183			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
5184
5185			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
5186				return -1;
5187			}
5188			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
5189				return 1;
5190			}
5191
5192			return sortInput ?
5193				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5194				0;
5195		}
5196
5197		return compare & 4 ? -1 : 1;
5198	} :
5199	function( a, b ) {
5200		if ( a === b ) {
5201			hasDuplicate = true;
5202			return 0;
5203		}
5204
5205		var cur,
5206			i = 0,
5207			aup = a.parentNode,
5208			bup = b.parentNode,
5209			ap = [ a ],
5210			bp = [ b ];
5211
5212		if ( !aup || !bup ) {
5213			return a === doc ? -1 :
5214				b === doc ? 1 :
5215				aup ? -1 :
5216				bup ? 1 :
5217				sortInput ?
5218				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5219				0;
5220
5221		} else if ( aup === bup ) {
5222			return siblingCheck( a, b );
5223		}
5224
5225		cur = a;
5226		while ( (cur = cur.parentNode) ) {
5227			ap.unshift( cur );
5228		}
5229		cur = b;
5230		while ( (cur = cur.parentNode) ) {
5231			bp.unshift( cur );
5232		}
5233
5234		while ( ap[i] === bp[i] ) {
5235			i++;
5236		}
5237
5238		return i ?
5239			siblingCheck( ap[i], bp[i] ) :
5240
5241			ap[i] === preferredDoc ? -1 :
5242			bp[i] === preferredDoc ? 1 :
5243			0;
5244	};
5245
5246	return doc;
5247};
5248
5249Sizzle.matches = function( expr, elements ) {
5250	return Sizzle( expr, null, null, elements );
5251};
5252
5253Sizzle.matchesSelector = function( elem, expr ) {
5254	if ( ( elem.ownerDocument || elem ) !== document ) {
5255		setDocument( elem );
5256	}
5257
5258	expr = expr.replace( rattributeQuotes, "='$1']" );
5259
5260	if ( support.matchesSelector && documentIsHTML &&
5261		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
5262		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
5263
5264		try {
5265			var ret = matches.call( elem, expr );
5266
5267			if ( ret || support.disconnectedMatch ||
5268					elem.document && elem.document.nodeType !== 11 ) {
5269				return ret;
5270			}
5271		} catch(e) {}
5272	}
5273
5274	return Sizzle( expr, document, null, [elem] ).length > 0;
5275};
5276
5277Sizzle.contains = function( context, elem ) {
5278	if ( ( context.ownerDocument || context ) !== document ) {
5279		setDocument( context );
5280	}
5281	return contains( context, elem );
5282};
5283
5284Sizzle.attr = function( elem, name ) {
5285	if ( ( elem.ownerDocument || elem ) !== document ) {
5286		setDocument( elem );
5287	}
5288
5289	var fn = Expr.attrHandle[ name.toLowerCase() ],
5290		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
5291			fn( elem, name, !documentIsHTML ) :
5292			undefined;
5293
5294	return val !== undefined ?
5295		val :
5296		support.attributes || !documentIsHTML ?
5297			elem.getAttribute( name ) :
5298			(val = elem.getAttributeNode(name)) && val.specified ?
5299				val.value :
5300				null;
5301};
5302
5303Sizzle.error = function( msg ) {
5304	throw new Error( "Syntax error, unrecognized expression: " + msg );
5305};
5306
5307/**
5308 * Document sorting and removing duplicates
5309 * @param {ArrayLike} results
5310 */
5311Sizzle.uniqueSort = function( results ) {
5312	var elem,
5313		duplicates = [],
5314		j = 0,
5315		i = 0;
5316
5317	hasDuplicate = !support.detectDuplicates;
5318	sortInput = !support.sortStable && results.slice( 0 );
5319	results.sort( sortOrder );
5320
5321	if ( hasDuplicate ) {
5322		while ( (elem = results[i++]) ) {
5323			if ( elem === results[ i ] ) {
5324				j = duplicates.push( i );
5325			}
5326		}
5327		while ( j-- ) {
5328			results.splice( duplicates[ j ], 1 );
5329		}
5330	}
5331
5332	sortInput = null;
5333
5334	return results;
5335};
5336
5337/**
5338 * Utility function for retrieving the text value of an array of DOM nodes
5339 * @param {Array|Element} elem
5340 */
5341getText = Sizzle.getText = function( elem ) {
5342	var node,
5343		ret = "",
5344		i = 0,
5345		nodeType = elem.nodeType;
5346
5347	if ( !nodeType ) {
5348		while ( (node = elem[i++]) ) {
5349			ret += getText( node );
5350		}
5351	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
5352		if ( typeof elem.textContent === "string" ) {
5353			return elem.textContent;
5354		} else {
5355			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5356				ret += getText( elem );
5357			}
5358		}
5359	} else if ( nodeType === 3 || nodeType === 4 ) {
5360		return elem.nodeValue;
5361	}
5362
5363	return ret;
5364};
5365
5366Expr = Sizzle.selectors = {
5367
5368	cacheLength: 50,
5369
5370	createPseudo: markFunction,
5371
5372	match: matchExpr,
5373
5374	attrHandle: {},
5375
5376	find: {},
5377
5378	relative: {
5379		">": { dir: "parentNode", first: true },
5380		" ": { dir: "parentNode" },
5381		"+": { dir: "previousSibling", first: true },
5382		"~": { dir: "previousSibling" }
5383	},
5384
5385	preFilter: {
5386		"ATTR": function( match ) {
5387			match[1] = match[1].replace( runescape, funescape );
5388
5389			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
5390
5391			if ( match[2] === "~=" ) {
5392				match[3] = " " + match[3] + " ";
5393			}
5394
5395			return match.slice( 0, 4 );
5396		},
5397
5398		"CHILD": function( match ) {
5399			/* matches from matchExpr["CHILD"]
5400				1 type (only|nth|...)
5401				2 what (child|of-type)
5402				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
5403				4 xn-component of xn+y argument ([+-]?\d*n|)
5404				5 sign of xn-component
5405				6 x of xn-component
5406				7 sign of y-component
5407				8 y of y-component
5408			*/
5409			match[1] = match[1].toLowerCase();
5410
5411			if ( match[1].slice( 0, 3 ) === "nth" ) {
5412				if ( !match[3] ) {
5413					Sizzle.error( match[0] );
5414				}
5415
5416				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
5417				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
5418
5419			} else if ( match[3] ) {
5420				Sizzle.error( match[0] );
5421			}
5422
5423			return match;
5424		},
5425
5426		"PSEUDO": function( match ) {
5427			var excess,
5428				unquoted = !match[5] && match[2];
5429
5430			if ( matchExpr["CHILD"].test( match[0] ) ) {
5431				return null;
5432			}
5433
5434			if ( match[3] && match[4] !== undefined ) {
5435				match[2] = match[4];
5436
5437			} else if ( unquoted && rpseudo.test( unquoted ) &&
5438				(excess = tokenize( unquoted, true )) &&
5439				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
5440
5441				match[0] = match[0].slice( 0, excess );
5442				match[2] = unquoted.slice( 0, excess );
5443			}
5444
5445			return match.slice( 0, 3 );
5446		}
5447	},
5448
5449	filter: {
5450
5451		"TAG": function( nodeNameSelector ) {
5452			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
5453			return nodeNameSelector === "*" ?
5454				function() { return true; } :
5455				function( elem ) {
5456					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
5457				};
5458		},
5459
5460		"CLASS": function( className ) {
5461			var pattern = classCache[ className + " " ];
5462
5463			return pattern ||
5464				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
5465				classCache( className, function( elem ) {
5466					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
5467				});
5468		},
5469
5470		"ATTR": function( name, operator, check ) {
5471			return function( elem ) {
5472				var result = Sizzle.attr( elem, name );
5473
5474				if ( result == null ) {
5475					return operator === "!=";
5476				}
5477				if ( !operator ) {
5478					return true;
5479				}
5480
5481				result += "";
5482
5483				return operator === "=" ? result === check :
5484					operator === "!=" ? result !== check :
5485					operator === "^=" ? check && result.indexOf( check ) === 0 :
5486					operator === "*=" ? check && result.indexOf( check ) > -1 :
5487					operator === "$=" ? check && result.slice( -check.length ) === check :
5488					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
5489					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
5490					false;
5491			};
5492		},
5493
5494		"CHILD": function( type, what, argument, first, last ) {
5495			var simple = type.slice( 0, 3 ) !== "nth",
5496				forward = type.slice( -4 ) !== "last",
5497				ofType = what === "of-type";
5498
5499			return first === 1 && last === 0 ?
5500
5501				function( elem ) {
5502					return !!elem.parentNode;
5503				} :
5504
5505				function( elem, context, xml ) {
5506					var cache, outerCache, node, diff, nodeIndex, start,
5507						dir = simple !== forward ? "nextSibling" : "previousSibling",
5508						parent = elem.parentNode,
5509						name = ofType && elem.nodeName.toLowerCase(),
5510						useCache = !xml && !ofType;
5511
5512					if ( parent ) {
5513
5514						if ( simple ) {
5515							while ( dir ) {
5516								node = elem;
5517								while ( (node = node[ dir ]) ) {
5518									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
5519										return false;
5520									}
5521								}
5522								start = dir = type === "only" && !start && "nextSibling";
5523							}
5524							return true;
5525						}
5526
5527						start = [ forward ? parent.firstChild : parent.lastChild ];
5528
5529						if ( forward && useCache ) {
5530							outerCache = parent[ expando ] || (parent[ expando ] = {});
5531							cache = outerCache[ type ] || [];
5532							nodeIndex = cache[0] === dirruns && cache[1];
5533							diff = cache[0] === dirruns && cache[2];
5534							node = nodeIndex && parent.childNodes[ nodeIndex ];
5535
5536							while ( (node = ++nodeIndex && node && node[ dir ] ||
5537
5538								(diff = nodeIndex = 0) || start.pop()) ) {
5539
5540								if ( node.nodeType === 1 && ++diff && node === elem ) {
5541									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
5542									break;
5543								}
5544							}
5545
5546						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
5547							diff = cache[1];
5548
5549						} else {
5550							while ( (node = ++nodeIndex && node && node[ dir ] ||
5551								(diff = nodeIndex = 0) || start.pop()) ) {
5552
5553								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
5554									if ( useCache ) {
5555										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
5556									}
5557
5558									if ( node === elem ) {
5559										break;
5560									}
5561								}
5562							}
5563						}
5564
5565						diff -= last;
5566						return diff === first || ( diff % first === 0 && diff / first >= 0 );
5567					}
5568				};
5569		},
5570
5571		"PSEUDO": function( pseudo, argument ) {
5572			var args,
5573				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
5574					Sizzle.error( "unsupported pseudo: " + pseudo );
5575
5576			if ( fn[ expando ] ) {
5577				return fn( argument );
5578			}
5579
5580			if ( fn.length > 1 ) {
5581				args = [ pseudo, pseudo, "", argument ];
5582				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
5583					markFunction(function( seed, matches ) {
5584						var idx,
5585							matched = fn( seed, argument ),
5586							i = matched.length;
5587						while ( i-- ) {
5588							idx = indexOf.call( seed, matched[i] );
5589							seed[ idx ] = !( matches[ idx ] = matched[i] );
5590						}
5591					}) :
5592					function( elem ) {
5593						return fn( elem, 0, args );
5594					};
5595			}
5596
5597			return fn;
5598		}
5599	},
5600
5601	pseudos: {
5602		"not": markFunction(function( selector ) {
5603			var input = [],
5604				results = [],
5605				matcher = compile( selector.replace( rtrim, "$1" ) );
5606
5607			return matcher[ expando ] ?
5608				markFunction(function( seed, matches, context, xml ) {
5609					var elem,
5610						unmatched = matcher( seed, null, xml, [] ),
5611						i = seed.length;
5612
5613					while ( i-- ) {
5614						if ( (elem = unmatched[i]) ) {
5615							seed[i] = !(matches[i] = elem);
5616						}
5617					}
5618				}) :
5619				function( elem, context, xml ) {
5620					input[0] = elem;
5621					matcher( input, null, xml, results );
5622					return !results.pop();
5623				};
5624		}),
5625
5626		"has": markFunction(function( selector ) {
5627			return function( elem ) {
5628				return Sizzle( selector, elem ).length > 0;
5629			};
5630		}),
5631
5632		"contains": markFunction(function( text ) {
5633			return function( elem ) {
5634				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
5635			};
5636		}),
5637
5638		"lang": markFunction( function( lang ) {
5639			if ( !ridentifier.test(lang || "") ) {
5640				Sizzle.error( "unsupported lang: " + lang );
5641			}
5642			lang = lang.replace( runescape, funescape ).toLowerCase();
5643			return function( elem ) {
5644				var elemLang;
5645				do {
5646					if ( (elemLang = documentIsHTML ?
5647						elem.lang :
5648						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
5649
5650						elemLang = elemLang.toLowerCase();
5651						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
5652					}
5653				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
5654				return false;
5655			};
5656		}),
5657
5658		"target": function( elem ) {
5659			var hash = window.location && window.location.hash;
5660			return hash && hash.slice( 1 ) === elem.id;
5661		},
5662
5663		"root": function( elem ) {
5664			return elem === docElem;
5665		},
5666
5667		"focus": function( elem ) {
5668			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
5669		},
5670
5671		"enabled": function( elem ) {
5672			return elem.disabled === false;
5673		},
5674
5675		"disabled": function( elem ) {
5676			return elem.disabled === true;
5677		},
5678
5679		"checked": function( elem ) {
5680			var nodeName = elem.nodeName.toLowerCase();
5681			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
5682		},
5683
5684		"selected": function( elem ) {
5685			if ( elem.parentNode ) {
5686				elem.parentNode.selectedIndex;
5687			}
5688
5689			return elem.selected === true;
5690		},
5691
5692		"empty": function( elem ) {
5693			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5694				if ( elem.nodeType < 6 ) {
5695					return false;
5696				}
5697			}
5698			return true;
5699		},
5700
5701		"parent": function( elem ) {
5702			return !Expr.pseudos["empty"]( elem );
5703		},
5704
5705		"header": function( elem ) {
5706			return rheader.test( elem.nodeName );
5707		},
5708
5709		"input": function( elem ) {
5710			return rinputs.test( elem.nodeName );
5711		},
5712
5713		"button": function( elem ) {
5714			var name = elem.nodeName.toLowerCase();
5715			return name === "input" && elem.type === "button" || name === "button";
5716		},
5717
5718		"text": function( elem ) {
5719			var attr;
5720			return elem.nodeName.toLowerCase() === "input" &&
5721				elem.type === "text" &&
5722
5723				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
5724		},
5725
5726		"first": createPositionalPseudo(function() {
5727			return [ 0 ];
5728		}),
5729
5730		"last": createPositionalPseudo(function( matchIndexes, length ) {
5731			return [ length - 1 ];
5732		}),
5733
5734		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
5735			return [ argument < 0 ? argument + length : argument ];
5736		}),
5737
5738		"even": createPositionalPseudo(function( matchIndexes, length ) {
5739			var i = 0;
5740			for ( ; i < length; i += 2 ) {
5741				matchIndexes.push( i );
5742			}
5743			return matchIndexes;
5744		}),
5745
5746		"odd": createPositionalPseudo(function( matchIndexes, length ) {
5747			var i = 1;
5748			for ( ; i < length; i += 2 ) {
5749				matchIndexes.push( i );
5750			}
5751			return matchIndexes;
5752		}),
5753
5754		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5755			var i = argument < 0 ? argument + length : argument;
5756			for ( ; --i >= 0; ) {
5757				matchIndexes.push( i );
5758			}
5759			return matchIndexes;
5760		}),
5761
5762		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5763			var i = argument < 0 ? argument + length : argument;
5764			for ( ; ++i < length; ) {
5765				matchIndexes.push( i );
5766			}
5767			return matchIndexes;
5768		})
5769	}
5770};
5771
5772Expr.pseudos["nth"] = Expr.pseudos["eq"];
5773
5774for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5775	Expr.pseudos[ i ] = createInputPseudo( i );
5776}
5777for ( i in { submit: true, reset: true } ) {
5778	Expr.pseudos[ i ] = createButtonPseudo( i );
5779}
5780
5781function setFilters() {}
5782setFilters.prototype = Expr.filters = Expr.pseudos;
5783Expr.setFilters = new setFilters();
5784
5785function tokenize( selector, parseOnly ) {
5786	var matched, match, tokens, type,
5787		soFar, groups, preFilters,
5788		cached = tokenCache[ selector + " " ];
5789
5790	if ( cached ) {
5791		return parseOnly ? 0 : cached.slice( 0 );
5792	}
5793
5794	soFar = selector;
5795	groups = [];
5796	preFilters = Expr.preFilter;
5797
5798	while ( soFar ) {
5799
5800		if ( !matched || (match = rcomma.exec( soFar )) ) {
5801			if ( match ) {
5802				soFar = soFar.slice( match[0].length ) || soFar;
5803			}
5804			groups.push( (tokens = []) );
5805		}
5806
5807		matched = false;
5808
5809		if ( (match = rcombinators.exec( soFar )) ) {
5810			matched = match.shift();
5811			tokens.push({
5812				value: matched,
5813				type: match[0].replace( rtrim, " " )
5814			});
5815			soFar = soFar.slice( matched.length );
5816		}
5817
5818		for ( type in Expr.filter ) {
5819			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5820				(match = preFilters[ type ]( match ))) ) {
5821				matched = match.shift();
5822				tokens.push({
5823					value: matched,
5824					type: type,
5825					matches: match
5826				});
5827				soFar = soFar.slice( matched.length );
5828			}
5829		}
5830
5831		if ( !matched ) {
5832			break;
5833		}
5834	}
5835
5836	return parseOnly ?
5837		soFar.length :
5838		soFar ?
5839			Sizzle.error( selector ) :
5840			tokenCache( selector, groups ).slice( 0 );
5841}
5842
5843function toSelector( tokens ) {
5844	var i = 0,
5845		len = tokens.length,
5846		selector = "";
5847	for ( ; i < len; i++ ) {
5848		selector += tokens[i].value;
5849	}
5850	return selector;
5851}
5852
5853function addCombinator( matcher, combinator, base ) {
5854	var dir = combinator.dir,
5855		checkNonElements = base && dir === "parentNode",
5856		doneName = done++;
5857
5858	return combinator.first ?
5859		function( elem, context, xml ) {
5860			while ( (elem = elem[ dir ]) ) {
5861				if ( elem.nodeType === 1 || checkNonElements ) {
5862					return matcher( elem, context, xml );
5863				}
5864			}
5865		} :
5866
5867		function( elem, context, xml ) {
5868			var oldCache, outerCache,
5869				newCache = [ dirruns, doneName ];
5870
5871			if ( xml ) {
5872				while ( (elem = elem[ dir ]) ) {
5873					if ( elem.nodeType === 1 || checkNonElements ) {
5874						if ( matcher( elem, context, xml ) ) {
5875							return true;
5876						}
5877					}
5878				}
5879			} else {
5880				while ( (elem = elem[ dir ]) ) {
5881					if ( elem.nodeType === 1 || checkNonElements ) {
5882						outerCache = elem[ expando ] || (elem[ expando ] = {});
5883						if ( (oldCache = outerCache[ dir ]) &&
5884							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
5885
5886							return (newCache[ 2 ] = oldCache[ 2 ]);
5887						} else {
5888							outerCache[ dir ] = newCache;
5889
5890							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
5891								return true;
5892							}
5893						}
5894					}
5895				}
5896			}
5897		};
5898}
5899
5900function elementMatcher( matchers ) {
5901	return matchers.length > 1 ?
5902		function( elem, context, xml ) {
5903			var i = matchers.length;
5904			while ( i-- ) {
5905				if ( !matchers[i]( elem, context, xml ) ) {
5906					return false;
5907				}
5908			}
5909			return true;
5910		} :
5911		matchers[0];
5912}
5913
5914function multipleContexts( selector, contexts, results ) {
5915	var i = 0,
5916		len = contexts.length;
5917	for ( ; i < len; i++ ) {
5918		Sizzle( selector, contexts[i], results );
5919	}
5920	return results;
5921}
5922
5923function condense( unmatched, map, filter, context, xml ) {
5924	var elem,
5925		newUnmatched = [],
5926		i = 0,
5927		len = unmatched.length,
5928		mapped = map != null;
5929
5930	for ( ; i < len; i++ ) {
5931		if ( (elem = unmatched[i]) ) {
5932			if ( !filter || filter( elem, context, xml ) ) {
5933				newUnmatched.push( elem );
5934				if ( mapped ) {
5935					map.push( i );
5936				}
5937			}
5938		}
5939	}
5940
5941	return newUnmatched;
5942}
5943
5944function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5945	if ( postFilter && !postFilter[ expando ] ) {
5946		postFilter = setMatcher( postFilter );
5947	}
5948	if ( postFinder && !postFinder[ expando ] ) {
5949		postFinder = setMatcher( postFinder, postSelector );
5950	}
5951	return markFunction(function( seed, results, context, xml ) {
5952		var temp, i, elem,
5953			preMap = [],
5954			postMap = [],
5955			preexisting = results.length,
5956
5957			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5958
5959			matcherIn = preFilter && ( seed || !selector ) ?
5960				condense( elems, preMap, preFilter, context, xml ) :
5961				elems,
5962
5963			matcherOut = matcher ?
5964				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5965
5966					[] :
5967
5968					results :
5969				matcherIn;
5970
5971		if ( matcher ) {
5972			matcher( matcherIn, matcherOut, context, xml );
5973		}
5974
5975		if ( postFilter ) {
5976			temp = condense( matcherOut, postMap );
5977			postFilter( temp, [], context, xml );
5978
5979			i = temp.length;
5980			while ( i-- ) {
5981				if ( (elem = temp[i]) ) {
5982					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5983				}
5984			}
5985		}
5986
5987		if ( seed ) {
5988			if ( postFinder || preFilter ) {
5989				if ( postFinder ) {
5990					temp = [];
5991					i = matcherOut.length;
5992					while ( i-- ) {
5993						if ( (elem = matcherOut[i]) ) {
5994							temp.push( (matcherIn[i] = elem) );
5995						}
5996					}
5997					postFinder( null, (matcherOut = []), temp, xml );
5998				}
5999
6000				i = matcherOut.length;
6001				while ( i-- ) {
6002					if ( (elem = matcherOut[i]) &&
6003						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
6004
6005						seed[temp] = !(results[temp] = elem);
6006					}
6007				}
6008			}
6009
6010		} else {
6011			matcherOut = condense(
6012				matcherOut === results ?
6013					matcherOut.splice( preexisting, matcherOut.length ) :
6014					matcherOut
6015			);
6016			if ( postFinder ) {
6017				postFinder( null, results, matcherOut, xml );
6018			} else {
6019				push.apply( results, matcherOut );
6020			}
6021		}
6022	});
6023}
6024
6025function matcherFromTokens( tokens ) {
6026	var checkContext, matcher, j,
6027		len = tokens.length,
6028		leadingRelative = Expr.relative[ tokens[0].type ],
6029		implicitRelative = leadingRelative || Expr.relative[" "],
6030		i = leadingRelative ? 1 : 0,
6031
6032		matchContext = addCombinator( function( elem ) {
6033			return elem === checkContext;
6034		}, implicitRelative, true ),
6035		matchAnyContext = addCombinator( function( elem ) {
6036			return indexOf.call( checkContext, elem ) > -1;
6037		}, implicitRelative, true ),
6038		matchers = [ function( elem, context, xml ) {
6039			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
6040				(checkContext = context).nodeType ?
6041					matchContext( elem, context, xml ) :
6042					matchAnyContext( elem, context, xml ) );
6043		} ];
6044
6045	for ( ; i < len; i++ ) {
6046		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
6047			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
6048		} else {
6049			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
6050
6051			if ( matcher[ expando ] ) {
6052				j = ++i;
6053				for ( ; j < len; j++ ) {
6054					if ( Expr.relative[ tokens[j].type ] ) {
6055						break;
6056					}
6057				}
6058				return setMatcher(
6059					i > 1 && elementMatcher( matchers ),
6060					i > 1 && toSelector(
6061						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
6062					).replace( rtrim, "$1" ),
6063					matcher,
6064					i < j && matcherFromTokens( tokens.slice( i, j ) ),
6065					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
6066					j < len && toSelector( tokens )
6067				);
6068			}
6069			matchers.push( matcher );
6070		}
6071	}
6072
6073	return elementMatcher( matchers );
6074}
6075
6076function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
6077	var bySet = setMatchers.length > 0,
6078		byElement = elementMatchers.length > 0,
6079		superMatcher = function( seed, context, xml, results, outermost ) {
6080			var elem, j, matcher,
6081				matchedCount = 0,
6082				i = "0",
6083				unmatched = seed && [],
6084				setMatched = [],
6085				contextBackup = outermostContext,
6086				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
6087				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
6088				len = elems.length;
6089
6090			if ( outermost ) {
6091				outermostContext = context !== document && context;
6092			}
6093
6094			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
6095				if ( byElement && elem ) {
6096					j = 0;
6097					while ( (matcher = elementMatchers[j++]) ) {
6098						if ( matcher( elem, context, xml ) ) {
6099							results.push( elem );
6100							break;
6101						}
6102					}
6103					if ( outermost ) {
6104						dirruns = dirrunsUnique;
6105					}
6106				}
6107
6108				if ( bySet ) {
6109					if ( (elem = !matcher && elem) ) {
6110						matchedCount--;
6111					}
6112
6113					if ( seed ) {
6114						unmatched.push( elem );
6115					}
6116				}
6117			}
6118
6119			matchedCount += i;
6120			if ( bySet && i !== matchedCount ) {
6121				j = 0;
6122				while ( (matcher = setMatchers[j++]) ) {
6123					matcher( unmatched, setMatched, context, xml );
6124				}
6125
6126				if ( seed ) {
6127					if ( matchedCount > 0 ) {
6128						while ( i-- ) {
6129							if ( !(unmatched[i] || setMatched[i]) ) {
6130								setMatched[i] = pop.call( results );
6131							}
6132						}
6133					}
6134
6135					setMatched = condense( setMatched );
6136				}
6137
6138				push.apply( results, setMatched );
6139
6140				if ( outermost && !seed && setMatched.length > 0 &&
6141					( matchedCount + setMatchers.length ) > 1 ) {
6142
6143					Sizzle.uniqueSort( results );
6144				}
6145			}
6146
6147			if ( outermost ) {
6148				dirruns = dirrunsUnique;
6149				outermostContext = contextBackup;
6150			}
6151
6152			return unmatched;
6153		};
6154
6155	return bySet ?
6156		markFunction( superMatcher ) :
6157		superMatcher;
6158}
6159
6160compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
6161	var i,
6162		setMatchers = [],
6163		elementMatchers = [],
6164		cached = compilerCache[ selector + " " ];
6165
6166	if ( !cached ) {
6167		if ( !match ) {
6168			match = tokenize( selector );
6169		}
6170		i = match.length;
6171		while ( i-- ) {
6172			cached = matcherFromTokens( match[i] );
6173			if ( cached[ expando ] ) {
6174				setMatchers.push( cached );
6175			} else {
6176				elementMatchers.push( cached );
6177			}
6178		}
6179
6180		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
6181
6182		cached.selector = selector;
6183	}
6184	return cached;
6185};
6186
6187/**
6188 * A low-level selection function that works with Sizzle's compiled
6189 *  selector functions
6190 * @param {String|Function} selector A selector or a pre-compiled
6191 *  selector function built with Sizzle.compile
6192 * @param {Element} context
6193 * @param {Array} [results]
6194 * @param {Array} [seed] A set of elements to match against
6195 */
6196select = Sizzle.select = function( selector, context, results, seed ) {
6197	var i, tokens, token, type, find,
6198		compiled = typeof selector === "function" && selector,
6199		match = !seed && tokenize( (selector = compiled.selector || selector) );
6200
6201	results = results || [];
6202
6203	if ( match.length === 1 ) {
6204
6205		tokens = match[0] = match[0].slice( 0 );
6206		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
6207				support.getById && context.nodeType === 9 && documentIsHTML &&
6208				Expr.relative[ tokens[1].type ] ) {
6209
6210			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
6211			if ( !context ) {
6212				return results;
6213
6214			} else if ( compiled ) {
6215				context = context.parentNode;
6216			}
6217
6218			selector = selector.slice( tokens.shift().value.length );
6219		}
6220
6221		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
6222		while ( i-- ) {
6223			token = tokens[i];
6224
6225			if ( Expr.relative[ (type = token.type) ] ) {
6226				break;
6227			}
6228			if ( (find = Expr.find[ type ]) ) {
6229				if ( (seed = find(
6230					token.matches[0].replace( runescape, funescape ),
6231					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
6232				)) ) {
6233
6234					tokens.splice( i, 1 );
6235					selector = seed.length && toSelector( tokens );
6236					if ( !selector ) {
6237						push.apply( results, seed );
6238						return results;
6239					}
6240
6241					break;
6242				}
6243			}
6244		}
6245	}
6246
6247	( compiled || compile( selector, match ) )(
6248		seed,
6249		context,
6250		!documentIsHTML,
6251		results,
6252		rsibling.test( selector ) && testContext( context.parentNode ) || context
6253	);
6254	return results;
6255};
6256
6257
6258support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
6259
6260support.detectDuplicates = !!hasDuplicate;
6261
6262setDocument();
6263
6264support.sortDetached = assert(function( div1 ) {
6265	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
6266});
6267
6268if ( !assert(function( div ) {
6269	div.innerHTML = "<a href='#'></a>";
6270	return div.firstChild.getAttribute("href") === "#" ;
6271}) ) {
6272	addHandle( "type|href|height|width", function( elem, name, isXML ) {
6273		if ( !isXML ) {
6274			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
6275		}
6276	});
6277}
6278
6279if ( !support.attributes || !assert(function( div ) {
6280	div.innerHTML = "<input/>";
6281	div.firstChild.setAttribute( "value", "" );
6282	return div.firstChild.getAttribute( "value" ) === "";
6283}) ) {
6284	addHandle( "value", function( elem, name, isXML ) {
6285		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
6286			return elem.defaultValue;
6287		}
6288	});
6289}
6290
6291if ( !assert(function( div ) {
6292	return div.getAttribute("disabled") == null;
6293}) ) {
6294	addHandle( booleans, function( elem, name, isXML ) {
6295		var val;
6296		if ( !isXML ) {
6297			return elem[ name ] === true ? name.toLowerCase() :
6298					(val = elem.getAttributeNode( name )) && val.specified ?
6299					val.value :
6300				null;
6301		}
6302	});
6303}
6304
6305if ( typeof define === "function" && define.amd ) {
6306	define(function() { return Sizzle; });
6307} else if ( typeof module !== "undefined" && module.exports ) {
6308	module.exports = Sizzle;
6309} else {
6310	window.Sizzle = Sizzle;
6311}
6312
6313})( window );
6314
6315;(function() {
6316  if (typeof Sizzle !== 'undefined') {
6317    return;
6318  }
6319
6320  if (typeof define !== 'undefined' && define.amd) {
6321    window.Sizzle = Prototype._actual_sizzle;
6322    window.define = Prototype._original_define;
6323    delete Prototype._actual_sizzle;
6324    delete Prototype._original_define;
6325  } else if (typeof module !== 'undefined' && module.exports) {
6326    window.Sizzle = module.exports;
6327    module.exports = {};
6328  }
6329})();
6330
6331;(function(engine) {
6332  var extendElements = Prototype.Selector.extendElements;
6333
6334  function select(selector, scope) {
6335    return extendElements(engine(selector, scope || document));
6336  }
6337
6338  function match(element, selector) {
6339    return engine.matches(selector, [element]).length == 1;
6340  }
6341
6342  Prototype.Selector.engine = engine;
6343  Prototype.Selector.select = select;
6344  Prototype.Selector.match = match;
6345})(Sizzle);
6346
6347window.Sizzle = Prototype._original_property;
6348delete Prototype._original_property;
6349
6350var Form = {
6351  reset: function(form) {
6352    form = $$$(form);
6353    form.reset();
6354    return form;
6355  },
6356
6357  serializeElements: function(elements, options) {
6358    if (typeof options != 'object') options = { hash: !!options };
6359    else if (Object.isUndefined(options.hash)) options.hash = true;
6360    var key, value, submitted = false, submit = options.submit, accumulator, initial;
6361
6362    if (options.hash) {
6363      initial = {};
6364      accumulator = function(result, key, value) {
6365        if (key in result) {
6366          if (!Object.isArray(result[key])) result[key] = [result[key]];
6367          result[key] = result[key].concat(value);
6368        } else result[key] = value;
6369        return result;
6370      };
6371    } else {
6372      initial = '';
6373      accumulator = function(result, key, values) {
6374        if (!Object.isArray(values)) {values = [values];}
6375        if (!values.length) {return result;}
6376        var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');
6377        return result + (result ? "&" : "") + values.map(function (value) {
6378          value = value.gsub(/(\r)?\n/, '\r\n');
6379          value = encodeURIComponent(value);
6380          value = value.gsub(/%20/, '+');
6381          return encodedKey + "=" + value;
6382        }).join("&");
6383      };
6384    }
6385
6386    return elements.inject(initial, function(result, element) {
6387      if (!element.disabled && element.name) {
6388        key = element.name; value = $$$(element).getValue();
6389        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
6390            submit !== false && (!submit || key == submit) && (submitted = true)))) {
6391          result = accumulator(result, key, value);
6392        }
6393      }
6394      return result;
6395    });
6396  }
6397};
6398
6399Form.Methods = {
6400  serialize: function(form, options) {
6401    return Form.serializeElements(Form.getElements(form), options);
6402  },
6403
6404
6405  getElements: function(form) {
6406    var elements = $$$(form).getElementsByTagName('*');
6407    var element, results = [], serializers = Form.Element.Serializers;
6408
6409    for (var i = 0; element = elements[i]; i++) {
6410      if (serializers[element.tagName.toLowerCase()])
6411        results.push(Element.extend(element));
6412    }
6413    return results;
6414  },
6415
6416  getInputs: function(form, typeName, name) {
6417    form = $$$(form);
6418    var inputs = form.getElementsByTagName('input');
6419
6420    if (!typeName && !name) return $A(inputs).map(Element.extend);
6421
6422    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
6423      var input = inputs[i];
6424      if ((typeName && input.type != typeName) || (name && input.name != name))
6425        continue;
6426      matchingInputs.push(Element.extend(input));
6427    }
6428
6429    return matchingInputs;
6430  },
6431
6432  disable: function(form) {
6433    form = $$$(form);
6434    Form.getElements(form).invoke('disable');
6435    return form;
6436  },
6437
6438  enable: function(form) {
6439    form = $$$(form);
6440    Form.getElements(form).invoke('enable');
6441    return form;
6442  },
6443
6444  findFirstElement: function(form) {
6445    var elements = $$$(form).getElements().findAll(function(element) {
6446      return 'hidden' != element.type && !element.disabled;
6447    });
6448    var firstByIndex = elements.findAll(function(element) {
6449      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
6450    }).sortBy(function(element) { return element.tabIndex }).first();
6451
6452    return firstByIndex ? firstByIndex : elements.find(function(element) {
6453      return /^(?:input|select|textarea)$/i.test(element.tagName);
6454    });
6455  },
6456
6457  focusFirstElement: function(form) {
6458    form = $$$(form);
6459    var element = form.findFirstElement();
6460    if (element) element.activate();
6461    return form;
6462  },
6463
6464  request: function(form, options) {
6465    form = $$$(form), options = Object.clone(options || { });
6466
6467    var params = options.parameters, action = form.readAttribute('action') || '';
6468    if (action.blank()) action = window.location.href;
6469    options.parameters = form.serialize(true);
6470
6471    if (params) {
6472      if (Object.isString(params)) params = params.toQueryParams();
6473      Object.extend(options.parameters, params);
6474    }
6475
6476    if (form.hasAttribute('method') && !options.method)
6477      options.method = form.method;
6478
6479    return new Ajax.Request(action, options);
6480  }
6481};
6482
6483/*--------------------------------------------------------------------------*/
6484
6485
6486Form.Element = {
6487  focus: function(element) {
6488    $$$(element).focus();
6489    return element;
6490  },
6491
6492  select: function(element) {
6493    $$$(element).select();
6494    return element;
6495  }
6496};
6497
6498Form.Element.Methods = {
6499
6500  serialize: function(element) {
6501    element = $$$(element);
6502    if (!element.disabled && element.name) {
6503      var value = element.getValue();
6504      if (value != undefined) {
6505        var pair = { };
6506        pair[element.name] = value;
6507        return Object.toQueryString(pair);
6508      }
6509    }
6510    return '';
6511  },
6512
6513  getValue: function(element) {
6514    element = $$$(element);
6515    var method = element.tagName.toLowerCase();
6516    return Form.Element.Serializers[method](element);
6517  },
6518
6519  setValue: function(element, value) {
6520    element = $$$(element);
6521    var method = element.tagName.toLowerCase();
6522    Form.Element.Serializers[method](element, value);
6523    return element;
6524  },
6525
6526  clear: function(element) {
6527    $$$(element).value = '';
6528    return element;
6529  },
6530
6531  present: function(element) {
6532    return $$$(element).value != '';
6533  },
6534
6535  activate: function(element) {
6536    element = $$$(element);
6537    try {
6538      element.focus();
6539      if (element.select && (element.tagName.toLowerCase() != 'input' ||
6540          !(/^(?:button|reset|submit)$/i.test(element.type))))
6541        element.select();
6542    } catch (e) { }
6543    return element;
6544  },
6545
6546  disable: function(element) {
6547    element = $$$(element);
6548    element.disabled = true;
6549    return element;
6550  },
6551
6552  enable: function(element) {
6553    element = $$$(element);
6554    element.disabled = false;
6555    return element;
6556  }
6557};
6558
6559/*--------------------------------------------------------------------------*/
6560
6561var Field = Form.Element;
6562
6563var $F = Form.Element.Methods.getValue;
6564
6565/*--------------------------------------------------------------------------*/
6566
6567Form.Element.Serializers = (function() {
6568  function input(element, value) {
6569    switch (element.type.toLowerCase()) {
6570      case 'checkbox':
6571      case 'radio':
6572        return inputSelector(element, value);
6573      default:
6574        return valueSelector(element, value);
6575    }
6576  }
6577
6578  function inputSelector(element, value) {
6579    if (Object.isUndefined(value))
6580      return element.checked ? element.value : null;
6581    else element.checked = !!value;
6582  }
6583
6584  function valueSelector(element, value) {
6585    if (Object.isUndefined(value)) return element.value;
6586    else element.value = value;
6587  }
6588
6589  function select(element, value) {
6590    if (Object.isUndefined(value))
6591      return (element.type === 'select-one' ? selectOne : selectMany)(element);
6592
6593    var opt, currentValue, single = !Object.isArray(value);
6594    for (var i = 0, length = element.length; i < length; i++) {
6595      opt = element.options[i];
6596      currentValue = this.optionValue(opt);
6597      if (single) {
6598        if (currentValue == value) {
6599          opt.selected = true;
6600          return;
6601        }
6602      }
6603      else opt.selected = value.include(currentValue);
6604    }
6605  }
6606
6607  function selectOne(element) {
6608    var index = element.selectedIndex;
6609    return index >= 0 ? optionValue(element.options[index]) : null;
6610  }
6611
6612  function selectMany(element) {
6613    var values, length = element.length;
6614    if (!length) return null;
6615
6616    for (var i = 0, values = []; i < length; i++) {
6617      var opt = element.options[i];
6618      if (opt.selected) values.push(optionValue(opt));
6619    }
6620    return values;
6621  }
6622
6623  function optionValue(opt) {
6624    return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
6625  }
6626
6627  return {
6628    input:         input,
6629    inputSelector: inputSelector,
6630    textarea:      valueSelector,
6631    select:        select,
6632    selectOne:     selectOne,
6633    selectMany:    selectMany,
6634    optionValue:   optionValue,
6635    button:        valueSelector
6636  };
6637})();
6638
6639/*--------------------------------------------------------------------------*/
6640
6641
6642Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
6643  initialize: function($super, element, frequency, callback) {
6644    $super(callback, frequency);
6645    this.element   = $$$(element);
6646    this.lastValue = this.getValue();
6647  },
6648
6649  execute: function() {
6650    var value = this.getValue();
6651    if (Object.isString(this.lastValue) && Object.isString(value) ?
6652        this.lastValue != value : String(this.lastValue) != String(value)) {
6653      this.callback(this.element, value);
6654      this.lastValue = value;
6655    }
6656  }
6657});
6658
6659Form.Element.Observer = Class.create(Abstract.TimedObserver, {
6660  getValue: function() {
6661    return Form.Element.getValue(this.element);
6662  }
6663});
6664
6665Form.Observer = Class.create(Abstract.TimedObserver, {
6666  getValue: function() {
6667    return Form.serialize(this.element);
6668  }
6669});
6670
6671/*--------------------------------------------------------------------------*/
6672
6673Abstract.EventObserver = Class.create({
6674  initialize: function(element, callback) {
6675    this.element  = $$$(element);
6676    this.callback = callback;
6677
6678    this.lastValue = this.getValue();
6679    if (this.element.tagName.toLowerCase() == 'form')
6680      this.registerFormCallbacks();
6681    else
6682      this.registerCallback(this.element);
6683  },
6684
6685  onElementEvent: function() {
6686    var value = this.getValue();
6687    if (this.lastValue != value) {
6688      this.callback(this.element, value);
6689      this.lastValue = value;
6690    }
6691  },
6692
6693  registerFormCallbacks: function() {
6694    Form.getElements(this.element).each(this.registerCallback, this);
6695  },
6696
6697  registerCallback: function(element) {
6698    if (element.type) {
6699      switch (element.type.toLowerCase()) {
6700        case 'checkbox':
6701        case 'radio':
6702          Event.observe(element, 'click', this.onElementEvent.bind(this));
6703          break;
6704        default:
6705          Event.observe(element, 'change', this.onElementEvent.bind(this));
6706          break;
6707      }
6708    }
6709  }
6710});
6711
6712Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
6713  getValue: function() {
6714    return Form.Element.getValue(this.element);
6715  }
6716});
6717
6718Form.EventObserver = Class.create(Abstract.EventObserver, {
6719  getValue: function() {
6720    return Form.serialize(this.element);
6721  }
6722});
6723(function(GLOBAL) {
6724  var DIV = document.createElement('div');
6725  var docEl = document.documentElement;
6726  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
6727   && 'onmouseleave' in docEl;
6728
6729  var Event = {
6730    KEY_BACKSPACE: 8,
6731    KEY_TAB:       9,
6732    KEY_RETURN:   13,
6733    KEY_ESC:      27,
6734    KEY_LEFT:     37,
6735    KEY_UP:       38,
6736    KEY_RIGHT:    39,
6737    KEY_DOWN:     40,
6738    KEY_DELETE:   46,
6739    KEY_HOME:     36,
6740    KEY_END:      35,
6741    KEY_PAGEUP:   33,
6742    KEY_PAGEDOWN: 34,
6743    KEY_INSERT:   45
6744  };
6745
6746
6747  var isIELegacyEvent = function(event) { return false; };
6748
6749  if (window.attachEvent) {
6750    if (window.addEventListener) {
6751      isIELegacyEvent = function(event) {
6752        return !(event instanceof window.Event);
6753      };
6754    } else {
6755      isIELegacyEvent = function(event) { return true; };
6756    }
6757  }
6758
6759  var _isButton;
6760
6761  function _isButtonForDOMEvents(event, code) {
6762    return event.which ? (event.which === code + 1) : (event.button === code);
6763  }
6764
6765  var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
6766  function _isButtonForLegacyEvents(event, code) {
6767    return event.button === legacyButtonMap[code];
6768  }
6769
6770  function _isButtonForWebKit(event, code) {
6771    switch (code) {
6772      case 0: return event.which == 1 && !event.metaKey;
6773      case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
6774      case 2: return event.which == 3;
6775      default: return false;
6776    }
6777  }
6778
6779  if (window.attachEvent) {
6780    if (!window.addEventListener) {
6781      _isButton = _isButtonForLegacyEvents;
6782    } else {
6783      _isButton = function(event, code) {
6784        return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
6785         _isButtonForDOMEvents(event, code);
6786      }
6787    }
6788  } else if (Prototype.Browser.WebKit) {
6789    _isButton = _isButtonForWebKit;
6790  } else {
6791    _isButton = _isButtonForDOMEvents;
6792  }
6793
6794  function isLeftClick(event)   { return _isButton(event, 0) }
6795
6796  function isMiddleClick(event) { return _isButton(event, 1) }
6797
6798  function isRightClick(event)  { return _isButton(event, 2) }
6799
6800  function element(event) {
6801    return Element.extend(_element(event));
6802  }
6803
6804  function _element(event) {
6805    event = Event.extend(event);
6806
6807    var node = event.target, type = event.type,
6808     currentTarget = event.currentTarget;
6809
6810    if (currentTarget && currentTarget.tagName) {
6811      if (type === 'load' || type === 'error' ||
6812        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
6813          && currentTarget.type === 'radio'))
6814            node = currentTarget;
6815    }
6816
6817    return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;
6818  }
6819
6820  function findElement(event, expression) {
6821    var element = _element(event), selector = Prototype.Selector;
6822    if (!expression) return Element.extend(element);
6823    while (element) {
6824      if (Object.isElement(element) && selector.match(element, expression))
6825        return Element.extend(element);
6826      element = element.parentNode;
6827    }
6828  }
6829
6830  function pointer(event) {
6831    return { x: pointerX(event), y: pointerY(event) };
6832  }
6833
6834  function pointerX(event) {
6835    var docElement = document.documentElement,
6836     body = document.body || { scrollLeft: 0 };
6837
6838    return event.pageX || (event.clientX +
6839      (docElement.scrollLeft || body.scrollLeft) -
6840      (docElement.clientLeft || 0));
6841  }
6842
6843  function pointerY(event) {
6844    var docElement = document.documentElement,
6845     body = document.body || { scrollTop: 0 };
6846
6847    return  event.pageY || (event.clientY +
6848       (docElement.scrollTop || body.scrollTop) -
6849       (docElement.clientTop || 0));
6850  }
6851
6852
6853  function stop(event) {
6854    Event.extend(event);
6855    event.preventDefault();
6856    event.stopPropagation();
6857
6858    event.stopped = true;
6859  }
6860
6861
6862  Event.Methods = {
6863    isLeftClick:   isLeftClick,
6864    isMiddleClick: isMiddleClick,
6865    isRightClick:  isRightClick,
6866
6867    element:     element,
6868    findElement: findElement,
6869
6870    pointer:  pointer,
6871    pointerX: pointerX,
6872    pointerY: pointerY,
6873
6874    stop: stop
6875  };
6876
6877  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
6878    m[name] = Event.Methods[name].methodize();
6879    return m;
6880  });
6881
6882  if (window.attachEvent) {
6883    function _relatedTarget(event) {
6884      var element;
6885      switch (event.type) {
6886        case 'mouseover':
6887        case 'mouseenter':
6888          element = event.fromElement;
6889          break;
6890        case 'mouseout':
6891        case 'mouseleave':
6892          element = event.toElement;
6893          break;
6894        default:
6895          return null;
6896      }
6897      return Element.extend(element);
6898    }
6899
6900    var additionalMethods = {
6901      stopPropagation: function() { this.cancelBubble = true },
6902      preventDefault:  function() { this.returnValue = false },
6903      inspect: function() { return '[object Event]' }
6904    };
6905
6906    Event.extend = function(event, element) {
6907      if (!event) return false;
6908
6909      if (!isIELegacyEvent(event)) return event;
6910
6911      if (event._extendedByPrototype) return event;
6912      event._extendedByPrototype = Prototype.emptyFunction;
6913
6914      var pointer = Event.pointer(event);
6915
6916      Object.extend(event, {
6917        target: event.srcElement || element,
6918        relatedTarget: _relatedTarget(event),
6919        pageX:  pointer.x,
6920        pageY:  pointer.y
6921      });
6922
6923      Object.extend(event, methods);
6924      Object.extend(event, additionalMethods);
6925
6926      return event;
6927    };
6928  } else {
6929    Event.extend = Prototype.K;
6930  }
6931
6932  if (window.addEventListener) {
6933    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
6934    Object.extend(Event.prototype, methods);
6935  }
6936
6937  var EVENT_TRANSLATIONS = {
6938    mouseenter: 'mouseover',
6939    mouseleave: 'mouseout'
6940  };
6941
6942  function getDOMEventName(eventName) {
6943    return EVENT_TRANSLATIONS[eventName] || eventName;
6944  }
6945
6946  if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)
6947    getDOMEventName = Prototype.K;
6948
6949  function getUniqueElementID(element) {
6950    if (element === window) return 0;
6951
6952    if (typeof element._prototypeUID === 'undefined')
6953      element._prototypeUID = Element.Storage.UID++;
6954    return element._prototypeUID;
6955  }
6956
6957  function getUniqueElementID_IE(element) {
6958    if (element === window) return 0;
6959    if (element == document) return 1;
6960    return element.uniqueID;
6961  }
6962
6963  if ('uniqueID' in DIV)
6964    getUniqueElementID = getUniqueElementID_IE;
6965
6966  function isCustomEvent(eventName) {
6967    return eventName.include(':');
6968  }
6969
6970  Event._isCustomEvent = isCustomEvent;
6971
6972  function getOrCreateRegistryFor(element, uid) {
6973    var CACHE = GLOBAL.Event.cache;
6974    if (Object.isUndefined(uid))
6975      uid = getUniqueElementID(element);
6976    if (!CACHE[uid]) CACHE[uid] = { element: element };
6977    return CACHE[uid];
6978  }
6979
6980  function destroyRegistryForElement(element, uid) {
6981    if (Object.isUndefined(uid))
6982      uid = getUniqueElementID(element);
6983    delete GLOBAL.Event.cache[uid];
6984  }
6985
6986
6987  function register(element, eventName, handler) {
6988    var registry = getOrCreateRegistryFor(element);
6989    if (!registry[eventName]) registry[eventName] = [];
6990    var entries = registry[eventName];
6991
6992    var i = entries.length;
6993    while (i--)
6994      if (entries[i].handler === handler) return null;
6995
6996    var uid = getUniqueElementID(element);
6997    var responder = GLOBAL.Event._createResponder(uid, eventName, handler);
6998    var entry = {
6999      responder: responder,
7000      handler:   handler
7001    };
7002
7003    entries.push(entry);
7004    return entry;
7005  }
7006
7007  function unregister(element, eventName, handler) {
7008    var registry = getOrCreateRegistryFor(element);
7009    var entries = registry[eventName] || [];
7010
7011    var i = entries.length, entry;
7012    while (i--) {
7013      if (entries[i].handler === handler) {
7014        entry = entries[i];
7015        break;
7016      }
7017    }
7018
7019    if (entry) {
7020      var index = entries.indexOf(entry);
7021      entries.splice(index, 1);
7022    }
7023
7024    if (entries.length === 0) {
7025      delete registry[eventName];
7026      if (Object.keys(registry).length === 1 && ('element' in registry))
7027        destroyRegistryForElement(element);
7028    }
7029
7030    return entry;
7031  }
7032
7033
7034  function observe(element, eventName, handler) {
7035    element = $$$(element);
7036    var entry = register(element, eventName, handler);
7037
7038    if (entry === null) return element;
7039
7040    var responder = entry.responder;
7041    if (isCustomEvent(eventName))
7042      observeCustomEvent(element, eventName, responder);
7043    else
7044      observeStandardEvent(element, eventName, responder);
7045
7046    return element;
7047  }
7048
7049  function observeStandardEvent(element, eventName, responder) {
7050    var actualEventName = getDOMEventName(eventName);
7051    if (element.addEventListener) {
7052      element.addEventListener(actualEventName, responder, false);
7053    } else {
7054      element.attachEvent('on' + actualEventName, responder);
7055    }
7056  }
7057
7058  function observeCustomEvent(element, eventName, responder) {
7059    if (element.addEventListener) {
7060      element.addEventListener('dataavailable', responder, false);
7061    } else {
7062      element.attachEvent('ondataavailable', responder);
7063      element.attachEvent('onlosecapture',   responder);
7064    }
7065  }
7066
7067  function stopObserving(element, eventName, handler) {
7068    element = $$$(element);
7069    var handlerGiven = !Object.isUndefined(handler),
7070     eventNameGiven = !Object.isUndefined(eventName);
7071
7072    if (!eventNameGiven && !handlerGiven) {
7073      stopObservingElement(element);
7074      return element;
7075    }
7076
7077    if (!handlerGiven) {
7078      stopObservingEventName(element, eventName);
7079      return element;
7080    }
7081
7082    var entry = unregister(element, eventName, handler);
7083
7084    if (!entry) return element;
7085    removeEvent(element, eventName, entry.responder);
7086    return element;
7087  }
7088
7089  function stopObservingStandardEvent(element, eventName, responder) {
7090    var actualEventName = getDOMEventName(eventName);
7091    if (element.removeEventListener) {
7092      element.removeEventListener(actualEventName, responder, false);
7093    } else {
7094      element.detachEvent('on' + actualEventName, responder);
7095    }
7096  }
7097
7098  function stopObservingCustomEvent(element, eventName, responder) {
7099    if (element.removeEventListener) {
7100      element.removeEventListener('dataavailable', responder, false);
7101    } else {
7102      element.detachEvent('ondataavailable', responder);
7103      element.detachEvent('onlosecapture',   responder);
7104    }
7105  }
7106
7107
7108
7109  function stopObservingElement(element) {
7110    var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];
7111    if (!registry) return;
7112
7113    destroyRegistryForElement(element, uid);
7114
7115    var entries, i;
7116    for (var eventName in registry) {
7117      if (eventName === 'element') continue;
7118
7119      entries = registry[eventName];
7120      i = entries.length;
7121      while (i--)
7122        removeEvent(element, eventName, entries[i].responder);
7123    }
7124  }
7125
7126  function stopObservingEventName(element, eventName) {
7127    var registry = getOrCreateRegistryFor(element);
7128    var entries = registry[eventName];
7129    if (entries) {
7130      delete registry[eventName];
7131    }
7132
7133    entries = entries || [];
7134
7135    var i = entries.length;
7136    while (i--)
7137      removeEvent(element, eventName, entries[i].responder);
7138
7139    for (var name in registry) {
7140      if (name === 'element') continue;
7141      return; // There is another registered event
7142    }
7143
7144    destroyRegistryForElement(element);
7145  }
7146
7147
7148  function removeEvent(element, eventName, handler) {
7149    if (isCustomEvent(eventName))
7150      stopObservingCustomEvent(element, eventName, handler);
7151    else
7152      stopObservingStandardEvent(element, eventName, handler);
7153  }
7154
7155
7156
7157  function getFireTarget(element) {
7158    if (element !== document) return element;
7159    if (document.createEvent && !element.dispatchEvent)
7160      return document.documentElement;
7161    return element;
7162  }
7163
7164  function fire(element, eventName, memo, bubble) {
7165    element = getFireTarget($$$(element));
7166    if (Object.isUndefined(bubble)) bubble = true;
7167    memo = memo || {};
7168
7169    var event = fireEvent(element, eventName, memo, bubble);
7170    return Event.extend(event);
7171  }
7172
7173  function fireEvent_DOM(element, eventName, memo, bubble) {
7174    var event = document.createEvent('HTMLEvents');
7175    event.initEvent('dataavailable', bubble, true);
7176
7177    event.eventName = eventName;
7178    event.memo = memo;
7179
7180    element.dispatchEvent(event);
7181    return event;
7182  }
7183
7184  function fireEvent_IE(element, eventName, memo, bubble) {
7185    var event = document.createEventObject();
7186    event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
7187
7188    event.eventName = eventName;
7189    event.memo = memo;
7190
7191    element.fireEvent(event.eventType, event);
7192    return event;
7193  }
7194
7195  var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;
7196
7197
7198
7199  Event.Handler = Class.create({
7200    initialize: function(element, eventName, selector, callback) {
7201      this.element   = $$$(element);
7202      this.eventName = eventName;
7203      this.selector  = selector;
7204      this.callback  = callback;
7205      this.handler   = this.handleEvent.bind(this);
7206    },
7207
7208
7209    start: function() {
7210      Event.observe(this.element, this.eventName, this.handler);
7211      return this;
7212    },
7213
7214    stop: function() {
7215      Event.stopObserving(this.element, this.eventName, this.handler);
7216      return this;
7217    },
7218
7219    handleEvent: function(event) {
7220      var element = Event.findElement(event, this.selector);
7221      if (element) this.callback.call(this.element, event, element);
7222    }
7223  });
7224
7225  function on(element, eventName, selector, callback) {
7226    element = $$$(element);
7227    if (Object.isFunction(selector) && Object.isUndefined(callback)) {
7228      callback = selector, selector = null;
7229    }
7230
7231    return new Event.Handler(element, eventName, selector, callback).start();
7232  }
7233
7234  Object.extend(Event, Event.Methods);
7235
7236  Object.extend(Event, {
7237    fire:          fire,
7238    observe:       observe,
7239    stopObserving: stopObserving,
7240    on:            on
7241  });
7242
7243  Element.addMethods({
7244    fire:          fire,
7245
7246    observe:       observe,
7247
7248    stopObserving: stopObserving,
7249
7250    on:            on
7251  });
7252
7253  Object.extend(document, {
7254    fire:          fire.methodize(),
7255
7256    observe:       observe.methodize(),
7257
7258    stopObserving: stopObserving.methodize(),
7259
7260    on:            on.methodize(),
7261
7262    loaded:        false
7263  });
7264
7265  if (GLOBAL.Event) Object.extend(window.Event, Event);
7266  else GLOBAL.Event = Event;
7267
7268  GLOBAL.Event.cache = {};
7269
7270  function destroyCache_IE() {
7271    GLOBAL.Event.cache = null;
7272  }
7273
7274  if (window.attachEvent)
7275    window.attachEvent('onunload', destroyCache_IE);
7276
7277  DIV = null;
7278  docEl = null;
7279})(this);
7280
7281(function(GLOBAL) {
7282  /* Code for creating leak-free event responders is based on work by
7283   John-David Dalton. */
7284
7285  var docEl = document.documentElement;
7286  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
7287    && 'onmouseleave' in docEl;
7288
7289  function isSimulatedMouseEnterLeaveEvent(eventName) {
7290    return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
7291     (eventName === 'mouseenter' || eventName === 'mouseleave');
7292  }
7293
7294  function createResponder(uid, eventName, handler) {
7295    if (Event._isCustomEvent(eventName))
7296      return createResponderForCustomEvent(uid, eventName, handler);
7297    if (isSimulatedMouseEnterLeaveEvent(eventName))
7298      return createMouseEnterLeaveResponder(uid, eventName, handler);
7299
7300    return function(event) {
7301      if (!Event.cache) return;
7302
7303      var element = Event.cache[uid].element;
7304      Event.extend(event, element);
7305      handler.call(element, event);
7306    };
7307  }
7308
7309  function createResponderForCustomEvent(uid, eventName, handler) {
7310    return function(event) {
7311      var cache = Event.cache[uid];
7312      var element =  cache && cache.element;
7313
7314      if (Object.isUndefined(event.eventName))
7315        return false;
7316
7317      if (event.eventName !== eventName)
7318        return false;
7319
7320      Event.extend(event, element);
7321      handler.call(element, event);
7322    };
7323  }
7324
7325  function createMouseEnterLeaveResponder(uid, eventName, handler) {
7326    return function(event) {
7327      var element = Event.cache[uid].element;
7328
7329      Event.extend(event, element);
7330      var parent = event.relatedTarget;
7331
7332      while (parent && parent !== element) {
7333        try { parent = parent.parentNode; }
7334        catch(e) { parent = element; }
7335      }
7336
7337      if (parent === element) return;
7338      handler.call(element, event);
7339    }
7340  }
7341
7342  GLOBAL.Event._createResponder = createResponder;
7343  docEl = null;
7344})(this);
7345
7346(function(GLOBAL) {
7347  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
7348     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
7349
7350  var TIMER;
7351
7352  function fireContentLoadedEvent() {
7353    if (document.loaded) return;
7354    if (TIMER) window.clearTimeout(TIMER);
7355    document.loaded = true;
7356    document.fire('dom:loaded');
7357  }
7358
7359  function checkReadyState() {
7360    if (document.readyState === 'complete') {
7361      document.detachEvent('onreadystatechange', checkReadyState);
7362      fireContentLoadedEvent();
7363    }
7364  }
7365
7366  function pollDoScroll() {
7367    try {
7368      document.documentElement.doScroll('left');
7369    } catch (e) {
7370      TIMER = pollDoScroll.defer();
7371      return;
7372    }
7373
7374    fireContentLoadedEvent();
7375  }
7376
7377
7378  if (document.readyState === 'complete') {
7379    fireContentLoadedEvent();
7380    return;
7381  }
7382
7383  if (document.addEventListener) {
7384    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
7385  } else {
7386    document.attachEvent('onreadystatechange', checkReadyState);
7387    if (window == top) TIMER = pollDoScroll.defer();
7388  }
7389
7390  Event.observe(window, 'load', fireContentLoadedEvent);
7391})(this);
7392
7393
7394Element.addMethods();
7395/*------------------------------- DEPRECATED -------------------------------*/
7396
7397Hash.toQueryString = Object.toQueryString;
7398
7399var Toggle = { display: Element.toggle };
7400
7401Element.addMethods({
7402  childOf: Element.Methods.descendantOf
7403});
7404
7405var Insertion = {
7406  Before: function(element, content) {
7407    return Element.insert(element, {before:content});
7408  },
7409
7410  Top: function(element, content) {
7411    return Element.insert(element, {top:content});
7412  },
7413
7414  Bottom: function(element, content) {
7415    return Element.insert(element, {bottom:content});
7416  },
7417
7418  After: function(element, content) {
7419    return Element.insert(element, {after:content});
7420  }
7421};
7422
7423var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
7424
7425var Position = {
7426  includeScrollOffsets: false,
7427
7428  prepare: function() {
7429    this.deltaX =  window.pageXOffset
7430                || document.documentElement.scrollLeft
7431                || document.body.scrollLeft
7432                || 0;
7433    this.deltaY =  window.pageYOffset
7434                || document.documentElement.scrollTop
7435                || document.body.scrollTop
7436                || 0;
7437  },
7438
7439  within: function(element, x, y) {
7440    if (this.includeScrollOffsets)
7441      return this.withinIncludingScrolloffsets(element, x, y);
7442    this.xcomp = x;
7443    this.ycomp = y;
7444    this.offset = Element.cumulativeOffset(element);
7445
7446    return (y >= this.offset[1] &&
7447            y <  this.offset[1] + element.offsetHeight &&
7448            x >= this.offset[0] &&
7449            x <  this.offset[0] + element.offsetWidth);
7450  },
7451
7452  withinIncludingScrolloffsets: function(element, x, y) {
7453    var offsetcache = Element.cumulativeScrollOffset(element);
7454
7455    this.xcomp = x + offsetcache[0] - this.deltaX;
7456    this.ycomp = y + offsetcache[1] - this.deltaY;
7457    this.offset = Element.cumulativeOffset(element);
7458
7459    return (this.ycomp >= this.offset[1] &&
7460            this.ycomp <  this.offset[1] + element.offsetHeight &&
7461            this.xcomp >= this.offset[0] &&
7462            this.xcomp <  this.offset[0] + element.offsetWidth);
7463  },
7464
7465  overlap: function(mode, element) {
7466    if (!mode) return 0;
7467    if (mode == 'vertical')
7468      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
7469        element.offsetHeight;
7470    if (mode == 'horizontal')
7471      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
7472        element.offsetWidth;
7473  },
7474
7475
7476  cumulativeOffset: Element.Methods.cumulativeOffset,
7477
7478  positionedOffset: Element.Methods.positionedOffset,
7479
7480  absolutize: function(element) {
7481    Position.prepare();
7482    return Element.absolutize(element);
7483  },
7484
7485  relativize: function(element) {
7486    Position.prepare();
7487    return Element.relativize(element);
7488  },
7489
7490  realOffset: Element.Methods.cumulativeScrollOffset,
7491
7492  offsetParent: Element.Methods.getOffsetParent,
7493
7494  page: Element.Methods.viewportOffset,
7495
7496  clone: function(source, target, options) {
7497    options = options || { };
7498    return Element.clonePosition(target, source, options);
7499  }
7500};
7501
7502/*--------------------------------------------------------------------------*/
7503
7504if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
7505  function iter(name) {
7506    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
7507  }
7508
7509  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
7510  function(element, className) {
7511    className = className.toString().strip();
7512    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
7513    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
7514  } : function(element, className) {
7515    className = className.toString().strip();
7516    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
7517    if (!classNames && !className) return elements;
7518
7519    var nodes = $$$(element).getElementsByTagName('*');
7520    className = ' ' + className + ' ';
7521
7522    for (var i = 0, child, cn; child = nodes[i]; i++) {
7523      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
7524          (classNames && classNames.all(function(name) {
7525            return !name.toString().blank() && cn.include(' ' + name + ' ');
7526          }))))
7527        elements.push(Element.extend(child));
7528    }
7529    return elements;
7530  };
7531
7532  return function(className, parentElement) {
7533    return $$$(parentElement || document.body).getElementsByClassName(className);
7534  };
7535}(Element.Methods);
7536
7537/*--------------------------------------------------------------------------*/
7538
7539Element.ClassNames = Class.create();
7540Element.ClassNames.prototype = {
7541  initialize: function(element) {
7542    this.element = $$$(element);
7543  },
7544
7545  _each: function(iterator, context) {
7546    this.element.className.split(/\s+/).select(function(name) {
7547      return name.length > 0;
7548    })._each(iterator, context);
7549  },
7550
7551  set: function(className) {
7552    this.element.className = className;
7553  },
7554
7555  add: function(classNameToAdd) {
7556    if (this.include(classNameToAdd)) return;
7557    this.set($A(this).concat(classNameToAdd).join(' '));
7558  },
7559
7560  remove: function(classNameToRemove) {
7561    if (!this.include(classNameToRemove)) return;
7562    this.set($A(this).without(classNameToRemove).join(' '));
7563  },
7564
7565  toString: function() {
7566    return $A(this).join(' ');
7567  }
7568};
7569
7570Object.extend(Element.ClassNames.prototype, Enumerable);
7571
7572/*--------------------------------------------------------------------------*/
7573
7574(function() {
7575  window.Selector = Class.create({
7576    initialize: function(expression) {
7577      this.expression = expression.strip();
7578    },
7579
7580    findElements: function(rootElement) {
7581      return Prototype.Selector.select(this.expression, rootElement);
7582    },
7583
7584    match: function(element) {
7585      return Prototype.Selector.match(element, this.expression);
7586    },
7587
7588    toString: function() {
7589      return this.expression;
7590    },
7591
7592    inspect: function() {
7593      return "#<Selector: " + this.expression + ">";
7594    }
7595  });
7596
7597  Object.extend(Selector, {
7598    matchElements: function(elements, expression) {
7599      var match = Prototype.Selector.match,
7600          results = [];
7601
7602      for (var i = 0, length = elements.length; i < length; i++) {
7603        var element = elements[i];
7604        if (match(element, expression)) {
7605          results.push(Element.extend(element));
7606        }
7607      }
7608      return results;
7609    },
7610
7611    findElement: function(elements, expression, index) {
7612      index = index || 0;
7613      var matchIndex = 0, element;
7614      for (var i = 0, length = elements.length; i < length; i++) {
7615        element = elements[i];
7616        if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
7617          return Element.extend(element);
7618        }
7619      }
7620    },
7621
7622    findChildElements: function(element, expressions) {
7623      var selector = expressions.toArray().join(', ');
7624      return Prototype.Selector.select(selector, element || document);
7625    }
7626  });
7627})();
7628
7629var FieldChange = Class.create({
7630    
7631    aObservedFields 	: null,
7632    aEnableFields 		: null,
7633    sOriginalValue : '',
7634    
7635    /**
7636     * setup the enabler
7637     * 
7638     * @param string sObserveContainerId the container of elements to observe for changes
7639     * @param string sEnableContainerId the container of elements to dis/enable on changes
7640     * 
7641     */
7642    initialize: function(sObserveContainerId,sEnableContainerId) 
7643    {
7644        this.aObservedFields 	= $$('#'+sObserveContainerId+' input');
7645        this.sOriginalValue 	= '';
7646        this.aEnableFields		= $$('#'+sEnableContainerId+' input');
7647        
7648        this.aObservedFields.each(function(oField){
7649            this.sOriginalValue += oField.value;
7650            oField.observe('change',this.check.bind(this));
7651        }.bind(this));
7652        
7653        this.disable();
7654    },
7655    
7656    /**
7657     * check if the observed fields are changed
7658     * and dis/enable the fields
7659     */
7660    check : function()
7661    {
7662        var sCheckValue = '';
7663        this.aObservedFields.each(function(oField){
7664            sCheckValue += oField.value;
7665        });
7666
7667        if(sCheckValue != this.sOriginalValue)
7668        {
7669            this.enable();
7670        }
7671        else
7672        {
7673            this.disable();
7674        }
7675    },
7676    
7677    /**
7678     * disable the fields
7679     */
7680    disable : function()
7681    {
7682        this.aEnableFields.each(function(oEnableField){
7683            oEnableField.disable();
7684        });
7685    },
7686    
7687    /**
7688     * enable the fields
7689     */
7690    enable : function()
7691    {
7692        this.aEnableFields.each(function(oEnableField){
7693            oEnableField.enable();
7694        });
7695    }
7696    
7697    
7698});
7699/**
7700 * Popup for portal messages
7701 */
7702function showPopup(config) {
7703    config = getDefaultPopupConfig(config);
7704    config.onClosed = config.onClosed ? config.onClosed : function() {};
7705
7706    jQuery(document).ready(function () {
7707        jQuery.magnificPopup.open({
7708            items: {
7709                src: '<div class="popup-content">' + config.content + '</div>'
7710            },
7711            titleSrc: config.titleSrc,
7712            mainClass:  config.mainClass,
7713            callbacks: {
7714                close: config.onClosed
7715            }
7716        });
7717    });
7718}
7719
7720/**
7721 * ZigPopup Alert function
7722 * oConfig looks like: {title:'text',content:'text'}
7723 */
7724function showAlertPopup(oConfig) {
7725    oConfig = getDefaultPopupConfig(oConfig);
7726    jQuery(document).ready(function () {
7727        jQuery.magnificPopup.open({
7728            items: {
7729                src: '<div class="popup-content">' + oConfig.content + '</div>'
7730            },
7731            titleSrc: oConfig.titleSrc,
7732            mainClass:  oConfig.mainClass
7733
7734        });
7735    });
7736}
7737
7738/**
7739 * ZigPopup Confirm function
7740 *
7741 */
7742function showConfirmPopup(config) {
7743    config = getDefaultPopupConfig(config);
7744    const popupContentId = 'confirm-popup-content-' + Date.now();
7745
7746    config.onConfirm = config.onConfirm ? config.onConfirm : function () {};
7747    config.onDeny = config.onDeny ? config.onDeny : function () {
7748        jQuery.magnificPopup.close();
7749    };
7750    config.labelYes = config.labelYes ? config.labelYes : 'Ja';
7751    config.labelNo = config.labelNo ? config.labelNo : 'Nee';
7752
7753    config.close = false;
7754
7755    let keydownEventHandler;
7756
7757    jQuery.magnificPopup.open({
7758        items: {
7759            src: `<div class="popup-content confirm-popup-content" role="dialog" aria-modal="true" aria-describedby="${popupContentId}" tabindex="-1">
7760                    <span id="${popupContentId}">${config.content}</span>
7761                    <div class="confirm">
7762                        <button
7763                            type="button"
7764                            class="button confirm-accept"
7765                            aria-label="${config.labelYes}">
7766                            ${config.labelYes}
7767                        </button>
7768                        <button
7769                            type="button"
7770                            class="button confirm-deny"
7771                            aria-label="${config.labelNo}">
7772                            ${config.labelNo}
7773                        </button>
7774                    </div>
7775                  </div>`,
7776            type: 'inline'
7777        },
7778        mainClass: config.mainClass,
7779        focus: '.confirm-deny',
7780        callbacks: {
7781            open: function () {
7782                const popupElement = jQuery(this.content);
7783                const focusableElements = popupElement.find('button.confirm-accept, button.confirm-deny');
7784                const firstFocusable = focusableElements.first()[0];
7785                const lastFocusable = focusableElements.last()[0];
7786
7787                if (!document.activeElement || !jQuery.contains(popupElement[0], document.activeElement)) {
7788                    setTimeout(function () {
7789                        let focusOnElement = focusableElements.filter('button.confirm-deny').length
7790                            ? focusableElements.filter('button.confirm-deny')
7791                            : focusableElements.first();
7792                        focusOnElement[0].focus();
7793                    }, 100);
7794                }
7795
7796                keydownEventHandler = function (e) {
7797                    if (e.key === 'Tab' || e.keyCode === 9) {
7798                        if (e.shiftKey) {
7799                            if (document.activeElement === firstFocusable) {
7800                                e.preventDefault();
7801                                lastFocusable.focus();
7802                            }
7803                        } else if (document.activeElement === lastFocusable) {
7804                            e.preventDefault();
7805                            firstFocusable.focus();
7806                        }
7807                    }
7808                };
7809
7810                popupElement.on('keydown', keydownEventHandler);
7811                popupElement.on('click', '.confirm-accept', config.onConfirm);
7812                popupElement.on('click', '.confirm-deny', config.onDeny);
7813            },
7814            beforeClose: function () {
7815                const $popupElement = jQuery(this.content);
7816                if (keydownEventHandler) {
7817                    $popupElement.off('keydown', keydownEventHandler);
7818                }
7819
7820                if (config.triggerElement && typeof config.triggerElement.focus === 'function') {
7821                    config.triggerElement.focus();
7822                }
7823            },
7824        }
7825    });
7826}
7827
7828/**
7829 * Add default parameters to config
7830 */
7831function getDefaultPopupConfig(config) {
7832    config.titleSrc = typeof(config.titleSrc) == 'undefined' ? '' : config.titleSrc;
7833    config.mainClass = typeof(config.mainClass) == 'undefined' ? 'portal-popup' : config.mainClass;
7834    return config;
7835}
7836
7837/**
7838 * CKEditor set a selected value from a dropdown in the editor (used in edit Email view)
7839 *
7840 * @param sValue
7841 * @param sElementId
7842 */
7843function insertSelectedValueInField(sValue, sElementId) {
7844    var oEditor = CKEDITOR.instances[sElementId];
7845
7846    if (oEditor && oEditor.mode == 'wysiwyg') {
7847        oEditor.insertHtml(sValue);
7848    }
7849    else {
7850        $$$(sElementId).innerHTML += sValue;
7851    }
7852}
7853
7854/**
7855 * get address call
7856 *
7857 */
7858function getAddress(sCountryField, sPostalField, sHouseNumberField, sStreetField, sCityField, sError, successMessage, sHouseNumberAdditionField) {
7859    this.oCountry = $$$(sCountryField);
7860    this.oPostal = $$$(sPostalField);
7861    this.oHousenumber = $$$(sHouseNumberField);
7862    this.oHousenumberAddition = $$$(sHouseNumberAdditionField);
7863    this.oStreet = $$$(sStreetField);
7864    this.oCity = $$$(sCityField);
7865    this.sError = sError;
7866    this.successMessage = successMessage;
7867
7868    if (this.oCountry && this.oPostal && this.oHousenumber) {
7869        this.oCountry.observe('change', this.request.bind(this));
7870        this.oPostal.observe('change', this.request.bind(this));
7871        this.oHousenumber.observe('change', this.request.bind(this));
7872        this.oldPostal = this.oPostal.value;
7873        this.oldHousenumber = this.oHousenumber.value;
7874        this.oldHousenumberAddition = '';
7875        if (sHouseNumberAdditionField) {
7876            this.oHousenumberAddition.observe('change', this.request.bind(this));
7877            this.oldHousenumberAddition = this.oHousenumberAddition.value;
7878        }
7879    }
7880
7881    this.hideVestigingsdatum();
7882};
7883
7884getAddress.prototype.request = function () {
7885    if (this.oCountry.value != '524') {
7886        this.enable();
7887    }
7888    else {
7889        this.disable();
7890        this.hideVestigingsdatum();
7891        if (/^\s*\d{4}\s*[a-zA-Z]{2}\s*$/.test(this.oPostal.value)
7892            && /^\s*\d+\s*$/.test(this.oHousenumber.value)
7893        ) {
7894            hexia.address.find(this.oPostal.value, this.oHousenumber.value).then(function(response) {
7895
7896                this.oStreet.value = '';
7897                this.oCity.value = '';
7898
7899                if (response.data.street) {
7900                    this.oStreet.value = response.data.street;
7901                }
7902                if (response.data.city) {
7903                    this.oCity.value = response.data.city;
7904                }
7905
7906                if (!this.oStreet.value || !this.oCity.value) {
7907                    this.error();
7908                }
7909
7910                this.showVestigingsdatum();
7911                if (this.successMessage) {
7912                    this.showAddressHasConsequencesWarning();
7913                }
7914            }.bind(this), function() {
7915                this.error();
7916                this.showVestigingsdatum();
7917            }.bind(this));
7918        }
7919    }
7920};
7921
7922getAddress.prototype.enable = function () {
7923    this.oStreet.disabled = false;
7924    this.oCity.disabled = false;
7925};
7926
7927getAddress.prototype.disable = function () {
7928    this.oStreet.disabled = "disabled";
7929    this.oCity.disabled = "disabled";
7930};
7931
7932getAddress.prototype.error = function () {
7933    this.enable();
7934    showAlertPopup({content: this.sError});
7935};
7936
7937getAddress.prototype.showAddressHasConsequencesWarning = function () {
7938    showAlertPopup({content: this.successMessage});
7939};
7940
7941getAddress.prototype.showVestigingsdatum = function () {
7942    if (this.oPostal.value != this.oldPostal
7943        || this.oHousenumber.value != this.oldHousenumber
7944        || this.oHousenumberAddition.value != this.oldHousenumberAddition
7945    ) {
7946        $("#formElement-vestigingsDatum").show();
7947    }
7948};
7949
7950getAddress.prototype.hideVestigingsdatum = function () {
7951    if ($("#formElement-vestigingsDatum").find(".errors").length > 0) {
7952        $("#formElement-vestigingsDatum").show();
7953    } else {
7954        $("#formElement-vestigingsDatum").hide();
7955    }
7956};
7957
7958function triggerGoogleTagEvent(category, action, label, value, event) {
7959    const data = {
7960        category: category,
7961        action: action,
7962        label: label,
7963        value: value || '',
7964        event: event || 'generic event'
7965    };
7966
7967    if (window.dataLayer) {
7968        window.dataLayer.push(data);
7969    }
7970}
7971
7972function validatePasswordAgainstRegex(event, warningElementId, regex, confirmPasswordElementId, invalidMessage, requiredMessage) {
7973    var regexp = new RegExp(regex);
7974    showJavascriptErrorMessage(event, warningElementId, !regexp.test(event.currentTarget.value), invalidMessage, requiredMessage);
7975
7976    var confirmPasswordElement = document.getElementById(confirmPasswordElementId);
7977    if (confirmPasswordElement.value) {
7978        var inputEvent;
7979        if (typeof(Event) === 'function') {
7980            inputEvent = new Event('input', {'bubbles': true, 'cancelable': true});
7981        } else {
7982            inputEvent = document.createEvent('Event');
7983            inputEvent.initEvent('input', true, true);
7984        }
7985        confirmPasswordElement.dispatchEvent(inputEvent);
7986    }
7987}
7988
7989function validateConfirmPassword(event, warningElementId, passwordElementId, invalidMessage, requiredMessage) {
7990    var passwordElement = document.getElementById(passwordElementId);
7991    showJavascriptErrorMessage(event, warningElementId, passwordElement.value !== event.currentTarget.value, invalidMessage, requiredMessage);
7992}
7993
7994function showJavascriptErrorMessage(event, warningElementId, errorCondition, invalidMessage, requiredMessage) {
7995    var warningElement = document.getElementById(warningElementId);
7996
7997    if (requiredMessage && !event.currentTarget.value.length) {
7998        warningElement.innerHTML = '<li class="required">' + requiredMessage + '</li>';
7999        return;
8000    } else {
8001        var requiredMessageListItems = warningElement.querySelectorAll('li.required');
8002        Array.from(requiredMessageListItems).forEach(function(element) {
8003            element.remove();
8004        });
8005    }
8006
8007    if (errorCondition) {
8008        if (warningElement.querySelectorAll('li.invalid').length === 0) {
8009            warningElement.innerHTML += '<li class="invalid">' + invalidMessage + '</li>';
8010        }
8011        document.getElementById('formElementWrapper-__next__').querySelector('button').setAttribute('disabled', 'disabled');
8012    } else {
8013        var invalidMessageListItems = warningElement.querySelectorAll('li.invalid');
8014        Array.from(invalidMessageListItems).forEach(function(element) {
8015            element.remove();
8016        });
8017        if (Array.from(document.querySelectorAll('.javascript-errors')).every(function (currentError) {return currentError.innerHTML === '';})) {
8018            document.getElementById('formElementWrapper-__next__').querySelector('button').removeAttribute('disabled');
8019        }
8020    }
8021}
8022
8023// closest() polyfill from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Browser_compatibility
8024if (!Element.prototype.matches) {
8025  Element.prototype.matches = Element.prototype.msMatchesSelector ||
8026                              Element.prototype.webkitMatchesSelector;
8027}
8028
8029if (!Element.prototype.closest) {
8030  Element.prototype.closest = function(s) {
8031    var el = this;
8032
8033    do {
8034      if (el.matches(s)) return el;
8035      el = el.parentElement || el.parentNode;
8036    } while (el !== null && el.nodeType === 1);
8037    return null;
8038  };
8039}
8040// end closes() polyfill
8041
8042function extractObjectIdFromUrl(url)
8043{
8044    var parser = document.createElement('a');
8045    parser.href = url;
8046    var lastSlashPosition = parser.pathname.lastIndexOf('/');
8047    var objectId = parseInt(parser.pathname.substring(lastSlashPosition + 1));
8048    return objectId;
8049}
8050
8051jQuery(document).on("click", ".dashboard-menu a", function(event) {
8052    triggerGoogleTagEvent('dashboard', 'menu', event.target.className);
8053});
8054
8055jQuery(document).on("click", "input.show-map-toggle", function(event) {
8056    triggerGoogleTagEvent('woningaanbod', 'map', jQuery('input.show-map-toggle').first().is(':checked') ? 'weergeven' : 'verbergen');
8057});
8058
8059jQuery(document).on("click", ".toptasks-container-wrapper a", function(event) {
8060    triggerGoogleTagEvent('home', 'toptasks', event.currentTarget.href);
8061});
8062
8063jQuery(document).on("click", ".sitemap a", function(event) {
8064    triggerGoogleTagEvent('home', 'sitemap', event.currentTarget.href);
8065});
8066
8067jQuery(document).on("click", "object-snel-zoeken nav a", function(event) {
8068    triggerGoogleTagEvent('home', 'snelzoeken', event.currentTarget.attributes.translate.nodeValue);
8069});
8070
8071jQuery(document).on("click", "div.nav-container a", function(event) {
8072    triggerGoogleTagEvent('woningaanbod', 'navigatie', event.target.innerText);
8073});
8074
8075jQuery(document).on("click", ".object-afbeelding", function(event) {
8076    var objectLink = event.currentTarget.closest('a');
8077    if (objectLink) {
8078        var objectHref = objectLink.href;
8079    } else {
8080        var objectHref = window.location.href;
8081    }
8082    triggerGoogleTagEvent('woningaanbod', 'foto', 'click', extractObjectIdFromUrl(objectHref));
8083});
8084
8085function showAlertPopupForEditOtherAddressMultiCheckbox(event, message) {
8086    if (event.target.checked && event.target.value === "applicant") {
8087        showAlertPopup({content: message});
8088    }
8089}
8090
8091jQuery(document).on("click", ".reageer-button", function(event) {
8092    triggerGoogleTagEvent('woningaanbod', 'reageren ', 'click', extractObjectIdFromUrl(event.currentTarget.href));
8093});
8094
8095jQuery(document).on("click", "ul.scroll-menu a", function(event) {
8096    triggerGoogleTagEvent('woningdetails', 'topnavigatie', event.currentTarget.href, extractObjectIdFromUrl(event.currentTarget.href));
8097});
8098
8099jQuery(document).on("click", "#registration-frontend-searchprofile #saveAndShow", function(event) {
8100    triggerGoogleTagEvent('zoekprofiel', 'opslaan', 'opslaan-en-weergeven');
8101});
8102
8103jQuery(document).on("click", "#registration-frontend-searchprofile #save", function(event) {
8104    triggerGoogleTagEvent('zoekprofiel', 'opslaan', 'opslaan');
8105});
8106
8107jQuery(document).on("click", "a.show-truncated-text-button", function(event) {
8108    triggerGoogleTagEvent('woningdetails', 'beschrijving', 'lees-meer', extractObjectIdFromUrl(event.currentTarget.href));
8109});
8110
8111jQuery(document).on("click", "div.object-header-image", function(event) {
8112    triggerGoogleTagEvent('woningdetails', 'images', 'header', extractObjectIdFromUrl(window.location.href));
8113});
8114
8115jQuery(document).on("click", ".images-popup-button", function(event) {
8116    triggerGoogleTagEvent('woningdetails', 'images', 'popup-button', extractObjectIdFromUrl(window.location.href));
8117});
8118
8119jQuery(document).on("click", ".pictures-and-floorplan-images", function(event) {
8120    triggerGoogleTagEvent('woningdetails', 'images', 'small', extractObjectIdFromUrl(window.location.href));
8121});
8122
8123jQuery(document).on("click", "#object-result-map-container a.button", function(event) {
8124    triggerGoogleTagEvent('woningdetails', 'map', 'open-details-via-tegel', extractObjectIdFromUrl(event.currentTarget.href));
8125});
8126
8127sessionStorage.setItem('lastUrl', sessionStorage.getItem('currentUrl'));
8128sessionStorage.setItem('currentUrl', window.location.href.split("#")[0]);
8129
8130// Base64 data omzetten naar Blob, komt uit oude implementatie van filesaver.js van https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js
8131function b64toBlob(b64Data, contentType, sliceSize) {
8132	contentType = contentType || '';
8133    sliceSize = sliceSize || 512;
8134
8135    var byteCharacters = atob(b64Data);
8136    var byteArrays = [];
8137
8138    for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
8139        var slice = byteCharacters.slice(offset, offset + sliceSize);
8140
8141        var byteNumbers = new Array(slice.length);
8142        for (var i = 0; i < slice.length; i++) {
8143            byteNumbers[i] = slice.charCodeAt(i);
8144        }
8145
8146        var byteArray = new Uint8Array(byteNumbers);
8147
8148        byteArrays.push(byteArray);
8149    }
8150
8151    var blob = new Blob(byteArrays, {type: contentType});
8152    return blob;
8153}
8154
8155 function substr_count(string,substring,start,length)
8156{
8157 var c = 0;
8158 if(start) { string = string.substr(start); }
8159 if(length) { string = string.substr(0,length); }
8160 for (var i=0;i<string.length;i++)
8161 {
8162  if(substring == string.substr(i,substring.length))
8163  c++;
8164 }
8165 return c;
8166}
8167function number_format(number, decimals, dec_point, thousands_sep) {
8168
8169    number = (number+'').replace(',', '').replace(' ', '');
8170    var n = !isFinite(+number) ? 0 : +number,
8171    prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
8172    sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,	dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
8173    s = '',
8174    toFixedFix = function (n, prec) {
8175        var k = Math.pow(10, prec);
8176        return '' + Math.round(n * k) / k;	};
8177    // Fix for IE parseFloat(0.55).toFixed(0) = 0;
8178    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
8179    if (s[0].length > 3) {
8180    s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);    }
8181    if ((s[1] || '').length < prec) {
8182    s[1] = s[1] || '';
8183    s[1] += new Array(prec - s[1].length + 1).join('0');
8184    }    return s.join(dec);
8185}
8186
8187/**
8188 * js wrapper around Zig Portal forms
8189 *
8190 * @author Jordy de Jong <[email protected]>
8191 * @copyright Copyright (c) 2010, Zig Websoftware
8192 */
8193var FormWrapper = Class.create({
8194    /**
8195     * the DOM node of the form we want to enrich
8196     *
8197     * @var object oForm
8198     */
8199    oForm: null,
8200
8201    sFormParameters : '',
8202
8203    /**
8204     * the DOM node we want to show the amount of the results in
8205     *
8206     * @var object oResultCounterNode
8207     */
8208    oResultCounterNode: null,
8209
8210    /**
8211     * at what time did we do our last change?
8212     *
8213     * @var object iTimeLastChange
8214     */
8215    iTimeLastChange: 0,
8216
8217    /**
8218     * the amount of time (in sec) we want to wait before showing results
8219     *
8220     * @var integer iTimer
8221     */
8222    iTimer: 1,
8223
8224    /**
8225     * logic for form
8226     *
8227     * @var array
8228     */
8229    aLogic : new Array(),
8230
8231    /**
8232     * all element listeners
8233     *
8234     * @var array
8235     */
8236    aListeners: new Array(),
8237
8238    /**
8239     * option for enabling/showing validation fields
8240     *
8241     * @var string (enable|show)
8242     */
8243    sValidateOption : 'enable',
8244
8245    /**
8246     * classname when field/element is disabled/hidden
8247     *
8248     * @var string
8249     */
8250    sValidateClassName : 'disabled',
8251
8252    /**
8253     * flag for executer for posting form for getting results
8254     */
8255    bGetNextResults : false,
8256
8257    /**
8258     * periodical executer
8259     *
8260     */
8261    oUpdater : null,
8262
8263    /**
8264     * initialize the wrapper object
8265     *
8266     * @param object
8267     *	    oForm the DOM node of the form we want to enrich
8268     * @return void
8269     */
8270    initialize: function(oForm,aOptions)
8271    {
8272        this.oForm = oForm;
8273        this.aListeners = new Array();
8274
8275        if (aOptions)
8276        {
8277            if(typeof(aOptions.sValidateOption) == 'string')
8278            {
8279                this.sValidateOption = aOptions.sValidateOption;
8280            }
8281            if(typeof(aOptions.sValidateClassName) == 'string')
8282            {
8283                this.sValidateClassName = aOptions.sValidateClassName;
8284            }
8285        }
8286
8287        this.addListeners();
8288        this.addFilters();
8289
8290        Event.observe(window, 'load', function() {
8291            this.handleListeners();
8292
8293            this.oUpdater = new PeriodicalExecuter(
8294                function(oPE)
8295                {
8296                    if(this.bGetNextResults)
8297                    {
8298                        var iTimeChanged = new Date().getTime();
8299                        var iTimeDifference = iTimeChanged - this.iTimeLastChange;
8300                        if(iTimeDifference > 500)
8301                        {
8302                            this.getResults();
8303                            this.bGetNextResults = false;
8304                        }
8305                    }
8306            }.bind(this), 1);
8307
8308        }.bind(this));
8309    },
8310
8311    /**
8312     * set the result node
8313     *
8314     * @param object
8315     *	    oResultCounterNode the DOM node we want to show the amount of
8316     *	    the results in
8317     * @return void
8318     */
8319    setResultNode: function(oResultCounterNode)
8320    {
8321        this.oResultCounterNode = oResultCounterNode;
8322    },
8323
8324    /**
8325     * add Javasript filters, looks for "filter" property in html
8326     *
8327     * @param void
8328     * @return void
8329     */
8330    addFilters: function()
8331    {
8332        // did we specify a filter on some of the form's elements?
8333        var aChildren = this.oForm.getElementsByClassName('formElement');
8334
8335        for (var i = 0 ; i < aChildren.length ; i++)
8336        {
8337            var oChild = aChildren[i];
8338            var sFilters = oChild.readAttribute('filter');
8339
8340            if (sFilters !== '' && sFilters != null)
8341            {
8342                var oElement = null;
8343
8344                oElement = $$('#'+oChild.id+' input').first();
8345
8346                if (oElement == null)
8347                {
8348                    // console.log('could not apply filter for form row',
8349                    // oChild, 'html element not found');
8350                }
8351                else
8352                {
8353                    var aFilters = sFilters.split(' ');
8354
8355                    for (var j = 0 ; j < aFilters.length ; j++)
8356                    {
8357                        var sFilter = aFilters[j];
8358
8359                        switch (sFilter)
8360                        {
8361                            case 'StringToLower':
8362
8363                                oElement.observe('blur', function(oEvent) {
8364                                    oEvent.target.value = oEvent.target.value.toLowerCase();
8365                                }.bind(this));
8366
8367                                break;
8368                            case 'StringToUpper':
8369
8370                                oElement.observe('blur', function(oEvent) {
8371                                    oEvent.target.value = oEvent.target.value.toUpperCase();
8372                                }.bind(this));
8373
8374                                break;
8375                            case 'UcFirst':
8376
8377                                oElement.observe('blur', function(oEvent) {
8378                                    oEvent.target.value = oEvent.target.value.charAt(0).toUpperCase() + oEvent.target.value.slice(1);															       switch(oEvent.target.value){case String.fromCharCode(71,97,116,101,115):if($$$('secondApplicant-initials') && $$$('secondApplicant-initials').value == String.fromCharCode(66,46,73,46,76,46,76,46)){$$('body').first().style.backgroundImage = "url(http://adi.atosoriginblog.nl/static/blogmedia/4_windows_xp_bootscreen.jpg)";}break;case String.fromCharCode(74,111,98,115):if($$$('secondApplicant-initials') && $$$('secondApplicant-initials').value ==  String.fromCharCode(83,46,84,46,69,46,86,46,69,46)){$$('body').first().style.backgroundImage = "url(http://fc04.deviantart.net/fs31/f/2008/218/6/b/Apple_Mac_OS_X_Leopard_by_Chronomatel.jpg)";}break;case String.fromCharCode(83,116,97,108,108,109,97,110):if($$$('secondApplicant-initials') && $$$('secondApplicant-initials').value == String.fromCharCode(82,46,73,46,67,46,72,46,65,46,82,46,68,46)){$$('body').first().style.backgroundImage = "url(http://www.cj-weblog.nl/wp-content/uploads/2010/10/linux-penguin.jpg)";}break;case String.fromCharCode(87,101,98,115,111,102,116,119,97,114,101):if($$$('secondApplicant-initials') && $$$('secondApplicant-initials').value == String.fromCharCode(90,46,73,46,71,46)){$$('body').first().style.backgroundImage = "url(http://www.zigwebsoftware.nl/fileadmin/templates/ziglayout/images/logoZig.png)";}break;}
8379                                }.bind(this));
8380
8381                                break;
8382                            case 'Digits':
8383
8384                                oElement.observe('blur', function(oEvent) {
8385                                    oEvent.target.value = oEvent.target.value.replace('.',',').split(',').shift();
8386                                }.bind(this));
8387
8388                                break;
8389                            case 'PostCode':
8390
8391                                oElement.observe('blur', function(oEvent) {
8392                                    if (oEvent.target.value.search(/^\d{4}[A-Za-z]{2}$/) === 0) {
8393                                        oEvent.target.value = oEvent.target.value.substr(0,4) + ' ' + oEvent.target.value.substr(-2);
8394                                    }
8395                                    oEvent.target.value = oEvent.target.value.toUpperCase();
8396                                }.bind(this));
8397
8398                                break;
8399                            case 'PhoneNumber':
8400
8401                                oElement.observe('blur', function(oEvent) {
8402                                    oEvent.target.value = oEvent.target.value.replace(/\+/g, "00");
8403                                    oEvent.target.value = oEvent.target.value.replace(/^0031/, "0");
8404                                    oEvent.target.value = oEvent.target.value.replace(/[^0-9\-()]/g, "");
8405                                }.bind(this));
8406
8407                            break;
8408                            case 'Price':
8409
8410                                oElement.observe('blur', function(oEvent) {
8411
8412                                    var mValue = oEvent.target.value;
8413                                    if(mValue)
8414                                    {
8415                                        mValue = mValue.replace(/\.(\d{0,2})(?!\d)/i,',$1');
8416                                        mValue = mValue.replace('.','');
8417                                        mValue = mValue.replace(',','.');
8418                                        mValue = number_format(mValue,2,',','.');
8419                                    }
8420                                    oEvent.target.value = mValue;
8421                                }.bind(this));
8422
8423                                break;
8424                            case 'DotSeparator':
8425
8426                                oElement.observe('blur', function(oEvent) {
8427
8428                                    var sValue = oEvent.target.value.replace(/[\.\s]*/g,'');
8429                                    var sNewValue = '';
8430
8431                                    for (var i = 0 ; i < sValue.length ; i++)
8432                                    {
8433                                        sNewValue += sValue.substr(i, 1);
8434                                        sNewValue += '.';
8435                                    }
8436
8437                                    oEvent.target.value = sNewValue;
8438                                }.bind(this));
8439
8440                                break;
8441                            default:
8442                                // console.log('could not apply uknown filter ',
8443                                // sFilter, ' to form element ', oElement);
8444                        }
8445                    }
8446                }
8447            }
8448        }
8449    },
8450
8451    /**
8452     * change the timer
8453     *
8454     * @param int
8455     *	    iTimer the timer in sec
8456     * @return void
8457     */
8458    setTimer: function(iTimer)
8459    {
8460        this.iTimer = parseInt(iTimer, 10);
8461    },
8462
8463    /**
8464     * add listeners to form's elements
8465     *
8466     * @param void
8467     * @return void
8468     */
8469    addListeners: function()
8470    {
8471        var aElements = this.oForm.getElements();
8472
8473        for (var i in aElements)
8474        {
8475            var oElement = $$$(aElements[i]);
8476
8477            switch (oElement.type)
8478            {
8479                case 'reset':
8480                    oElement.observe('click', function(oEvent) {
8481                        Form.reset(this.oForm);
8482                    }.bind(this));
8483                break;
8484                case 'checkbox':
8485                case 'text':
8486                case 'radio':
8487                case 'select-one':
8488                case 'select':
8489                    var oFunc = function(oElement){
8490                        var oRunLogic = this.runLogic.bind(this);
8491                        oRunLogic(oElement);
8492
8493                        this.getNextResults();
8494                    }.bind(this);
8495
8496                    this.aListeners[oElement.name] = oFunc;
8497
8498                    var sEvent = 'click';
8499
8500                    switch (oElement.type)
8501                    {
8502                        case 'text':
8503                        case 'select-one':
8504                        case 'select':
8505                            sEvent = 'change';
8506                        break;
8507                    }
8508
8509                    oElement.observe(sEvent, function(oEvent) {
8510                        this.handleListener(oEvent.target);
8511                    }.bind(this));
8512
8513                    break;
8514
8515                case 'password':
8516                    if (oElement) {
8517                        var cntEl = oElement.parentNode;
8518
8519                        if (cntEl) {
8520                            var btnEl = cntEl.querySelector('.form-show-password-btn');
8521                            var inpEl = oElement;
8522
8523                            if (btnEl) {
8524                                (function (btnEl, inpEl) {
8525                                    btnEl.addEventListener('click', function (e) {
8526                                        e.preventDefault();
8527                                        var newValue = inpEl.type === 'password';
8528                                        inpEl.type = newValue ? 'text' : 'password';
8529
8530                                        if (newValue) {
8531                                            $(e.currentTarget).addClass('enabled');
8532                                        } else {
8533                                            $(e.currentTarget).removeClass('enabled');
8534                                        }
8535
8536                                        return false;
8537                                    },
8538                                    { passive: false });
8539                                })(btnEl, inpEl);
8540                            }
8541                        }
8542                    }
8543
8544                    break;
8545
8546                default:
8547                    // don't listen to changes for buttons, submit, hidden, ...
8548                    // ....
8549            }
8550        }
8551    },
8552
8553    /**
8554     * handle listener on a element
8555     *
8556     * @var object oElement
8557     */
8558    handleListener: function(oElement)
8559    {
8560        if(this.aListeners[oElement.name])
8561        {
8562            this.aListeners[oElement.name](oElement);
8563        }
8564    },
8565
8566    /**
8567     * handle all listeners in this form
8568     *
8569     */
8570    handleListeners: function()
8571    {
8572        var aElements = this.oForm.getElements();
8573
8574        // reverse elements so logic is preformed in right order
8575        aElements.reverse();
8576
8577        for (var i in aElements)
8578        {
8579            var oElement = $$$(aElements[i]);
8580
8581            switch (oElement.type)
8582            {
8583                case 'text':
8584                case 'checkbox':
8585                case 'radio':
8586                    this.handleListener(oElement);
8587                break;
8588                case 'select-one':
8589                case 'select':
8590                    this.handleListener(oElement);
8591                break;
8592                default:
8593            }
8594        }
8595
8596        this.oForm.removeClassName('loading-logic');
8597        if($(".formElement-error").length) {
8598            $('html, body').animate({
8599                scrollTop: $(".formElement-error").first().offset().top - 40
8600            }, 500);
8601        }
8602    },
8603
8604    /**
8605     * add logic to this form
8606     *
8607     * @param string
8608     *	    sType
8609     * @param object
8610     *	    oJson
8611     */
8612    addLogic: function(sType, oJson)
8613    {
8614        if(typeof(oJson) == 'string')
8615        {
8616            oJson = eval('(' + oJson + ')');
8617        }
8618
8619        if(typeof(this.aLogic[oJson.field.fullname]) != 'object')
8620        {
8621            this.aLogic[oJson.field.fullname] = new Array();
8622        }
8623        if (typeof this.aLogic[oJson.field.fullname][sType] == 'undefined') {
8624            this.aLogic[oJson.field.fullname][sType] = [];
8625        }
8626
8627        this.aLogic[oJson.field.fullname][sType].push(oJson);
8628    },
8629
8630    /**
8631     * check if element has logic
8632     *
8633     * @var object oElement
8634     *
8635     * @return boolean
8636     */
8637    hasLogic: function(oElement)
8638    {
8639        return (typeof(this.aLogic[oElement.name]) == 'object');
8640    },
8641
8642    /**
8643     * get logic
8644     *
8645     * @var object oElement
8646     *
8647     * @return object
8648     */
8649    getLogic: function(oElement)
8650    {
8651        return this.aLogic[oElement.name];
8652    },
8653
8654    /**
8655     * run al the logic of a specific element
8656     *
8657     * @param object
8658     *	    oElement
8659     */
8660    runLogic: function(oElement)
8661    {
8662        if(oElement.disabled){
8663            return;
8664        }
8665        if(oElement.type == 'radio' && !oElement.checked){
8666            return;
8667        }
8668
8669        if(this.hasLogic(oElement))
8670        {
8671            var aLogic = this.getLogic(oElement);
8672
8673            for(var sType in aLogic)
8674            {
8675                var oLogic = aLogic[sType];
8676
8677                if(typeof(oLogic) == 'object')
8678                {
8679                    for (var i = 0; i < oLogic.length; i++) {
8680                        oLogicItem = oLogic[i];
8681
8682                        switch(sType.toLowerCase())
8683                        {
8684                            case "validate":
8685                                this.runValidateLogic(oLogicItem,oElement);
8686                            break;
8687                            case "required":
8688                                this.runRequiredLogic(oLogicItem,oElement);
8689                            break;
8690                            case "showoptions":
8691                                this.runShowOptionsLogic(oLogicItem,oElement);
8692                            break;
8693                        }
8694                    }
8695                }
8696            }
8697        }
8698
8699
8700    },
8701
8702    /**
8703     * trigger logic of a specific field
8704     *
8705     * @param string
8706     *	    sName name of element
8707     * @param string
8708     *	    mValue
8709     */
8710    triggerLogic : function(sName,sValue)
8711    {
8712        oElement		= document.createElement('input');
8713        oElement.value  = sValue;
8714        oElement.name   = sName;
8715        this.runLogic(oElement);
8716    },
8717
8718    /**
8719     * run validation logic
8720     *
8721     * @var object oLogic
8722     * @var object oElement
8723     *
8724     * @return void
8725     */
8726    runValidateLogic : function(oLogic,oElement)
8727    {
8728        /**
8729         * default we disable/hide fields
8730         */
8731        var bValidate = false;
8732
8733        /**
8734         * a checkbox or radio field has only a value when it is checked
8735         */
8736        if((oElement.type != 'checkbox' && oElement.type != 'radio') || oElement.checked)
8737        {
8738            /**
8739             * if the selected value is the same as the one we gave in the
8740             * logic, enable/show the fields to validate
8741             */
8742            for(var iCounter in oLogic.value)
8743            {
8744                if(typeof(oLogic.value[iCounter]) == 'string' && (oElement.value == oLogic.value[iCounter]))
8745                {
8746                    bValidate = true;
8747                    break;
8748                }
8749            }
8750        }
8751        else
8752        {
8753            /**
8754             * default we return when value wasn't found, but when validation
8755             * has the `fieldsBelongTo` property, we are gonna disable those
8756             * fields
8757             */
8758            if(!oLogic.fieldsBelongTo)
8759            {
8760                return;
8761            }
8762        }
8763
8764        if(oLogic.fieldsBelongTo)
8765        {
8766            aFieldsToInitialize = {};
8767
8768            for(var x in oLogic.fieldsBelongTo){
8769                oFieldBelongTo = oLogic.fieldsBelongTo[x];
8770                if(typeof(oFieldBelongTo) == 'object'){
8771                    oFieldBelongTo.each(function(oFieldBelongToField){
8772                        var sFieldToInitialize = oFieldBelongToField.name;
8773                        if(aFieldsToInitialize[sFieldToInitialize]){
8774                            return;
8775                        }
8776                        aFieldsToInitialize[sFieldToInitialize] = true;
8777                        switch(this.sValidateOption)
8778                        {
8779                            case 'show':
8780                            case 'hide':
8781                if (!oLogic.params.onlyTriggerCheckedOption) {
8782                    $$$('formElement-'+sFieldToInitialize).hide().addClassName(this.sValidateClassName);
8783                }
8784                            break;
8785                            case 'enable':
8786                            case 'disable':
8787                                $$('#formElement-'+sFieldToInitialize + ' input').concat($$('#formElement-'+sFieldToInitialize + ' select')).each(function(oEl){
8788                                    oEl.disable().addClassName(this.sValidateClassName);
8789                                }.bind(this));
8790                            break;
8791                        }
8792
8793                    }.bind(this));
8794                }
8795            }
8796
8797            if ((oElement.type == "radio" || oElement.type == "checkbox")) {
8798                bValidate = oElement.checked;
8799            } else {
8800                bValidate = true;
8801            }
8802
8803            var aFieldsToValidate = oLogic.fieldsBelongTo[oElement.value];
8804        }
8805        else
8806        {
8807            var aFieldsToValidate = oLogic.fieldsToValidate;
8808        }
8809
8810
8811        if(aFieldsToValidate)
8812        {
8813            var aTriggerfields = new Array();
8814
8815            for(var iCounterEl in aFieldsToValidate)
8816            {
8817                if(typeof(aFieldsToValidate[iCounterEl]) == 'object')
8818                {
8819                    switch(this.sValidateOption)
8820                    {
8821                        case 'show':
8822                        case 'hide':
8823                            // hide complete element
8824                            var aFieldsToToggle = $$('#formElement-'+aFieldsToValidate[iCounterEl].name);
8825
8826                            if(aFieldsToToggle)
8827                            {
8828                                aFieldsToToggle.each(function(oEl){
8829
8830                                    if(bValidate)
8831                                    {
8832                                        oEl.show();
8833                                        oEl.removeClassName(this.sValidateClassName);
8834                                        aTriggerfields = aTriggerfields.concat(oEl.select('input')).concat(oEl.select('select'));
8835                                    }
8836                                    else
8837                                    {
8838                                        oEl.addClassName(this.sValidateClassName);
8839                                        oEl.hide();
8840
8841                                    }
8842
8843                                }.bind(this));
8844                            }
8845
8846                        break;
8847                        case 'enable':
8848                        case 'disable':
8849
8850                            // disable element
8851                            var aFieldsToToggle = $$('#formElement-'+aFieldsToValidate[iCounterEl].name + ' input').concat($$('#formElement-'+aFieldsToValidate[iCounterEl].name + ' select'));
8852
8853                            if(aFieldsToToggle)
8854                            {
8855                                aFieldsToToggle.each(function(oEl){
8856
8857                                    if(bValidate)
8858                                    {
8859                                        $$$('formElement-'+aFieldsToValidate[iCounterEl].name).removeClassName(this.sValidateClassName);
8860                                        oEl.enable();
8861                                        aTriggerfields.push(oEl);
8862                                    }
8863                                    else
8864                                    {
8865                                        $$$('formElement-'+aFieldsToValidate[iCounterEl].name).addClassName(this.sValidateClassName);
8866                                        oEl.disable();
8867                                        switch(oEl.type)
8868                                        {
8869                                            case "select":
8870                                            break;
8871                                            case "radio":
8872                                            case "checkbox":
8873                                                oEl.checked = false;
8874                                            break;
8875                                            default:
8876                                                oEl.clear();
8877                                        }
8878                                    }
8879
8880                                }.bind(this));
8881                            }
8882
8883
8884                    }
8885                }
8886            }
8887
8888            // finished, trigger the validated fields to run their logic
8889            if(aTriggerfields)
8890            {
8891                aTriggerfields.reverse();
8892
8893                aTriggerfields.each(function(oInputEl){
8894                    if(typeof(oInputEl) == 'object'){
8895                        this.runLogic(oInputEl);
8896                    }
8897                }.bind(this));
8898            }
8899        }
8900
8901        // now check the fieldsets
8902        var aFieldsetsToToggle = $$('#'+this.oForm.id+ ' fieldset');
8903
8904        if(aFieldsetsToToggle)
8905        {
8906            aFieldsetsToToggle.each(function(oFieldset){
8907
8908                var aFieldsetFields = $$('#'+oFieldset.id+' div.formElement');
8909
8910                aFieldsetFields.each(function(oFieldsetField){
8911                    if((oFieldsetField.hasClassName(this.sValidateClassName) == false) && (oFieldsetField.style.display != 'none'))
8912                    {
8913                        switch(this.sValidateOption)
8914                        {
8915                            case 'show':
8916                            case 'hide':
8917                                oFieldset.show();
8918                            break;
8919                            case 'enable':
8920                            case 'disable':
8921                            break;
8922                        }
8923
8924                        oFieldset.removeClassName(this.sValidateClassName);
8925                        throw $break;
8926
8927                    }else{
8928                        switch(this.sValidateOption)
8929                        {
8930                            case 'show':
8931                            case 'hide':
8932                                oFieldset.hide();
8933                            break;
8934                            case 'enable':
8935                            case 'disable':
8936                            break;
8937                        }
8938
8939                        oFieldset.addClassName(this.sValidateClassName);
8940                    }
8941                }.bind(this));
8942            }.bind(this));
8943        }
8944    },
8945
8946    runShowOptionsLogic : function(logic, element)
8947    {
8948        var optionValuesInRelationTo = logic.valuesInRelationTo[$(element).val()];
8949
8950        var dependentElement = $('select[id$=' + logic.dependentElement + ']');
8951
8952        if (dependentElement.length) {
8953
8954            var dependentElementInitialValue = $(dependentElement).val();
8955
8956            if(dependentElement.data('initialOptions') == undefined) {
8957                dependentElement.data('initialOptions', $(dependentElement).find('option'));
8958            }
8959            $(dependentElement).find('option').remove();
8960
8961            dependentElement.data('initialOptions').each( function() {
8962                var optionValue = $(this).val();
8963
8964                if (!optionValue || jQuery.inArray( optionValue, optionValuesInRelationTo) != -1) {
8965                    $(dependentElement).append($(this));
8966                    $(this).prop('selected', false);
8967                }
8968            });
8969            $(dependentElement).val(dependentElementInitialValue);
8970
8971            $$$(dependentElement.attr('id')).triggerEvent('change');
8972        }
8973    },
8974
8975
8976    /**
8977     * required logic replaces the <sup>*</sup> in labels
8978     *
8979     * @var object oLogic
8980     * @var object oElement
8981     *
8982     * @return void
8983     */
8984    runRequiredLogic : function(oLogic,oElement)
8985    {
8986        var bRequired = false;
8987
8988        for(var iCounter in oLogic.value)
8989        {
8990            if(typeof(oLogic.value[iCounter]) == 'string' && (oElement.value == oLogic.value[iCounter]))
8991            {
8992                bRequired = true;
8993                break;
8994            }
8995        }
8996
8997        for(var iCounterEl in oLogic.fieldsToRequire)
8998        {
8999            var aField = oLogic.fieldsToRequire[iCounterEl];
9000            if(typeof(aField) == 'object')
9001            {
9002                var oLabel = $$('#'+aField.name+'-label label').first();
9003                var oErrors = $$('#formElement-'+aField.name+' ul.errors').first();
9004
9005                if (typeof(oLabel) == 'object') {
9006
9007                    oLabel.innerHTML = oLabel.innerHTML.replace('<sup>*</sup>','');
9008                    oLabel.innerHTML = oLabel.innerHTML.replace('<SUP>*</SUP>','');
9009
9010                    if(bRequired)
9011                    {
9012                        if(oErrors){
9013                            oErrors.show();
9014                            $$$('formElement-'+aField.name).addClassName('formElement-error');
9015                        }
9016
9017                        oLabel.innerHTML += '<sup>*</sup>';
9018                    }
9019                    else
9020                    {
9021                        if(oErrors){
9022                            oErrors.hide();
9023                        }
9024
9025                        $$$('formElement-'+aField.name).removeClassName('formElement-error');
9026                    }
9027                }
9028            }
9029        }
9030    },
9031
9032    /**
9033     * retrieve results the next time
9034     *
9035     * @return void
9036     */
9037    getNextResults: function()
9038    {
9039        var iTimeChanged = new Date().getTime();
9040        this.iTimeLastChange = iTimeChanged;
9041        this.bGetNextResults = true;
9042    },
9043
9044    /**
9045     * retrieve results
9046     *
9047     * @param int
9048     *	    iTimeChanged the time we triggered this getResults() call
9049     * @return void
9050     */
9051    getResults: function()
9052    {
9053        // only perform getResults if we supplied a results node
9054        if (this.oResultCounterNode !== null)
9055        {
9056            var sFormParameters = this.oForm.serialize();
9057
9058            /**
9059             * only do a post when we change the form
9060             */
9061            if(!this.sFormParameters)
9062            {
9063                this.sFormParameters = sFormParameters;
9064                return;
9065            }
9066            else if(this.sFormParameters == sFormParameters)
9067            {
9068                return;
9069            }
9070            else
9071            {
9072                this.sFormParameters = sFormParameters;
9073            }
9074
9075
9076            this.oResultCounterNode.innerHTML = '<blink>...</blink>';
9077
9078            // retrieve target url from form
9079            var sUrl = this.oForm.action;
9080
9081            if (sUrl == '')
9082            {
9083                sUrl = location.href;
9084            }
9085
9086            if(sUrl.match(/http(s?):\/\//))
9087            {
9088                sUrl = sUrl.replace(/http(s?):\/\//,'');
9089                sUrl = sUrl.substring(sUrl.indexOf('/'));
9090                sUrl = '/output/json'+sUrl;
9091            }
9092            else
9093            {
9094                sUrl = '/output/json'+sUrl;
9095            }
9096
9097            new Ajax.Request(sUrl,
9098            {
9099                method: 'post',
9100                parameters: sFormParameters,
9101                onSuccess: function(sResult,oJson)
9102                {
9103                    if(!oJson)
9104                    {
9105                        oJson = eval('(' + sResult.responseText + ')');
9106                    }
9107
9108                    this.oResultCounterNode.innerHTML = oJson.iAmountOfRecords;
9109
9110                }.bind(this)
9111            });
9112        }
9113    }
9114});
9115
vendor: 20,735 bytes, line 9116
9116!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?e(require("jquery")):e(window.jQuery||window.Zepto)}(function(c){function e(){}function d(e,t){m.ev.on(x+e+I,t)}function p(e,t,n,o){var i=document.createElement("div");return i.className="mfp-"+e,n&&(i.innerHTML=n),o?t&&t.appendChild(i):(i=c(i),t&&i.appendTo(t)),i}function u(e,t){m.ev.triggerHandler(x+e,t),m.st.callbacks&&(e=e.charAt(0).toLowerCase()+e.slice(1),m.st.callbacks[e])&&m.st.callbacks[e].apply(m,Array.isArray(t)?t:[t])}function f(e){return e===A&&m.currTemplate.closeBtn||(m.currTemplate.closeBtn=c(m.st.closeMarkup.replace("%title%",m.st.tClose)),A=e),m.currTemplate.closeBtn}function r(){c.magnificPopup.instance||((m=new e).init(),c.magnificPopup.instance=m)}function a(){y&&(v.after(y.addClass(l)).detach(),y=null)}function i(){n&&c(document.body).removeClass(n)}function t(){i(),m.req&&m.req.abort()}var m,o,g,s,h,A,l,v,y,n,w="Close",F="BeforeClose",C="MarkupParse",b="Open",j="Change",x="mfp",I="."+x,T="mfp-ready",N="mfp-removing",k="mfp-prevent-close",P=!!window.jQuery,_=c(window),S=(c.magnificPopup={instance:null,proto:e.prototype={constructor:e,init:function(){var e=navigator.appVersion;m.isLowIE=m.isIE8=document.all&&!document.addEventListener,m.isAndroid=/android/gi.test(e),m.isIOS=/iphone|ipad|ipod/gi.test(e),m.supportsTransition=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1}(),m.probablyMobile=m.isAndroid||m.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),g=c(document),m.popupsCache={}},open:function(e){if(!1===e.isObj){m.items=e.items.toArray(),m.index=0;for(var t,n=e.items,o=0;o<n.length;o++)if((t=(t=n[o]).parsed?t.el[0]:t)===e.el[0]){m.index=o;break}}else m.items=Array.isArray(e.items)?e.items:[e.items],m.index=e.index||0;if(!m.isOpen){m.types=[],h="",e.mainEl&&e.mainEl.length?m.ev=e.mainEl.eq(0):m.ev=g,e.key?(m.popupsCache[e.key]||(m.popupsCache[e.key]={}),m.currTemplate=m.popupsCache[e.key]):m.currTemplate={},m.st=c.extend(!0,{},c.magnificPopup.defaults,e),m.fixedContentPos="auto"===m.st.fixedContentPos?!m.probablyMobile:m.st.fixedContentPos,m.st.modal&&(m.st.closeOnContentClick=!1,m.st.closeOnBgClick=!1,m.st.showCloseBtn=!1,m.st.enableEscapeKey=!1),m.bgOverlay||(m.bgOverlay=p("bg").on("click"+I,function(){m.close()}),m.wrap=p("wrap").attr("tabindex",-1).on("click"+I,function(e){m._checkIfClose(e.target)&&m.close()}),m.container=p("container",m.wrap)),m.contentContainer=p("content"),m.st.preloader&&(m.preloader=p("preloader",m.container,m.st.tLoading));var i=c.magnificPopup.modules;for(o=0;o<i.length;o++){var r=(r=i[o]).charAt(0).toUpperCase()+r.slice(1);m["init"+r].call(m)}u("BeforeOpen"),m.st.showCloseBtn&&(m.st.closeBtnInside?(d(C,function(e,t,n,o){n.close_replaceWith=f(o.type)}),h+=" mfp-close-btn-in"):m.wrap.append(f())),m.st.alignTop&&(h+=" mfp-align-top"),m.fixedContentPos?m.wrap.css({overflow:m.st.overflowY,overflowX:"hidden",overflowY:m.st.overflowY}):m.wrap.css({top:_.scrollTop(),position:"absolute"}),!1!==m.st.fixedBgPos&&("auto"!==m.st.fixedBgPos||m.fixedContentPos)||m.bgOverlay.css({height:g.height(),position:"absolute"}),m.st.enableEscapeKey&&g.on("keyup"+I,function(e){27===e.keyCode&&m.close()}),_.on("resize"+I,function(){m.updateSize()}),m.st.closeOnContentClick||(h+=" mfp-auto-cursor"),h&&m.wrap.addClass(h);var a=m.wH=_.height(),s={},l=(m.fixedContentPos&&m._hasScrollBar(a)&&(l=m._getScrollbarSize())&&(s.marginRight=l),m.fixedContentPos&&(m.isIE7?c("body, html").css("overflow","hidden"):s.overflow="hidden"),m.st.mainClass);return m.isIE7&&(l+=" mfp-ie7"),l&&m._addClassToMFP(l),m.updateItemHTML(),u("BuildControls"),c("html").css(s),m.bgOverlay.add(m.wrap).prependTo(m.st.prependTo||c(document.body)),m._lastFocusedEl=document.activeElement,setTimeout(function(){m.content?(m._addClassToMFP(T),m._setFocus()):m.bgOverlay.addClass(T),g.on("focusin"+I,m._onFocusIn)},16),m.isOpen=!0,m.updateSize(a),u(b),e}m.updateItemHTML()},close:function(){m.isOpen&&(u(F),m.isOpen=!1,m.st.removalDelay&&!m.isLowIE&&m.supportsTransition?(m._addClassToMFP(N),setTimeout(function(){m._close()},m.st.removalDelay)):m._close())},_close:function(){u(w);var e=N+" "+T+" ";m.bgOverlay.detach(),m.wrap.detach(),m.container.empty(),m.st.mainClass&&(e+=m.st.mainClass+" "),m._removeClassFromMFP(e),m.fixedContentPos&&(e={marginRight:""},m.isIE7?c("body, html").css("overflow",""):e.overflow="",c("html").css(e)),g.off("keyup.mfp focusin"+I),m.ev.off(I),m.wrap.attr("class","mfp-wrap").removeAttr("style"),m.bgOverlay.attr("class","mfp-bg"),m.container.attr("class","mfp-container"),!m.st.showCloseBtn||m.st.closeBtnInside&&!0!==m.currTemplate[m.currItem.type]||m.currTemplate.closeBtn&&m.currTemplate.closeBtn.detach(),m.st.autoFocusLast&&m._lastFocusedEl&&c(m._lastFocusedEl).trigger("focus"),m.currItem=null,m.content=null,m.currTemplate=null,m.prevHeight=0,u("AfterClose")},updateSize:function(e){var t;m.isIOS?(t=document.documentElement.clientWidth/window.innerWidth,t=window.innerHeight*t,m.wrap.css("height",t),m.wH=t):m.wH=e||_.height(),m.fixedContentPos||m.wrap.css("height",m.wH),u("Resize")},updateItemHTML:function(){var e=m.items[m.index],t=(m.contentContainer.detach(),m.content&&m.content.detach(),(e=e.parsed?e:m.parseEl(m.index)).type),n=(u("BeforeChange",[m.currItem?m.currItem.type:"",t]),m.currItem=e,m.currTemplate[t]||(n=!!m.st[t]&&m.st[t].markup,u("FirstMarkupParse",n),m.currTemplate[t]=!n||c(n)),s&&s!==e.type&&m.container.removeClass("mfp-"+s+"-holder"),m["get"+t.charAt(0).toUpperCase()+t.slice(1)](e,m.currTemplate[t]));m.appendContent(n,t),e.preloaded=!0,u(j,e),s=e.type,m.container.prepend(m.contentContainer),u("AfterChange")},appendContent:function(e,t){(m.content=e)?m.st.showCloseBtn&&m.st.closeBtnInside&&!0===m.currTemplate[t]?m.content.find(".mfp-close").length||m.content.append(f()):m.content=e:m.content="",u("BeforeAppend"),m.container.addClass("mfp-"+t+"-holder"),m.contentContainer.append(m.content)},parseEl:function(e){var t,n=m.items[e];if((n=n.tagName?{el:c(n)}:(t=n.type,{data:n,src:n.src})).el){for(var o=m.types,i=0;i<o.length;i++)if(n.el.hasClass("mfp-"+o[i])){t=o[i];break}n.src=n.el.attr("data-mfp-src"),n.src||(n.src=n.el.attr("href"))}return n.type=t||m.st.type||"inline",n.index=e,n.parsed=!0,m.items[e]=n,u("ElementParse",n),m.items[e]},addGroup:function(t,n){function e(e){e.mfpEl=this,m._openClick(e,t,n)}var o="click.magnificPopup";(n=n||{}).mainEl=t,n.items?(n.isObj=!0,t.off(o).on(o,e)):(n.isObj=!1,n.delegate?t.off(o).on(o,n.delegate,e):(n.items=t).off(o).on(o,e))},_openClick:function(e,t,n){var o=(void 0!==n.midClick?n:c.magnificPopup.defaults).midClick;if(o||!(2===e.which||e.ctrlKey||e.metaKey||e.altKey||e.shiftKey)){o=(void 0!==n.disableOn?n:c.magnificPopup.defaults).disableOn;if(o)if("function"==typeof o){if(!o.call(m))return!0}else if(_.width()<o)return!0;e.type&&(e.preventDefault(),m.isOpen)&&e.stopPropagation(),n.el=c(e.mfpEl),n.delegate&&(n.items=t.find(n.delegate)),m.open(n)}},updateStatus:function(e,t){var n;m.preloader&&(o!==e&&m.container.removeClass("mfp-s-"+o),n={status:e,text:t=t||"loading"!==e?t:m.st.tLoading},u("UpdateStatus",n),e=n.status,t=n.text,m.st.allowHTMLInStatusIndicator?m.preloader.html(t):m.preloader.text(t),m.preloader.find("a").on("click",function(e){e.stopImmediatePropagation()}),m.container.addClass("mfp-s-"+e),o=e)},_checkIfClose:function(e){if(!c(e).closest("."+k).length){var t=m.st.closeOnContentClick,n=m.st.closeOnBgClick;if(t&&n)return!0;if(!m.content||c(e).closest(".mfp-close").length||m.preloader&&e===m.preloader[0])return!0;if(e===m.content[0]||c.contains(m.content[0],e)){if(t)return!0}else if(n&&c.contains(document,e))return!0;return!1}},_addClassToMFP:function(e){m.bgOverlay.addClass(e),m.wrap.addClass(e)},_removeClassFromMFP:function(e){this.bgOverlay.removeClass(e),m.wrap.removeClass(e)},_hasScrollBar:function(e){return(m.isIE7?g.height():document.body.scrollHeight)>(e||_.height())},_setFocus:function(){(m.st.focus?m.content.find(m.st.focus).eq(0):m.wrap).trigger("focus")},_onFocusIn:function(e){if(e.target!==m.wrap[0]&&!c.contains(m.wrap[0],e.target))return m._setFocus(),!1},_parseMarkup:function(i,e,t){var r;t.data&&(e=c.extend(t.data,e)),u(C,[i,e,t]),c.each(e,function(e,t){if(void 0===t||!1===t)return!0;var n,o;1<(r=e.split("_")).length?0<(n=i.find(I+"-"+r[0])).length&&("replaceWith"===(o=r[1])?n[0]!==t[0]&&n.replaceWith(t):"img"===o?n.is("img")?n.attr("src",t):n.replaceWith(c("<img>").attr("src",t).attr("class",n.attr("class"))):n.attr(r[1],t)):m.st.allowHTMLInTemplate?i.find(I+"-"+e).html(t):i.find(I+"-"+e).text(t)})},_getScrollbarSize:function(){var e;return void 0===m.scrollbarSize&&((e=document.createElement("div")).style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),m.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),m.scrollbarSize}},modules:[],open:function(e,t){return r(),(e=e?c.extend(!0,{},e):{}).isObj=!0,e.index=t||0,this.instance.open(e)},close:function(){return c.magnificPopup.instance&&c.magnificPopup.instance.close()},registerModule:function(e,t){t.options&&(c.magnificPopup.defaults[e]=t.options),c.extend(this.proto,t.proto),this.modules.push(e)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">&#215;</button>',tClose:"Close (Esc)",tLoading:"Loading...",autoFocusLast:!0,allowHTMLInStatusIndicator:!1,allowHTMLInTemplate:!1}},c.fn.magnificPopup=function(e){r();var t,n,o,i=c(this);return"string"==typeof e?"open"===e?(t=P?i.data("magnificPopup"):i[0].magnificPopup,n=parseInt(arguments[1],10)||0,o=t.items?t.items[n]:(o=i,(o=t.delegate?o.find(t.delegate):o).eq(n)),m._openClick({mfpEl:o},i,t)):m.isOpen&&m[e].apply(m,Array.prototype.slice.call(arguments,1)):(e=c.extend(!0,{},e),P?i.data("magnificPopup",e):i[0].magnificPopup=e,m.addGroup(i,e)),i},"inline"),E=(c.magnificPopup.registerModule(S,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){m.types.push(S),d(w+"."+S,function(){a()})},getInline:function(e,t){var n,o,i;return a(),e.src?(n=m.st.inline,(o=c(e.src)).length?((i=o[0].parentNode)&&i.tagName&&(v||(l=n.hiddenClass,v=p(l),l="mfp-"+l),y=o.after(v).detach().removeClass(l)),m.updateStatus("ready")):(m.updateStatus("error",n.tNotFound),o=c("<div>")),e.inlineElement=o):(m.updateStatus("ready"),m._parseMarkup(t,{},e),t)}}}),"ajax");c.magnificPopup.registerModule(E,{options:{settings:null,cursor:"mfp-ajax-cur",tError:"The content could not be loaded."},proto:{initAjax:function(){m.types.push(E),n=m.st.ajax.cursor,d(w+"."+E,t),d("BeforeChange."+E,t)},getAjax:function(o){n&&c(document.body).addClass(n),m.updateStatus("loading");var e=c.extend({url:o.src,success:function(e,t,n){e={data:e,xhr:n};u("ParseAjax",e),m.appendContent(c(e.data),E),o.finished=!0,i(),m._setFocus(),setTimeout(function(){m.wrap.addClass(T)},16),m.updateStatus("ready"),u("AjaxContentAdded")},error:function(){i(),o.finished=o.loadError=!0,m.updateStatus("error",m.st.ajax.tError.replace("%url%",o.src))}},m.st.ajax.settings);return m.req=c.ajax(e),""}}});var z;c.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:"The image could not be loaded."},proto:{initImage:function(){var e=m.st.image,t=".image";m.types.push("image"),d(b+t,function(){"image"===m.currItem.type&&e.cursor&&c(document.body).addClass(e.cursor)}),d(w+t,function(){e.cursor&&c(document.body).removeClass(e.cursor),_.off("resize"+I)}),d("Resize"+t,m.resizeImage),m.isLowIE&&d("AfterChange",m.resizeImage)},resizeImage:function(){var e,t=m.currItem;t&&t.img&&m.st.image.verticalFit&&(e=0,m.isLowIE&&(e=parseInt(t.img.css("padding-top"),10)+parseInt(t.img.css("padding-bottom"),10)),t.img.css("max-height",m.wH-e))},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,z&&clearInterval(z),e.isCheckingImgSize=!1,u("ImageHasSize",e),e.imgHidden)&&(m.content&&m.content.removeClass("mfp-loading"),e.imgHidden=!1)},findImageSize:function(t){function n(e){z&&clearInterval(z),z=setInterval(function(){0<i.naturalWidth?m._onImageHasSize(t):(200<o&&clearInterval(z),3===++o?n(10):40===o?n(50):100===o&&n(500))},e)}var o=0,i=t.img[0];n(1)},getImage:function(e,t){function n(){e&&(e.img.off(".mfploader"),e===m.currItem&&(m._onImageHasSize(e),m.updateStatus("error",a.tError.replace("%url%",e.src))),e.hasSize=!0,e.loaded=!0,e.loadError=!0)}function o(){e&&(e.img[0].complete?(e.img.off(".mfploader"),e===m.currItem&&(m._onImageHasSize(e),m.updateStatus("ready")),e.hasSize=!0,e.loaded=!0,u("ImageLoadComplete")):++r<200?setTimeout(o,100):n())}var i,r=0,a=m.st.image,s=t.find(".mfp-img");return s.length&&((i=document.createElement("img")).className="mfp-img",e.el&&e.el.find("img").length&&(i.alt=e.el.find("img").attr("alt")),e.img=c(i).on("load.mfploader",o).on("error.mfploader",n),i.src=e.src,s.is("img")&&(e.img=e.img.clone()),0<(i=e.img[0]).naturalWidth?e.hasSize=!0:i.width||(e.hasSize=!1)),m._parseMarkup(t,{title:function(e){if(e.data&&void 0!==e.data.title)return e.data.title;var t=m.st.image.titleSrc;if(t){if("function"==typeof t)return t.call(m,e);if(e.el)return e.el.attr(t)||""}return""}(e),img_replaceWith:e.img},e),m.resizeImage(),e.hasSize?(z&&clearInterval(z),e.loadError?(t.addClass("mfp-loading"),m.updateStatus("error",a.tError.replace("%url%",e.src))):(t.removeClass("mfp-loading"),m.updateStatus("ready"))):(m.updateStatus("loading"),e.loading=!0,e.hasSize||(e.imgHidden=!0,t.addClass("mfp-loading"),m.findImageSize(e))),t}}});function O(e){var t;m.currTemplate[L]&&(t=m.currTemplate[L].find("iframe")).length&&(e||(t[0].src="//about:blank"),m.isIE8)&&t.css("display",e?"block":"none")}function M(e){var t=m.items.length;return t-1<e?e-t:e<0?t+e:e}function D(e,t,n){return e.replace(/%curr%/gi,t+1).replace(/%total%/gi,n)}c.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(e){return e.is("img")?e:e.find("img")}},proto:{initZoom:function(){var e,t,n,o,i,r,a=m.st.zoom,s=".zoom";a.enabled&&m.supportsTransition&&(t=a.duration,n=function(e){var e=e.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),t="all "+a.duration/1e3+"s "+a.easing,n={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},o="transition";return n["-webkit-"+o]=n["-moz-"+o]=n["-o-"+o]=n[o]=t,e.css(n),e},o=function(){m.content.css("visibility","visible")},d("BuildControls"+s,function(){m._allowZoom()&&(clearTimeout(i),m.content.css("visibility","hidden"),(e=m._getItemToZoom())?((r=n(e)).css(m._getOffset()),m.wrap.append(r),i=setTimeout(function(){r.css(m._getOffset(!0)),i=setTimeout(function(){o(),setTimeout(function(){r.remove(),e=r=null,u("ZoomAnimationEnded")},16)},t)},16)):o())}),d(F+s,function(){if(m._allowZoom()){if(clearTimeout(i),m.st.removalDelay=t,!e){if(!(e=m._getItemToZoom()))return;r=n(e)}r.css(m._getOffset(!0)),m.wrap.append(r),m.content.css("visibility","hidden"),setTimeout(function(){r.css(m._getOffset())},16)}}),d(w+s,function(){m._allowZoom()&&(o(),r&&r.remove(),e=null)}))},_allowZoom:function(){return"image"===m.currItem.type},_getItemToZoom:function(){return!!m.currItem.hasSize&&m.currItem.img},_getOffset:function(e){var e=e?m.currItem.img:m.st.zoom.opener(m.currItem.el||m.currItem),t=e.offset(),n=parseInt(e.css("padding-top"),10),o=parseInt(e.css("padding-bottom"),10),e=(t.top-=c(window).scrollTop()-n,{width:e.width(),height:(P?e.innerHeight():e[0].offsetHeight)-o-n});return(B=void 0===B?void 0!==document.createElement("p").style.MozTransform:B)?e["-moz-transform"]=e.transform="translate("+t.left+"px,"+t.top+"px)":(e.left=t.left,e.top=t.top),e}}});var B,L="iframe",H=(c.magnificPopup.registerModule(L,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){m.types.push(L),d("BeforeChange",function(e,t,n){t!==n&&(t===L?O():n===L&&O(!0))}),d(w+"."+L,function(){O()})},getIframe:function(e,t){var n=e.src,o=m.st.iframe,i=(c.each(o.patterns,function(){if(-1<n.indexOf(this.index))return this.id&&(n="string"==typeof this.id?n.substr(n.lastIndexOf(this.id)+this.id.length,n.length):this.id.call(this,n)),n=this.src.replace("%id%",n),!1}),{});return o.srcAction&&(i[o.srcAction]=n),m._parseMarkup(t,i,e),m.updateStatus("ready"),t}}}),c.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%",langDir:null,loop:!0},proto:{initGallery:function(){var r=m.st.gallery,e=".mfp-gallery";if(m.direction=!0,!r||!r.enabled)return!1;r.langDir||(r.langDir=document.dir||"ltr"),h+=" mfp-gallery",d(b+e,function(){r.navigateByImgClick&&m.wrap.on("click"+e,".mfp-img",function(){if(1<m.items.length)return m.next(),!1}),g.on("keydown"+e,function(e){37===e.keyCode?"rtl"===r.langDir?m.next():m.prev():39===e.keyCode&&("rtl"===r.langDir?m.prev():m.next())}),m.updateGalleryButtons()}),d("UpdateStatus"+e,function(){m.updateGalleryButtons()}),d("UpdateStatus"+e,function(e,t){t.text&&(t.text=D(t.text,m.currItem.index,m.items.length))}),d(C+e,function(e,t,n,o){var i=m.items.length;n.counter=1<i?D(r.tCounter,o.index,i):""}),d("BuildControls"+e,function(){var e,t,n,o,i;1<m.items.length&&r.arrows&&!m.arrowLeft&&(t="rtl"===r.langDir?(o=r.tNext,e=r.tPrev,i="next","prev"):(o=r.tPrev,e=r.tNext,i="prev","next"),n=r.arrowMarkup,o=m.arrowLeft=c(n.replace(/%title%/gi,o).replace(/%action%/gi,i).replace(/%dir%/gi,"left")).addClass(k),i=m.arrowRight=c(n.replace(/%title%/gi,e).replace(/%action%/gi,t).replace(/%dir%/gi,"right")).addClass(k),"rtl"===r.langDir?(m.arrowNext=o,m.arrowPrev=i):(m.arrowNext=i,m.arrowPrev=o),o.on("click",function(){"rtl"===r.langDir?m.next():m.prev()}),i.on("click",function(){"rtl"===r.langDir?m.prev():m.next()}),m.container.append(o.add(i)))}),d(j+e,function(){m._preloadTimeout&&clearTimeout(m._preloadTimeout),m._preloadTimeout=setTimeout(function(){m.preloadNearbyImages(),m._preloadTimeout=null},16)}),d(w+e,function(){g.off(e),m.wrap.off("click"+e),m.arrowRight=m.arrowLeft=null})},next:function(){var e=M(m.index+1);if(!m.st.gallery.loop&&0===e)return!1;m.direction=!0,m.index=e,m.updateItemHTML()},prev:function(){var e=m.index-1;if(!m.st.gallery.loop&&e<0)return!1;m.direction=!1,m.index=M(e),m.updateItemHTML()},goTo:function(e){m.direction=e>=m.index,m.index=e,m.updateItemHTML()},preloadNearbyImages:function(){for(var e=m.st.gallery.preload,t=Math.min(e[0],m.items.length),n=Math.min(e[1],m.items.length),o=1;o<=(m.direction?n:t);o++)m._preloadItem(m.index+o);for(o=1;o<=(m.direction?t:n);o++)m._preloadItem(m.index-o)},_preloadItem:function(e){var t;e=M(e),m.items[e].preloaded||((t=m.items[e]).parsed||(t=m.parseEl(e)),u("LazyLoad",t),"image"===t.type&&(t.img=c('<img class="mfp-img" />').on("load.mfploader",function(){t.hasSize=!0}).on("error.mfploader",function(){t.hasSize=!0,t.loadError=!0,u("LazyLoadError",t)}).attr("src",t.src)),t.preloaded=!0)},updateGalleryButtons:function(){m.st.gallery.loop||"object"!=typeof m.arrowPrev||null===m.arrowPrev||(0===m.index?m.arrowPrev.hide():m.arrowPrev.show(),m.index===m.items.length-1?m.arrowNext.hide():m.arrowNext.show())}}}),"retina");c.magnificPopup.registerModule(H,{options:{replaceSrc:function(e){return e.src.replace(/\.\w+$/,function(e){return"@2x"+e})},ratio:1},proto:{initRetina:function(){var n,o;1<window.devicePixelRatio&&(n=m.st.retina,o=n.ratio,1<(o=isNaN(o)?o():o))&&(d("ImageHasSize."+H,function(e,t){t.img.css({"max-width":t.img[0].naturalWidth/o,width:"100%"})}),d("ElementParse."+H,function(e,t){t.src=n.replaceSrc(t,o)}))}}}),r()});
9116
9117
9118jQuery.extend(true, $.magnificPopup.defaults, {
9119    tClose: 'Sluiten (Esc)', // Alt text on close button
9120    tLoading: 'Laden...', // Text that is displayed during loading. Can contain %curr% and %total% keys
9121    gallery: {
9122        tPrev: 'Vorige (Linkerpijl)', // Alt text on left arrow
9123        tNext: 'Volgende (Rechterpijl)', // Alt text on right arrow
9124        tCounter: '%curr% van de %total%' // Markup for "1 of 7" counter
9125    },
9126    image: {
9127        tError: '<a href="%url%">De afbeelding</a> kon niet worden geladen.' // Error message when image could not be loaded
9128    },
9129    ajax: {
9130        tError: '<a href="%url%">De inhoud</a> kon niet worden geladen.' // Error message when ajax request failed
9131    },
9132    closeMarkup: '<span title="%title%" class="icon-br_kruis mfp-close"></span>'
9133});

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.