PageSourceSearch

https://www.baer-galvanik.de/packages/tc-www-main.js?cached201804021033

js baer-galvanik.de collected 2026-10-07 05:08:07 UTC 137,012 bytes, 3,313 lines download raw bytes

1if (window.tcc_package_tcsmainjavascript===undefined) {
2 var tcc_package_tcsmainjavascript=1;
3/** Start: main.js */
4if(window.tc_Consts===undefined){var tc_Consts={debug:false,loadParam:"cached20080104135822"}}document.getStyleSheets=function(){var links=[],css=[];links=document.getElementsByTagName("link");for(var i=0,length=links.length;i<length;i++){if(links[i].type=="text/css"){css.push(links[i])}}return css};document.getJavascripts=function(){var js=[],scripts=[];scripts=document.getElementsByTagName("script");for(var i=0,length=scripts.length;i<length;i++){if(typeof scripts[i].src=="string"){js.push(scripts[i])}}return js};document.getFavicon=function(){var links;links=document.getElementsByTagName("link");for(var i=0;i<links.length;i++){if(links[i]["rel"]===undefined){continue}if(links[i].rel.indexOf("icon")>-1){return links[i]}}return null};document.setFavicon=function(href,type){var head,favicon;if(type===undefined){type="image/x-icon"}head=document.getElementsByTagName("head")[0];favicon=document.getFavicon();if(favicon){$(favicon).remove()}favicon=document.createElement("link");favicon.type=type;favicon.rel=("shortcut icon");favicon.href=href;head.appendChild(favicon)};document.addCSS=function(id,css){if($(id)){$(id).remove()}var style=document.createElement("style");style.type="text/css";style.id=id;document.getElementsByTagName("head")[0].appendChild(style);if(Prototype.Browser.IE){style.styleSheet.cssText=css}else{var node=document.createTextNode("\n<!--\n"+css+"\n-->\n");style.appendChild(node)}};var tc_Loader={_domready:false,_idCounter:1,_initialized:false,_loaded:{},_loading:false,proxyPath:"/proxy",requestOptions:{},_initialize:function(){tc_Loader._initialized=true;var replace=document.location.protocol+"//"+document.location.hostname;var types=[{files:document.getJavascripts(),src:"src"},{files:document.getStyleSheets(),src:"href"}];for(var type=0;type<types.length;type++){var files=types[type].files;var src;for(var i=0;i<files.length;i++){src=files[i][types[type].src].replace(replace,"");src=src.replace("&"+tc_Consts.loadParam,"");src=src.replace("?"+tc_Consts.loadParam,"");if(tc_Loader._loaded[src]!==undefined){continue}if(!files[i].id){tc_Loader._loaded[src]=files[i].id="tc_loaded_"+(tc_Loader._idCounter++)}}}},_ajaxLoad:function(path,callback,onload,async){tc_Loader._loading=true;if(window.tc_Loading!==undefined){tc_Loading.add({get:function(set){set(tc_Loader._loading)}})}if(path.indexOf("/")!==0&&path.indexOf(document.location.protocol+"//"+document.location.hostname)!==0){path=tc_Loader.proxyPath+"?file="+encodeURIComponent(path)}var options=tc_Loader.requestOptions;options.asynchronous=async;options.evaluate=false;options.method="get";options.onComplete=function(request){tc_Loader._loading=false};options.onSuccess=function(request){callback(request);if(onload!==undefined){onload()}};new Ajax.Request(path,options)},_loadStyleSheet:function(path,id,onload,async){if(async===undefined){async=false}callback=function(request){var element=$(id);if(element){element.remove()}document.addCSS(id,request.responseText)};tc_Loader._ajaxLoad(path,callback,onload,async)},_loadJavascript:function(path,id,onload){if(tc_Loader._domready===true){callback=function(request){var s=document.createElement("script");s.type="text/javascript";s.text=request.responseText;s.id=id;s.defer=true;document.getElementsByTagName("head")[0].appendChild(s)};tc_Loader._ajaxLoad(path,callback,onload,false)}else{if(window.XMLHttpRequest===undefined){var temp=new Image();temp.src=path}document.writeln('<script src="'+path+'" id="'+id+'" type="text/javascript"><\/script>')}},isLoaded:function(path){if(tc_Loader._initialized===false){tc_Loader._domready=(document.getElementsByTagName("body").length>0);if(tc_Loader._domready===true){tc_Loader._initialize()}}return tc_Loader._loaded[path]!==undefined},load:function(path,reload,onload,async){if(tc_Loader._initialized===false){tc_Loader._domready=(document.getElementsByTagName("body").length>0);if(tc_Loader._domready===true){tc_Loader._initialize()}}if(reload===undefined||tc_Loader._domready===false){reload=false}var loaded=tc_Loader.isLoaded(path);if(reload===false&&loaded===true){return }var id=tc_Loader._loaded[path];if(id===undefined){id=tc_Loader._loaded[path]="tc_loaded_"+(tc_Loader._idCounter++)}var separator="?";if(path.indexOf("?")!==-1){separator="&"}path+=separator+tc_Consts.loadParam;if(loaded===true){var time=new Date();path+="&"+time.getTime()}if(path.indexOf(".css")!==-1){tc_Loader._loadStyleSheet(path,id,onload,async)}else{if(loaded===true){var element=$(id);element.remove()}tc_Loader._loadJavascript(path,id,onload)}},unload:function(path){if(tc_Loader._loaded[path]!==undefined){$(tc_Loader._loaded[path]).remove();tc_Loader._loaded[path]=undefined}}};function tc_load(path,reload,onload,async){if(tc_load._bc===undefined){if(tc_load.proxyPath!==undefined){tc_Loader.proxyPath=tc_load.proxyPath;tc_load._bc=true}if(tc_load.requestOptions!==undefined){tc_Loader.requestOptions=tc_load.requestOptions;tc_load._bc=true}}if(async===undefined){async=onload===undefined}tc_Loader.load(path,reload,onload,async)}function tc_unload(path){tc_Loader.unload(path)}if(window.Protoype===undefined){if (window.tcc_package_tcsmainjavascript === undefined) {tc_load("/packages/tc-www-main.js");}}if(window.tc_ElementSubject===undefined){if (window.tcc_package_tcsmainjavascript === undefined) {tc_load("/packages/tc-www-main.js");}}function tc_Mouseover(){this.mouseposition=tc_MousePosition.getInstance();this.mouseposition.addObserver(this)}tc_Mouseover.instance=null;tc_Mouseover.prototype.elements=[];tc_Mouseover.prototype.mouseposition=null;tc_Mouseover.getInstance=function(){if(this.instance===null){this.instance=new tc_Mouseover()}return this.instance};tc_Mouseover.prototype.removeElement=function(element){var length=this.elements.length;var index;for(var i=0;i<length;i++){if(this.elements[i]===undefined){continue}if(this.elements[i].element==element){index=i;break}}delete this.elements[index]};tc_Mouseover.prototype.addElement=function(element,overFunc,outFunc,tolerance,multiple){if(tolerance===undefined){tolerance=0}if(multiple===undefined){multiple=true}this.elements.push({element:element,overFunc:overFunc,outFunc:outFunc,tolerance:tolerance,multiple:multiple,status:null})};tc_Mouseover.prototype.update=function(x,y,e){var element,positions,elementX1,elementX2,elementY1,elementY2,elements,length;elements=this.elements;length=elements.length;for(var i=0;i<length;i++){if(elements[i]===undefined){continue}element=$(elements[i].element);if(element===undefined||element===null||element.visible()===false){continue}positions=Position.cumulativeOffset(element);elementX1=positions[0]-elements[i].tolerance;elementX2=positions[0]+Element.getWidth(element)+elements[i].tolerance;elementY1=positions[1]-elements[i].tolerance;elementY2=positions[1]+Element.getHeight(element)+elements[i].tolerance;if(elementX1<=x&&elementX2>=x&&elementY1<=y&&elementY2>=y){if(elements[i].multiple===true||elements[i].status!=="over"){elements[i].status="over";elements[i].overFunc(element,e)}}else{if(elements[i].multiple===true||elements[i].status!=="out"){elements[i].status="out";elements[i].outFunc(element,e)}}}};function tc_MousePosition(){var instance=this;Event.observe(document.getElementsByTagName("html")[0],"mousemove",function(e){instance._position(e)})}tc_MousePosition.instance=null;tc_MousePosition.prototype.positionX=0;tc_MousePosition.prototype.positionY=0;tc_MousePosition.prototype.observers=[];tc_MousePosition.getInstance=function(){if(this.instance===null){this.instance=new tc_MousePosition()}return this.instance};tc_MousePosition.prototype.addObserver=function(observer){this.observers.push(observer)};tc_MousePosition.prototype.getX=function(){return this.positionX};tc_MousePosition.prototype.getY=function(){return this.positionY};tc_MousePosition.prototype._position=function(e){this.positionX=Event.pointerX(e);this.positionY=Event.pointerY(e);for(var i=0,length=this.observers.length;i<length;i++){this.observers[i].update(this.positionX,this.positionY,e)}};if(window.tc_PageSize===undefined){if (window.tcc_package_tcsmainjavascript === undefined) {tc_load("/packages/tc-www-main.js");}}function tc_build_url(url,nodes){var string="";if(url!==undefined){string+=url}if(nodes!==undefined){if(string.substr(-1)!="/"){string+="/"}for(var i=0;i<nodes.length;i++){string+=nodes[i]+(i+1!=nodes.length?"/":"")}}return string}if(window.tc_translations===undefined){var tc_translations={}}
4function tc_translate(key){if(tc_translations[key]===undefined){tc_translations[key]="{"+key+"}"}return tc_translations[key]};
5
6/** End: main.js */
7/** Start: prototype.js */
8/*  Prototype JavaScript framework, version 1.5.1.1
9 *  (c) 2005-2007 Sam Stephenson
10 *
11 *  Prototype is freely distributable under the terms of an MIT-style license.
12 *  For details, see the Prototype web site: http://www.prototypejs.org/
13 *
14/*--------------------------------------------------------------------------*/
15
16var Prototype = {
17  Version: '1.5.1.1',
18
19  Browser: {
20    IE:     !!(window.attachEvent && !window.opera),
21    Opera:  !!window.opera,
22    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
23    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
24  },
25
26  BrowserFeatures: {
27    XPath: !!document.evaluate,
28    ElementExtensions: !!window.HTMLElement,
29    SpecificElementExtensions:
30      (document.createElement('div').__proto__ !==
31       document.createElement('form').__proto__)
32  },
33
34  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
35  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
36
37  emptyFunction: function() { },
38  K: function(x) { return x }
39}
40
41var Class = {
42  create: function() {
43    return function() {
44      this.initialize.apply(this, arguments);
45    }
46  }
47}
48
49var Abstract = new Object();
50
51Object.extend = function(destination, source) {
52  for (var property in source) {
53    destination[property] = source[property];
54  }
55  return destination;
56}
57
58Object.extend(Object, {
59  inspect: function(object) {
60    try {
61      if (object === undefined) return 'undefined';
62      if (object === null) return 'null';
63      return object.inspect ? object.inspect() : object.toString();
64    } catch (e) {
65      if (e instanceof RangeError) return '...';
66      throw e;
67    }
68  },
69
70  toJSON: function(object) {
71    var type = typeof object;
72    switch(type) {
73      case 'undefined':
74      case 'function':
75      case 'unknown': return;
76      case 'boolean': return object.toString();
77    }
78    if (object === null) return 'null';
79    if (object.toJSON) return object.toJSON();
80    if (object.ownerDocument === document) return;
81    var results = [];
82    for (var property in object) {
83      var value = Object.toJSON(object[property]);
84      if (value !== undefined)
85        results.push(property.toJSON() + ': ' + value);
86    }
87    return '{' + results.join(', ') + '}';
88  },
89
90  keys: function(object) {
91    var keys = [];
92    for (var property in object)
93      keys.push(property);
94    return keys;
95  },
96
97  values: function(object) {
98    var values = [];
99    for (var property in object)
100      values.push(object[property]);
101    return values;
102  },
103
104  clone: function(object) {
105    return Object.extend({}, object);
106  }
107});
108
109Function.prototype.bind = function() {
110  var __method = this, args = $A(arguments), object = args.shift();
111  return function() {
112    return __method.apply(object, args.concat($A(arguments)));
113  }
114}
115
116Function.prototype.bindAsEventListener = function(object) {
117  var __method = this, args = $A(arguments), object = args.shift();
118  return function(event) {
119    return __method.apply(object, [event || window.event].concat(args));
120  }
121}
122
123Object.extend(Number.prototype, {
124  toColorPart: function() {
125    return this.toPaddedString(2, 16);
126  },
127
128  succ: function() {
129    return this + 1;
130  },
131
132  times: function(iterator) {
133    $R(0, this, true).each(iterator);
134    return this;
135  },
136
137  toPaddedString: function(length, radix) {
138    var string = this.toString(radix || 10);
139    return '0'.times(length - string.length) + string;
140  },
141
142  toJSON: function() {
143    return isFinite(this) ? this.toString() : 'null';
144  }
145});
146
147Date.prototype.toJSON = function() {
148  return '"' + this.getFullYear() + '-' +
149    (this.getMonth() + 1).toPaddedString(2) + '-' +
150    this.getDate().toPaddedString(2) + 'T' +
151    this.getHours().toPaddedString(2) + ':' +
152    this.getMinutes().toPaddedString(2) + ':' +
153    this.getSeconds().toPaddedString(2) + '"';
154};
155
156var Try = {
157  these: function() {
158    var returnValue;
159
160    for (var i = 0, length = arguments.length; i < length; i++) {
161      var lambda = arguments[i];
162      try {
163        returnValue = lambda();
164        break;
165      } catch (e) {}
166    }
167
168    return returnValue;
169  }
170}
171
172/*--------------------------------------------------------------------------*/
173
174var PeriodicalExecuter = Class.create();
175PeriodicalExecuter.prototype = {
176  initialize: function(callback, frequency) {
177    this.callback = callback;
178    this.frequency = frequency;
179    this.currentlyExecuting = false;
180
181    this.registerCallback();
182  },
183
184  registerCallback: function() {
185    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
186  },
187
188  stop: function() {
189    if (!this.timer) return;
190    clearInterval(this.timer);
191    this.timer = null;
192  },
193
194  onTimerEvent: function() {
195    if (!this.currentlyExecuting) {
196      try {
197        this.currentlyExecuting = true;
198        this.callback(this);
199      } finally {
200        this.currentlyExecuting = false;
201      }
202    }
203  }
204}
205Object.extend(String, {
206  interpret: function(value) {
207    return value == null ? '' : String(value);
208  },
209  specialChar: {
210    '\b': '\\b',
211    '\t': '\\t',
212    '\n': '\\n',
213    '\f': '\\f',
214    '\r': '\\r',
215    '\\': '\\\\'
216  }
217});
218
219Object.extend(String.prototype, {
220  gsub: function(pattern, replacement) {
221    var result = '', source = this, match;
222    replacement = arguments.callee.prepareReplacement(replacement);
223
224    while (source.length > 0) {
225      if (match = source.match(pattern)) {
226        result += source.slice(0, match.index);
227        result += String.interpret(replacement(match));
228        source  = source.slice(match.index + match[0].length);
229      } else {
230        result += source, source = '';
231      }
232    }
233    return result;
234  },
235
236  sub: function(pattern, replacement, count) {
237    replacement = this.gsub.prepareReplacement(replacement);
238    count = count === undefined ? 1 : count;
239
240    return this.gsub(pattern, function(match) {
241      if (--count < 0) return match[0];
242      return replacement(match);
243    });
244  },
245
246  scan: function(pattern, iterator) {
247    this.gsub(pattern, iterator);
248    return this;
249  },
250
251  truncate: function(length, truncation) {
252    length = length || 30;
253    truncation = truncation === undefined ? '...' : truncation;
254    return this.length > length ?
255      this.slice(0, length - truncation.length) + truncation : this;
256  },
257
258  strip: function() {
259    return this.replace(/^\s+/, '').replace(/\s+$/, '');
260  },
261
262  stripTags: function() {
263    return this.replace(/<\/?[^>]+>/gi, '');
264  },
265
266  stripScripts: function() {
267    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
268  },
269
270  extractScripts: function() {
271    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
272    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
273    return (this.match(matchAll) || []).map(function(scriptTag) {
274      if(scriptTag.indexOf('<script type="application/ld+json">') != -1) {
275          // skip this script type (external module via API)
276      }else {
277          return (scriptTag.match(matchOne) || ['', ''])[1];
278      }
279    });
280  },
281
282  evalScripts: function() {
283    return this.extractScripts().map(function(script) { return eval(script) });
284  },
285
286  escapeHTML: function() {
287    var self = arguments.callee;
288    self.text.data = this;
289    return self.div.innerHTML;
290  },
291
292  unescapeHTML: function() {
293    var div = document.createElement('div');
294    div.innerHTML = this.stripTags();
295    return div.childNodes[0] ? (div.childNodes.length > 1 ?
296      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
297      div.childNodes[0].nodeValue) : '';
298  },
299
300  toQueryParams: function(separator) {
301    var match = this.strip().match(/([^?#]*)(#.*)?$/);
302    if (!match) return {};
303
304    return match[1].split(separator || '&').inject({}, function(hash, pair) {
305      if ((pair = pair.split('='))[0]) {
306        var key = decodeURIComponent(pair.shift());
307        var value = pair.length > 1 ? pair.join('=') : pair[0];
308        if (value != undefined) value = decodeURIComponent(value);
309
310        if (key in hash) {
311          if (hash[key].constructor != Array) hash[key] = [hash[key]];
312          hash[key].push(value);
313        }
314        else hash[key] = value;
315      }
316      return hash;
317    });
318  },
319
320  toArray: function() {
321    return this.split('');
322  },
323
324  succ: function() {
325    return this.slice(0, this.length - 1) +
326      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
327  },
328
329  times: function(count) {
330    var result = '';
331    for (var i = 0; i < count; i++) result += this;
332    return result;
333  },
334
335  camelize: function() {
336    var parts = this.split('-'), len = parts.length;
337    if (len == 1) return parts[0];
338
339    var camelized = this.charAt(0) == '-'
340      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
341      : parts[0];
342
343    for (var i = 1; i < len; i++)
344      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
345
346    return camelized;
347  },
348
349  capitalize: function() {
350    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
351  },
352
353  underscore: function() {
354    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
355  },
356
357  dasherize: function() {
358    return this.gsub(/_/,'-');
359  },
360
361  inspect: function(useDoubleQuotes) {
362    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
363      var character = String.specialChar[match[0]];
364      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
365    });
366    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
367    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
368  },
369
370  toJSON: function() {
371    return this.inspect(true);
372  },
373
374  unfilterJSON: function(filter) {
375    return this.sub(filter || Prototype.JSONFilter, '#{1}');
376  },
377
378  isJSON: function() {
379    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
380    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
381  },
382
383  evalJSON: function(sanitize) {
384    var json = this.unfilterJSON();
385    try {
386      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
387    } catch (e) { }
388    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
389  },
390
391  include: function(pattern) {
392    return this.indexOf(pattern) > -1;
393  },
394
395  startsWith: function(pattern) {
396    return this.indexOf(pattern) === 0;
397  },
398
399  endsWith: function(pattern) {
400    var d = this.length - pattern.length;
401    return d >= 0 && this.lastIndexOf(pattern) === d;
402  },
403
404  empty: function() {
405    return this == '';
406  },
407
408  blank: function() {
409    return /^\s*$/.test(this);
410  }
411});
412
413if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
414  escapeHTML: function() {
415    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
416  },
417  unescapeHTML: function() {
418    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
419  }
420});
421
422String.prototype.gsub.prepareReplacement = function(replacement) {
423  if (typeof replacement == 'function') return replacement;
424  var template = new Template(replacement);
425  return function(match) { return template.evaluate(match) };
426}
427
428String.prototype.parseQuery = String.prototype.toQueryParams;
429
430Object.extend(String.prototype.escapeHTML, {
431  div:  document.createElement('div'),
432  text: document.createTextNode('')
433});
434
435with (String.prototype.escapeHTML) div.appendChild(text);
436
437var Template = Class.create();
438Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
439Template.prototype = {
440  initialize: function(template, pattern) {
441    this.template = template.toString();
442    this.pattern  = pattern || Template.Pattern;
443  },
444
445  evaluate: function(object) {
446    return this.template.gsub(this.pattern, function(match) {
447      var before = match[1];
448      if (before == '\\') return match[2];
449      return before + String.interpret(object[match[3]]);
450    });
451  }
452}
453
454var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
455
456var Enumerable = {
457  each: function(iterator) {
458    var index = 0;
459    try {
460      this._each(function(value) {
461        iterator(value, index++);
462      });
463    } catch (e) {
464      if (e != $break) throw e;
465    }
466    return this;
467  },
468
469  eachSlice: function(number, iterator) {
470    var index = -number, slices = [], array = this.toArray();
471    while ((index += number) < array.length)
472      slices.push(array.slice(index, index+number));
473    return slices.map(iterator);
474  },
475
476  all: function(iterator) {
477    var result = true;
478    this.each(function(value, index) {
479      result = result && !!(iterator || Prototype.K)(value, index);
480      if (!result) throw $break;
481    });
482    return result;
483  },
484
485  any: function(iterator) {
486    var result = false;
487    this.each(function(value, index) {
488      if (result = !!(iterator || Prototype.K)(value, index))
489        throw $break;
490    });
491    return result;
492  },
493
494  collect: function(iterator) {
495    var results = [];
496    this.each(function(value, index) {
497      results.push((iterator || Prototype.K)(value, index));
498    });
499    return results;
500  },
501
502  detect: function(iterator) {
503    var result;
504    this.each(function(value, index) {
505      if (iterator(value, index)) {
506        result = value;
507        throw $break;
508      }
509    });
510    return result;
511  },
512
513  findAll: function(iterator) {
514    var results = [];
515    this.each(function(value, index) {
516      if (iterator(value, index))
517        results.push(value);
518    });
519    return results;
520  },
521
522  grep: function(pattern, iterator) {
523    var results = [];
524    this.each(function(value, index) {
525      var stringValue = value.toString();
526      if (stringValue.match(pattern))
527        results.push((iterator || Prototype.K)(value, index));
528    })
529    return results;
530  },
531
532  include: function(object) {
533    var found = false;
534    this.each(function(value) {
535      if (value == object) {
536        found = true;
537        throw $break;
538      }
539    });
540    return found;
541  },
542
543  inGroupsOf: function(number, fillWith) {
544    fillWith = fillWith === undefined ? null : fillWith;
545    return this.eachSlice(number, function(slice) {
546      while(slice.length < number) slice.push(fillWith);
547      return slice;
548    });
549  },
550
551  inject: function(memo, iterator) {
552    this.each(function(value, index) {
553      memo = iterator(memo, value, index);
554    });
555    return memo;
556  },
557
558  invoke: function(method) {
559    var args = $A(arguments).slice(1);
560    return this.map(function(value) {
561      return value[method].apply(value, args);
562    });
563  },
564
565  max: function(iterator) {
566    var result;
567    this.each(function(value, index) {
568      value = (iterator || Prototype.K)(value, index);
569      if (result == undefined || value >= result)
570        result = value;
571    });
572    return result;
573  },
574
575  min: function(iterator) {
576    var result;
577    this.each(function(value, index) {
578      value = (iterator || Prototype.K)(value, index);
579      if (result == undefined || value < result)
580        result = value;
581    });
582    return result;
583  },
584
585  partition: function(iterator) {
586    var trues = [], falses = [];
587    this.each(function(value, index) {
588      ((iterator || Prototype.K)(value, index) ?
589        trues : falses).push(value);
590    });
591    return [trues, falses];
592  },
593
594  pluck: function(property) {
595    var results = [];
596    this.each(function(value, index) {
597      results.push(value[property]);
598    });
599    return results;
600  },
601
602  reject: function(iterator) {
603    var results = [];
604    this.each(function(value, index) {
605      if (!iterator(value, index))
606        results.push(value);
607    });
608    return results;
609  },
610
611  sortBy: function(iterator) {
612    return this.map(function(value, index) {
613      return {value: value, criteria: iterator(value, index)};
614    }).sort(function(left, right) {
615      var a = left.criteria, b = right.criteria;
616      return a < b ? -1 : a > b ? 1 : 0;
617    }).pluck('value');
618  },
619
620  toArray: function() {
621    return this.map();
622  },
623
624  zip: function() {
625    var iterator = Prototype.K, args = $A(arguments);
626    if (typeof args.last() == 'function')
627      iterator = args.pop();
628
629    var collections = [this].concat(args).map($A);
630    return this.map(function(value, index) {
631      return iterator(collections.pluck(index));
632    });
633  },
634
635  size: function() {
636    return this.toArray().length;
637  },
638
639  inspect: function() {
640    return '#<Enumerable:' + this.toArray().inspect() + '>';
641  }
642}
643
644Object.extend(Enumerable, {
645  map:     Enumerable.collect,
646  find:    Enumerable.detect,
647  select:  Enumerable.findAll,
648  member:  Enumerable.include,
649  entries: Enumerable.toArray
650});
651var $A = Array.from = function(iterable) {
652  if (!iterable) return [];
653  if (iterable.toArray) {
654    return iterable.toArray();
655  } else {
656    var results = [];
657    for (var i = 0, length = iterable.length; i < length; i++)
658      results.push(iterable[i]);
659    return results;
660  }
661}
662
663if (Prototype.Browser.WebKit) {
664  $A = Array.from = function(iterable) {
665    if (!iterable) return [];
666    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
667      iterable.toArray) {
668      return iterable.toArray();
669    } else {
670      var results = [];
671      for (var i = 0, length = iterable.length; i < length; i++)
672        results.push(iterable[i]);
673      return results;
674    }
675  }
676}
677
678Object.extend(Array.prototype, Enumerable);
679
680if (!Array.prototype._reverse)
681  Array.prototype._reverse = Array.prototype.reverse;
682
683Object.extend(Array.prototype, {
684  _each: function(iterator) {
685    for (var i = 0, length = this.length; i < length; i++)
686      iterator(this[i]);
687  },
688
689  clear: function() {
690    this.length = 0;
691    return this;
692  },
693
694  first: function() {
695    return this[0];
696  },
697
698  last: function() {
699    return this[this.length - 1];
700  },
701
702  compact: function() {
703    return this.select(function(value) {
704      return value != null;
705    });
706  },
707
708  flatten: function() {
709    return this.inject([], function(array, value) {
710      return array.concat(value && value.constructor == Array ?
711        value.flatten() : [value]);
712    });
713  },
714
715  without: function() {
716    var values = $A(arguments);
717    return this.select(function(value) {
718      return !values.include(value);
719    });
720  },
721
722  indexOf: function(object) {
723    for (var i = 0, length = this.length; i < length; i++)
724      if (this[i] == object) return i;
725    return -1;
726  },
727
728  reverse: function(inline) {
729    return (inline !== false ? this : this.toArray())._reverse();
730  },
731
732  reduce: function() {
733    return this.length >
733 1 ? this : this[0];
734  },
735
736  uniq: function(sorted) {
737    return this.inject([], function(array, value, index) {
738      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
739        array.push(value);
740      return array;
741    });
742  },
743
744  clone: function() {
745    return [].concat(this);
746  },
747
748  size: function() {
749    return this.length;
750  },
751
752  inspect: function() {
753    return '[' + this.map(Object.inspect).join(', ') + ']';
754  },
755
756  toJSON: function() {
757    var results = [];
758    this.each(function(object) {
759      var value = Object.toJSON(object);
760      if (value !== undefined) results.push(value);
761    });
762    return '[' + results.join(', ') + ']';
763  }
764});
765
766Array.prototype.toArray = Array.prototype.clone;
767
768function $w(string) {
769  string = string.strip();
770  return string ? string.split(/\s+/) : [];
771}
772
773if (Prototype.Browser.Opera){
774  Array.prototype.concat = function() {
775    var array = [];
776    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
777    for (var i = 0, length = arguments.length; i < length; i++) {
778      if (arguments[i].constructor == Array) {
779        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
780          array.push(arguments[i][j]);
781      } else {
782        array.push(arguments[i]);
783      }
784    }
785    return array;
786  }
787}
788var Hash = function(object) {
789  if (object instanceof Hash) this.merge(object);
790  else Object.extend(this, object || {});
791};
792
793Object.extend(Hash, {
794  toQueryString: function(obj) {
795    var parts = [];
796    parts.add = arguments.callee.addPair;
797
798    this.prototype._each.call(obj, function(pair) {
799      if (!pair.key) return;
800      var value = pair.value;
801
802      if (value && typeof value == 'object') {
803        if (value.constructor == Array) value.each(function(value) {
804          parts.add(pair.key, value);
805        });
806        return;
807      }
808      parts.add(pair.key, value);
809    });
810
811    return parts.join('&');
812  },
813
814  toJSON: function(object) {
815    var results = [];
816    this.prototype._each.call(object, function(pair) {
817      var value = Object.toJSON(pair.value);
818      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
819    });
820    return '{' + results.join(', ') + '}';
821  }
822});
823
824Hash.toQueryString.addPair = function(key, value, prefix) {
825  key = encodeURIComponent(key);
826  if (value === undefined) this.push(key);
827  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
828}
829
830Object.extend(Hash.prototype, Enumerable);
831Object.extend(Hash.prototype, {
832  _each: function(iterator) {
833    for (var key in this) {
834      var value = this[key];
835      if (value && value == Hash.prototype[key]) continue;
836
837      var pair = [key, value];
838      pair.key = key;
839      pair.value = value;
840      iterator(pair);
841    }
842  },
843
844  keys: function() {
845    return this.pluck('key');
846  },
847
848  values: function() {
849    return this.pluck('value');
850  },
851
852  merge: function(hash) {
853    return $H(hash).inject(this, function(mergedHash, pair) {
854      mergedHash[pair.key] = pair.value;
855      return mergedHash;
856    });
857  },
858
859  remove: function() {
860    var result;
861    for(var i = 0, length = arguments.length; i < length; i++) {
862      var value = this[arguments[i]];
863      if (value !== undefined){
864        if (result === undefined) result = value;
865        else {
866          if (result.constructor != Array) result = [result];
867          result.push(value)
868        }
869      }
870      delete this[arguments[i]];
871    }
872    return result;
873  },
874
875  toQueryString: function() {
876    return Hash.toQueryString(this);
877  },
878
879  inspect: function() {
880    return '#<Hash:{' + this.map(function(pair) {
881      return pair.map(Object.inspect).join(': ');
882    }).join(', ') + '}>';
883  },
884
885  toJSON: function() {
886    return Hash.toJSON(this);
887  }
888});
889
890function $H(object) {
891  if (object instanceof Hash) return object;
892  return new Hash(object);
893};
894
895// Safari iterates over shadowed properties
896if (function() {
897  var i = 0, Test = function(value) { this.key = value };
898  Test.prototype.key = 'foo';
899  for (var property in new Test('bar')) i++;
900  return i > 1;
901}()) Hash.prototype._each = function(iterator) {
902  var cache = [];
903  for (var key in this) {
904    var value = this[key];
905    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
906    cache.push(key);
907    var pair = [key, value];
908    pair.key = key;
909    pair.value = value;
910    iterator(pair);
911  }
912};
913ObjectRange = Class.create();
914Object.extend(ObjectRange.prototype, Enumerable);
915Object.extend(ObjectRange.prototype, {
916  initialize: function(start, end, exclusive) {
917    this.start = start;
918    this.end = end;
919    this.exclusive = exclusive;
920  },
921
922  _each: function(iterator) {
923    var value = this.start;
924    while (this.include(value)) {
925      iterator(value);
926      value = value.succ();
927    }
928  },
929
930  include: function(value) {
931    if (value < this.start)
932      return false;
933    if (this.exclusive)
934      return value < this.end;
935    return value <= this.end;
936  }
937});
938
939var $R = function(start, end, exclusive) {
940  return new ObjectRange(start, end, exclusive);
941}
942
943var Ajax = {
944  getTransport: function() {
945    return Try.these(
946      function() {return new XMLHttpRequest()},
947      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
948      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
949    ) || false;
950  },
951
952  activeRequestCount: 0
953}
954
955Ajax.Responders = {
956  responders: [],
957
958  _each: function(iterator) {
959    this.responders._each(iterator);
960  },
961
962  register: function(responder) {
963    if (!this.include(responder))
964      this.responders.push(responder);
965  },
966
967  unregister: function(responder) {
968    this.responders = this.responders.without(responder);
969  },
970
971  dispatch: function(callback, request, transport, json) {
972    this.each(function(responder) {
973      if (typeof responder[callback] == 'function') {
974        try {
975          responder[callback].apply(responder, [request, transport, json]);
976        } catch (e) {}
977      }
978    });
979  }
980};
981
982Object.extend(Ajax.Responders, Enumerable);
983
984Ajax.Responders.register({
985  onCreate: function() {
986    Ajax.activeRequestCount++;
987  },
988  onComplete: function() {
989    Ajax.activeRequestCount--;
990  }
991});
992
993Ajax.Base = function() {};
994Ajax.Base.prototype = {
995  setOptions: function(options) {
996    this.options = {
997      method:       'post',
998      asynchronous: true,
999      contentType:  'application/x-www-form-urlencoded',
1000      encoding:     'UTF-8',
1001      parameters:   ''
1002    }
1003    Object.extend(this.options, options || {});
1004
1005    this.options.method = this.options.method.toLowerCase();
1006    if (typeof this.options.parameters == 'string')
1007      this.options.parameters = this.options.parameters.toQueryParams();
1008  }
1009}
1010
1011Ajax.Request = Class.create();
1012Ajax.Request.Events =
1013  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1014
1015Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
1016  _complete: false,
1017
1018  initialize: function(url, options) {
1019    this.transport = Ajax.getTransport();
1020    this.setOptions(options);
1021    this.request(url);
1022  },
1023
1024  request: function(url) {
1025    this.url = url;
1026    this.method = this.options.method;
1027    var params = Object.clone(this.options.parameters);
1028
1029    if (!['get', 'post'].include(this.method)) {
1030      // simulate other verbs over post
1031      params['_method'] = this.method;
1032      this.method = 'post';
1033    }
1034
1035    this.parameters = params;
1036
1037    if (params = Hash.toQueryString(params)) {
1038      // when GET, append parameters to URL
1039      if (this.method == 'get')
1040        this.url += (this.url.include('?') ? '&' : '?') + params;
1041      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1042        params += '&_=';
1043    }
1044
1045    try {
1046      if (this.options.onCreate) this.options.onCreate(this.transport);
1047      Ajax.Responders.dispatch('onCreate', this, this.transport);
1048
1049      this.transport.open(this.method.toUpperCase(), this.url,
1050        this.options.asynchronous);
1051
1052      if (this.options.asynchronous)
1053        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
1054
1055      this.transport.onreadystatechange = this.onStateChange.bind(this);
1056      this.setRequestHeaders();
1057
1058      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1059      this.transport.send(this.body);
1060
1061      /* Force Firefox to handle ready state 4 for synchronous requests */
1062      if (!this.options.asynchronous && this.transport.overrideMimeType)
1063        this.onStateChange();
1064
1065    }
1066    catch (e) {
1067      this.dispatchException(e);
1068    }
1069  },
1070
1071  onStateChange: function() {
1072    var readyState = this.transport.readyState;
1073    if (readyState > 1 && !((readyState == 4) && this._complete))
1074      this.respondToReadyState(this.transport.readyState);
1075  },
1076
1077  setRequestHeaders: function() {
1078    var headers = {
1079      'X-Requested-With': 'XMLHttpRequest',
1080      'X-Prototype-Version': Prototype.Version,
1081      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1082    };
1083
1084    if (this.method == 'post') {
1085      headers['Content-type'] = this.options.contentType +
1086        (this.options.encoding ? '; charset=' + this.options.encoding : '');
1087
1088      /* Force "Connection: close" for older Mozilla browsers to work
1089       * around a bug where XMLHttpRequest sends an incorrect
1090       * Content-length header. See Mozilla Bugzilla #246651.
1091       */
1092      if (this.transport.overrideMimeType &&
1093          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1094            headers['Connection'] = 'close';
1095    }
1096
1097    // user-defined headers
1098    if (typeof this.options.requestHeaders == 'object') {
1099      var extras = this.options.requestHeaders;
1100
1101      if (typeof extras.push == 'function')
1102        for (var i = 0, length = extras.length; i < length; i += 2)
1103          headers[extras[i]] = extras[i+1];
1104      else
1105        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1106    }
1107
1108    for (var name in headers)
1109      this.transport.setRequestHeader(name, headers[name]);
1110  },
1111
1112  success: function() {
1113    return !this.transport.status
1114        || (this.transport.status >= 200 && this.transport.status < 300);
1115  },
1116
1117  respondToReadyState: function(readyState) {
1118    var state = Ajax.Request.Events[readyState];
1119    var transport = this.transport, json = this.evalJSON();
1120
1121    if (state == 'Complete') {
1122      try {
1123        this._complete = true;
1124        (this.options['on' + this.transport.status]
1125         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1126         || Prototype.emptyFunction)(transport, json);
1127      } catch (e) {
1128        this.dispatchException(e);
1129      }
1130
1131      var contentType = this.getHeader('Content-type');
1132      if (contentType && contentType.strip().
1133        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
1134          this.evalResponse();
1135    }
1136
1137    try {
1138      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
1139      Ajax.Responders.dispatch('on' + state, this, transport, json);
1140    } catch (e) {
1141      this.dispatchException(e);
1142    }
1143
1144    if (state == 'Complete') {
1145      // avoid memory leak in MSIE: clean up
1146      this.transport.onreadystatechange = Prototype.emptyFunction;
1147    }
1148  },
1149
1150  getHeader: function(name) {
1151    try {
1152      return this.transport.getResponseHeader(name);
1153    } catch (e) { return null }
1154  },
1155
1156  evalJSON: function() {
1157    try {
1158      var json = this.getHeader('X-JSON');
1159      return json ? json.evalJSON() : null;
1160    } catch (e) { return null }
1161  },
1162
1163  evalResponse: function() {
1164    try {
1165      return eval((this.transport.responseText || '').unfilterJSON());
1166    } catch (e) {
1167      this.dispatchException(e);
1168    }
1169  },
1170
1171  dispatchException: function(exception) {
1172    (this.options.onException || Prototype.emptyFunction)(this, exception);
1173    Ajax.Responders.dispatch('onException', this, exception);
1174  }
1175});
1176
1177Ajax.Updater = Class.create();
1178
1179Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
1180  initialize: function(container, url, options) {
1181    this.container = {
1182      success: (container.success || container),
1183      failure: (container.failure || (container.success ? null : container))
1184    }
1185
1186    this.transport = Ajax.getTransport();
1187    this.setOptions(options);
1188
1189    var onComplete = this.options.onComplete || Prototype.emptyFunction;
1190    this.options.onComplete = (function(transport, param) {
1191      this.updateContent();
1192      onComplete(transport, param);
1193    }).bind(this);
1194
1195    this.request(url);
1196  },
1197
1198  updateContent: function() {
1199    var receiver = this.container[this.success() ? 'success' : 'failure'];
1200    var response = this.transport.responseText;
1201
1202    if (!this.options.evalScripts) response = response.stripScripts();
1203
1204    if (receiver = $(receiver)) {
1205      if (this.options.insertion)
1206        new this.options.insertion(receiver, response);
1207      else
1208        receiver.update(response);
1209    }
1210
1211    if (this.success()) {
1212      if (this.onComplete)
1213        setTimeout(this.onComplete.bind(this), 10);
1214    }
1215  }
1216});
1217
1218Ajax.PeriodicalUpdater = Class.create();
1219Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
1220  initialize: function(container, url, options) {
1221    this.setOptions(options);
1222    this.onComplete = this.options.onComplete;
1223
1224    this.frequency = (this.options.frequency || 2);
1225    this.decay = (this.options.decay || 1);
1226
1227    this.updater = {};
1228    this.container = container;
1229    this.url = url;
1230
1231    this.start();
1232  },
1233
1234  start: function() {
1235    this.options.onComplete = this.updateComplete.bind(this);
1236    this.onTimerEvent();
1237  },
1238
1239  stop: function() {
1240    this.updater.options.onComplete = undefined;
1241    clearTimeout(this.timer);
1242    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1243  },
1244
1245  updateComplete: function(request) {
1246    if (this.options.decay) {
1247      this.decay = (request.responseText == this.lastText ?
1248        this.decay * this.options.decay : 1);
1249
1250      this.lastText = request.responseText;
1251    }
1252    this.timer = setTimeout(this.onTimerEvent.bind(this),
1253      this.decay * this.frequency * 1000);
1254  },
1255
1256  onTimerEvent: function() {
1257    this.updater = new Ajax.Updater(this.container, this.url, this.options);
1258  }
1259});
1260function $(element) {
1261  if (arguments.length > 1) {
1262    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1263      elements.push($(arguments[i]));
1264    return elements;
1265  }
1266  if (typeof element == 'string')
1267    element = document.getElementById(element);
1268  return Element.extend(element);
1269}
1270
1271if (Prototype.BrowserFeatures.XPath) {
1272  document._getElementsByXPath = function(expression, parentElement) {
1273    var results = [];
1274    var query = document.evaluate(expression, $(parentElement) || document,
1275      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1276    for (var i = 0, length = query.snapshotLength; i < length; i++)
1277      results.push(query.snapshotItem(i));
1278    return results;
1279  };
1280
1281  document.getElementsByClassName = function(className, parentElement) {
1282    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1283    return document._getElementsByXPath(q, parentElement);
1284  }
1285
1286} else document.getElementsByClassName = function(className, parentElement) {
1287  var children = ($(parentElement) || document.body).getElementsByTagName('*');
1288  var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
1289  for (var i = 0, length = children.length; i < length; i++) {
1290    child = children[i];
1291    var elementClassName = child.className;
1292    if (elementClassName.length == 0) continue;
1293    if (elementClassName == className || elementClassName.match(pattern))
1294      elements.push(Element.extend(child));
1295  }
1296  return elements;
1297};
1298
1299/*--------------------------------------------------------------------------*/
1300
1301if (!window.Element) var Element = {};
1302
1303Element.extend = function(element) {
1304  var F = Prototype.BrowserFeatures;
1305  if (!element || !element.tagName || element.nodeType == 3 ||
1306   element._extended || F.SpecificElementExtensions || element == window)
1307    return element;
1308
1309  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
1310   T = Element.Methods.ByTag;
1311
1312  // extend methods for all tags (Safari doesn't need this)
1313  if (!F.ElementExtensions) {
1314    Object.extend(methods, Element.Methods),
1315    Object.extend(methods, Element.Methods.Simulated);
1316  }
1317
1318  // extend methods for specific tags
1319  if (T[tagName]) Object.extend(methods, T[tagName]);
1320
1321  for (var property in methods) {
1322    var value = methods[property];
1323    if (typeof value == 'function' && !(property in element))
1324      element[property] = cache.findOrStore(value);
1325  }
1326
1327  element._extended = Prototype.emptyFunction;
1328  return element;
1329};
1330
1331Element.extend.cache = {
1332  findOrStore: function(value) {
1333    return this[value] = this[value] || function() {
1334      return value.apply(null, [this].concat($A(arguments)));
1335    }
1336  }
1337};
1338
1339Element.Methods = {
1340  visible: function(element) {
1341    return $(element).style.display != 'none';
1342  },
1343
1344  toggle: function(element) {
1345    element = $(element);
1346    Element[Element.visible(element) ? 'hide' : 'show'](element);
1347    return element;
1348  },
1349
1350  hide: function(element) {
1351    $(element).style.display = 'none';
1352    return element;
1353  },
1354
1355  show: function(element) {
1356    $(element).style.display = '';
1357    return element;
1358  },
1359
1360  remove: function(element) {
1361    element = $(element);
1362    element.parentNode.removeChild(element);
1363    return element;
1364  },
1365
1366  update: function(element, html) {
1367    html = typeof html == 'undefined' ? '' : html.toString();
1368    $(element).innerHTML = html.stripScripts();
1369    setTimeout(function() {html.evalScripts()}, 10);
1370    return element;
1371  },
1372
1373  replace: function(element, html) {
1374    element = $(element);
1375    html = typeof html == 'undefined' ? '' : html.toString();
1376    if (element.outerHTML) {
1377      element.outerHTML = html.stripScripts();
1378    } else {
1379      var range = element.ownerDocument.createRange();
1380      range.selectNodeContents(element);
1381      element.parentNode.replaceChild(
1382        range.createContextualFragment(html.stripScripts()), element);
1383    }
1384    setTimeout(function() {html.evalScripts()}, 10);
1385    return element;
1386  },
1387
1388  inspect: function(element) {
1389    element = $(element);
1390    var result = '<' + element.tagName.toLowerCase();
1391    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1392      var property = pair.first(), attribute = pair.last();
1393      var value = (element[property] || '').toString();
1394      if (value) result += ' ' + attribute + '=' + value.inspect(true);
1395    });
1396    return result + '>';
1397  },
1398
1399  recursivelyCollect: function(element, property) {
1400    element = $(element);
1401    var elements = [];
1402    while (element = element[property])
1403      if (element.nodeType == 1)
1404        elements.push(Element.extend(element));
1405    return elements;
1406  },
1407
1408  ancestors: function(element) {
1409    return $(element).recursivelyCollect('parentNode');
1410  },
1411
1412  descendants: function(element) {
1413    return $A($(element).getElementsByTagName('*')).each(Element.extend);
1414  },
1415
1416  firstDescendant: function(element) {
1417    element = $(element).firstChild;
1418    while (element && element.nodeType != 1) element = element.nextSibling;
1419    return $(element);
1420  },
1421
1422  immediateDescendants: function(element) {
1423    if (!(element = $(element).firstChild)) return [];
1424    while (element && element.nodeType != 1) element = element.nextSibling;
1425    if (element) return [element].concat($(element).nextSiblings());
1426    return [];
1427  },
1428
1429  previousSiblings: function(element) {
1430    return $(element).recursivelyCollect('previousSibling');
1431  },
1432
1433  nextSiblings: function(element) {
1434    return $(element).recursivelyCollect('nextSibling');
1435  },
1436
1437  siblings: function(element) {
1438    element = $(element);
1439    return element.previousSiblings().reverse().concat(element.nextSiblings());
1440  },
1441
1442  match: function(element, selector) {
1443    if (typeof selector == 'string')
1444      selector = new Selector(selector);
1445    return selector.match($(element));
1446  },
1447
1448  up: function(element, expression, index) {
1449    element = $(element);
1450    if (arguments.length == 1) return $(element.parentNode);
1451    var ancestors = element.ancestors();
1452    return expression ? Selector.findElement(ancestors, expression, index) :
1453      ancestors[index || 0];
1454  },
1455
1456  down: function(element, expression, index) {
1457    element = $(element);
1458    if (arguments.length == 1) return element.firstDescendant();
1459    var descendants = element.descendants();
1460    return expression ? Selector.findElement(descendants, expression, index) :
1461      descendants[index || 0];
1462  },
1463
1464  previous: function(element, expression, index) {
1465    element = $(element);
1466    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1467    var previousSiblings = element.previousSiblings();
1468    return expression ? Selector.findElement(previousSiblings, expression, index) :
1469      previousSiblings[index || 0];
1470  },
1471
1472  next: function(element, expression, index) {
1473    element = $(element);
1474    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1475    var nextSiblings = element.nextSiblings();
1476    return expression ? Selector.findElement(nextSiblings, expression, index) :
1477      nextSiblings[index || 0];
1478  },
1479
1480  getElementsBySelector: function() {
1481    var args = $A(arguments), element = $(args.shift());
1482    return Selector.findChildElements(element, args);
1483  },
1484
1485  getElementsByClassName: function(element, className) {
1486    return document.getElementsByClassName(className, element);
1487  },
1488
1489  readAttribute: function(element, name) {
1490    element = $(element);
1491    if (Prototype.Browser.IE) {
1492      if (!element.attributes) return null;
1493      var t = Element._attributeTranslations;
1494      if (t.values[name]) return t.values[name](element, name);
1495      if (t.names[name])  name = t.names[name];
1496      var attribute = element.attributes[name];
1497      return attribute ? attribute.nodeValue : null;
1498    }
1499    return element.getAttribute(name);
1500  },
1501
1502  getHeight: function(element) {
1503    return $(element).getDimensions().height;
1504  },
1505
1506  getWidth: function(element) {
1507    return $(element).getDimensions().width;
1508  },
1509
1510  classNames: function(element) {
1511    return new Element.ClassNames(element);
1512  },
1513
1514  hasClassName: function(element, className) {
1515    if (!(element = $(element))) return;
1516    var elementClassName = element.className;
1517    if (elementClassName.length == 0) return false;
1518    if (elementClassName == className ||
1519        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1520      return true;
1521    return false;
1522  },
1523
1524  addClassName: function(element, className) {
1525    if (!(element = $(element))) return;
1526    Element.classNames(element).add(className);
1527    return element;
1528  },
1529
1530  removeClassName: function(element, className) {
1531    if (!(element = $(element))) return;
1532    Element.classNames(element).remove(className);
1533    return element;
1534  },
1535
1536  toggleClassName: function(element, className) {
1537    if (!(element = $(element))) return;
1538    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
1539    return element;
1540  },
1541
1542  observe: function() {
1543    Event.observe.apply(Event, arguments);
1544    return $A(arguments).first();
1545  },
1546
1547  stopObserving: function() {
1548    Event.stopObserving.apply(Event, arguments);
1549    return $A(arguments).first();
1550  },
1551
1552  // removes whitespace-only text node children
1553  cleanWhitespace: function(element) {
1554    element = $(element);
1555    var node = element.firstChild;
1556    while (node) {
1557      var nextNode = node.nextSibling;
1558      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1559        element.removeChild(node);
1560      node = nextNode;
1561    }
1562    return element;
1563  },
1564
1565  empty: function(element) {
1566    return $(element).innerHTML.blank();
1567  },
1568
1569  descendantOf: function(element, ancestor) {
1570    element = $(element), ancestor = $(ancestor);
1571    while (element = element.parentNode)
1572      if (element == ancestor) return true;
1573    return false;
1574  },
1575
1576  scrollTo: function(element) {
1577    element = $(element);
1578    var pos = Position.cumulativeOffset(element);
1579    window.scrollTo(pos[0], pos[1]);
1580    return element;
1581  },
1582
1583  getStyle: function(element, style) {
1584    element = $(element);
1585    style = style == 'float' ? 'cssFloat' : style.camelize();
1586    var value = element.style[style];
1587    if (!value) {
1588      var css = document.defaultView.getComputedStyle(element, null);
1589      value = css ? css[style] : null;
1590    }
1591    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1592    return value == 'auto' ? null : value;
1593  },
1594
1595  getOpacity: function(element) {
1596    return $(element).getStyle('opacity');
1597  },
1598
1599  setStyle: function(element, styles, camelized) {
1600    element = $(element);
1601    var elementStyle = element.style;
1602
1603    for (var property in styles)
1604      if (property == 'opacity') element.setOpacity(styles[property])
1605      else
1606        elementStyle[(property == 'float' || property == 'cssFloat') ?
1607          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
1608          (camelized ? property : property.camelize())] = styles[property];
1609
1610    return element;
1611  },
1612
1613  setOpacity: function(element, value) {
1614    element = $(element);
1615    element.style.opacity = (value == 1 || value === '') ? '' :
1616      (value < 0.00001) ? 0 : value;
1617    return element;
1618  },
1619
1620  getDimensions: function(element) {
1621    element = $(element);
1622    var display = $(element).getStyle('display');
1623    if (display != 'none' && display != null) // Safari bug
1624      return {width: element.offsetWidth, height: element.offsetHeight};
1625
1626    // All *Width and *Height properties give 0 on elements with display none,
1627    // so enable the element temporarily
1628    var els = element.style;
1629    var originalVisibility = els.visibility;
1630    var originalPosition = els.position;
1631    var originalDisplay = els.display;
1632    els.visibility = 'hidden';
1633    els.position = 'absolute';
1634    els.display = 'block';
1635    var originalWidth = element.clientWidth;
1636    var originalHeight = element.clientHeight;
1637    els.display = originalDisplay;
1638    els.position = originalPosition;
1639    els.visibility = originalVisibility;
1640    return {width: originalWidth, height: originalHeight};
1641  },
1642
1643  makePositioned: function(element) {
1644    element = $(element);
1645    var pos = Element.getStyle(element, 'position');
1646    if (pos == 'static' || !pos) {
1647      element._madePositioned = true;
1648      element.style.position = 'relative';
1649      // Opera returns the offset relative to the positioning context, when an
1650      // element is position relative but top and left have not been defined
1651      if (window.opera) {
1652        element.style.top = 0;
1653        element.style.left = 0;
1654      }
1655    }
1656    return element;
1657  },
1658
1659  undoPositioned: function(element) {
1660    element = $(element);
1661    if (element._madePositioned) {
1662      element._madePositioned = undefined;
1663      element.style.position =
1664        element.style.top =
1665        element.style.left =
1666        element.style.bottom =
1667        element.style.right = '';
1668    }
1669    return element;
1670  },
1671
1672  makeClipping: function(element) {
1673    element = $(element);
1674    if (element._overflow) return element;
1675    element._overflow = element.style.overflow || 'auto';
1676    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1677      element.style.overflow = 'hidden';
1678    return element;
1679  },
1680
1681  undoClipping: function(element) {
1682    element = $(element);
1683    if (!element._overflow) return element;
1684    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1685    element._overflow = null;
1686    return element;
1687  }
1688};
1689
1690Object.extend(Element.Methods, {
1691  childOf: Element.Methods.descendantOf,
1692  childElements: Element.Methods.immediateDescendants
1693});
1694
1695if (Prototype.Browser.Opera) {
1696  Element.Methods._getStyle = Element.Methods.getStyle;
1697  Element.Methods.getStyle = function(element, style) {
1698    switch(style) {
1699      case 'left':
1700      case 'top':
1701      case 'right':
1702      case 'bottom':
1703        if (Element._getStyle(element, 'position') == 'static') return null;
1704      default: return Element._getStyle(element, style);
1705    }
1706  };
1707}
1708else if (Prototype.Browser.IE) {
1709  Element.Methods.getStyle = function(element, style) {
1710    element = $(element);
1711    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
1712    var value = element.style[style];
1713    if (!value && element.currentStyle) value = element.currentStyle[style];
1714
1715    if (style == 'opacity') {
1716      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
1717        if (value[1]) return parseFloat(value[1]) / 100;
1718      return 1.0;
1719    }
1720
1721    if (value == 'auto') {
1722      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
1723        return element['offset'+style.capitalize()] + 'px';
1724      return null;
1725    }
1726    return value;
1727  };
1728
1729  Element.Methods.setOpacity = function(element, value) {
1730    element = $(element);
1731    var filter = element.getStyle('filter'), style = element.style;
1732    if (value == 1 || value === '') {
1733      style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
1734      return element;
1735    } else if (value < 0.00001) value = 0;
1736    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
1737      'alpha(opacity=' + (value * 100) + ')';
1738    return element;
1739  };
1740
1741  // IE is missing .innerHTML support for TABLE-related elements
1742  Element.Methods.update = function(element, html) {
1743    element = $(element);
1744    html = typeof html == 'undefined' ? '' : html.toString();
1745    var tagName = element.tagName.toUpperCase();
1746    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1747      var div = document.createElement('div');
1748      switch (tagName) {
1749        case 'THEAD':
1750        case 'TBODY':
1751          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
1752          depth = 2;
1753          break;
1754        case 'TR':
1755          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
1756          depth = 3;
1757          break;
1758        case 'TD':
1759          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
1760          depth = 4;
1761      }
1762      $A(element.childNodes).each(function(node) { element.removeChild(node) });
1763      depth.times(function() { div = div.firstChild });
1764      $A(div.childNodes).each(function(node) { element.appendChild(node) });
1765    } else {
1766      element.innerHTML = html.stripScripts();
1767    }
1768    setTimeout(function() { html.evalScripts() }, 10);
1769    return element;
1770  }
1771}
1772else if (Prototype.Browser.Gecko) {
1773  Element.Methods.setOpacity = function(element, value) {
1774    element = $(element);
1775    element.style.opacity = (value == 1) ? 0.999999 :
1776      (value === '') ? '' : (value < 0.00001) ? 0 : value;
1777    return element;
1778  };
1779}
1780
1781Element._attributeTranslations = {
1782  names: {
1783    colspan:   "colSpan",
1784    rowspan:   "rowSpan",
1785    valign:    "vAlign",
1786    datetime:  "dateTime",
1787    accesskey: "accessKey",
1788    tabindex:  "tabIndex",
1789    enctype:   "encType",
1790    maxlength: "maxLength",
1791    readonly:  "readOnly",
1792    longdesc:  "longDesc"
1793  },
1794  values: {
1795    _getAttr: function(element, attribute) {
1796      return element.getAttribute(attribute, 2);
1797    },
1798    _flag: function(element, attribute) {
1799      return $(element).hasAttribute(attribute) ? attribute : null;
1800    },
1801    style: function(element) {
1802      return element.style.cssText.toLowerCase();
1803    },
1804    title: function(element) {
1805      var node = element.getAttributeNode('title');
1806      return node.specified ? node.nodeValue : null;
1807    }
1808  }
1809};
1810
1811(function() {
1812  Object.extend(this, {
1813    href: this._getAttr,
1814    src:  this._getAttr,
1815    type: this._getAttr,
1816    disabled: this._flag,
1817    checked:  this._flag,
1818    readonly: this._flag,
1819    multiple: this._flag
1820  });
1821}).call(Element._attributeTranslations.values);
1822
1823Element.Methods.Simulated = {
1824  hasAttribute: function(element, attribute) {
1825    var t = Element._attributeTranslations, node;
1826    attribute = t.names[attribute] || attribute;
1827    node = $(element).getAttributeNode(attribute);
1828    return node && node.specified;
1829  }
1830};
1831
1832Element.Methods.ByTag = {};
1833
1834Object.extend(Element, Element.Methods);
1835
1836if (!Prototype.BrowserFeatures.ElementExtensions &&
1837 document.createElement('div').__proto__) {
1838  window.HTMLElement = {};
1839  window.HTMLElement.prototype = document.createElement('div').__proto__;
1840  Prototype.BrowserFeatures.ElementExtensions = true;
1841}
1842
1843Element.hasAttribute = function(element, attribute) {
1844  if (element.hasAttribute) return element.hasAttribute(attribute);
1845  return Element.Methods.Simulated.hasAttribute(element, attribute);
1846};
1847
1848Element.addMethods = function(methods) {
1849  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
1850
1851  if (!methods) {
1852    Object.extend(Form, Form.Methods);
1853    Object.extend(Form.Element, Form.Element.Methods);
1854    Object.extend(Element.Methods.ByTag, {
1855      "FORM":     Object.clone(Form.Methods),
1856      "INPUT":    Object.clone(Form.Element.Methods),
1857      "SELECT":   Object.clone(Form.Element.Methods),
1858      "TEXTAREA": Object.clone(Form.Element.Methods)
1859    });
1860  }
1861
1862  if (arguments.length == 2) {
1863    var tagName = methods;
1864    methods = arguments[1];
1865  }
1866
1867  if (!tagName) Object.extend(Element.Methods, methods || {});
1868  else {
1869    if (tagName.constructor == Array) tagName.each(extend);
1870    else extend(tagName);
1871  }
1872
1873  function extend(tagName) {
1874    tagName = tagName.toUpperCase();
1875    if (!Element.Methods.ByTag[tagName])
1876      Element.Methods.ByTag[tagName] = {};
1877    Object.extend(Element.Methods.ByTag[tagName], methods);
1878  }
1879
1880  function copy(methods, destination, onlyIfAbsent) {
1881    onlyIfAbsent = onlyIfAbsent || false;
1882    var cache = Element.extend.cache;
1883    for (var property in methods) {
1884      var value = methods[property];
1885      if (!onlyIfAbsent || !(property in destination))
1886        destination[property] = cache.findOrStore(value);
1887    }
1888  }
1889
1890  function findDOMClass(tagName) {
1891    var klass;
1892    var trans = {
1893      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
1894      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
1895      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
1896      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
1897      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
1898      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
1899      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
1900      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
1901      "FrameSet", "IFRAME": "IFrame"
1902    };
1903    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
1904    if (window[klass]) return window[klass];
1905    klass = 'HTML' + tagName + 'Element';
1906    if (window[klass]) return window[klass];
1907    klass = 'HTML' + tagName.capitalize() + 'Element';
1908    if (window[klass]) return window[klass];
1909
1910    window[klass] = {};
1911    window[klass].prototype = document.createElement(tagName).__proto__;
1912    return window[klass];
1913  }
1914
1915  if (F.ElementExtensions) {
1916    copy(Element.Methods, HTMLElement.prototype);
1917    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
1918  }
1919
1920  if (F.SpecificElementExtensions) {
1921    for (var tag in Element.Methods.ByTag) {
1922      var klass = findDOMClass(tag);
1923      if (typeof klass == "undefined") continue;
1924      copy(T[tag], klass.prototype);
1925    }
1926  }
1927
1928  Object.extend(Element, Element.Methods);
1929  delete Element.ByTag;
1930};
1931
1932var Toggle = { display: Element.toggle };
1933
1934/*--------------------------------------------------------------------------*/
1935
1936Abstract.Insertion = function(adjacency) {
1937  this.adjacency = adjacency;
1938}
1939
1940Abstract.Insertion.prototype = {
1941  initialize: function(element, content) {
1942    this.element = $(element);
1943    this.content = content.stripScripts();
1944
1945    if (this.adjacency && this.element.insertAdjacentHTML) {
1946      try {
1947        this.element.insertAdjacentHTML(this.adjacency, this.content);
1948      } catch (e) {
1949        var tagName = this.element.tagName.toUpperCase();
1950        if (['TBODY', 'TR'].include(tagName)) {
1951          this.insertContent(this.contentFromAnonymousTable());
1952        } else {
1953          throw e;
1954        }
1955      }
1956    } else {
1957      this.range = this.element.ownerDocument.createRange();
1958      if (this.initializeRange) this.initializeRange();
1959      this.insertContent([this.range.createContextualFragment(this.content)]);
1960    }
1961
1962    setTimeout(function() {content.evalScripts()}, 10);
1963  },
1964
1965  contentFromAnonymousTable: function() {
1966    var div = document.createElement('div');
1967    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1968    return $A(div.childNodes[0].childNodes[0].childNodes);
1969  }
1970}
1971
1972var Insertion = new Object();
1973
1974Insertion.Before = Class.create();
1975Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1976  initializeRange: function() {
1977    this.range.setStartBefore(this.element);
1978  },
1979
1980  insertContent: function(fragments) {
1981    fragments.each((function(fragment) {
1982      this.element.parentNode.insertBefore(fragment, this.element);
1983    }).bind(this));
1984  }
1985});
1986
1987Insertion.Top = Class.create();
1988Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1989  initializeRange: function() {
1990    this.range.selectNodeContents(this.element);
1991    this.range.collapse(true);
1992  },
1993
1994  insertContent: function(fragments) {
1995    fragments.reverse(false).each((function(fragment) {
1996      this.element.insertBefore(fragment, this.element.firstChild);
1997    }).bind(this));
1998  }
1999});
2000
2001Insertion.Bottom = Class.create();
2002Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
2003  initializeRange: function() {
2004    this.range.selectNodeContents(this.element);
2005    this.range.collapse(this.element);
2006  },
2007
2008  insertContent: function(fragments) {
2009    fragments.each((function(fragment) {
2010      this.element.appendChild(fragment);
2011    }).bind(this));
2012  }
2013});
2014
2015Insertion.After = Class.create();
2016Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
2017  initializeRange: function() {
2018    this.range.setStartAfter(this.element);
2019  },
2020
2021  insertContent: function(fragments) {
2022    fragments.each((function(fragment) {
2023      this.element.parentNode.insertBefore(fragment,
2024        this.element.nextSibling);
2025    }).bind(this));
2026  }
2027});
2028
2029/*--------------------------------------------------------------------------*/
2030
2031Element.ClassNames = Class.create();
2032Element.ClassNames.prototype = {
2033  initialize: function(element) {
2034    this.element = $(element);
2035  },
2036
2037  _each: function(iterator) {
2038    this.element.className.split(/\s+/).select(function(name) {
2039      return name.length > 0;
2040    })._each(iterator);
2041  },
2042
2043  set: function(className) {
2044    this.element.className = className;
2045  },
2046
2047  add: function(classNameToAdd) {
2048    if (this.include(classNameToAdd)) return;
2049    this.set($A(this).concat(classNameToAdd).join(' '));
2050  },
2051
2052  remove: function(classNameToRemove) {
2053    if (!this.include(classNameToRemove)) return;
2054    this.set($A(this).without(classNameToRemove).join(' '));
2055  },
2056
2057  toString: function() {
2058    return $A(this).join(' ');
2059  }
2060};
2061
2062Object.extend(Element.ClassNames.prototype, Enumerable);
2063/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
2064 * part of YUI-Ext version 0.40, distributed under the terms of an MIT
2064-style
2065 * license.  Please see http://www.yui-ext.com/ for more information. */
2066
2067var Selector = Class.create();
2068
2069Selector.prototype = {
2070  initialize: function(expression) {
2071    this.expression = expression.strip();
2072    this.compileMatcher();
2073  },
2074
2075  compileMatcher: function() {
2076    // Selectors with namespaced attributes can't use the XPath version
2077    if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
2078      return this.compileXPathMatcher();
2079
2080    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
2081        c = Selector.criteria, le, p, m;
2082
2083    if (Selector._cache[e]) {
2084      this.matcher = Selector._cache[e]; return;
2085    }
2086    this.matcher = ["this.matcher = function(root) {",
2087                    "var r = root, h = Selector.handlers, c = false, n;"];
2088
2089    while (e && le != e && (/\S/).test(e)) {
2090      le = e;
2091      for (var i in ps) {
2092        p = ps[i];
2093        if (m = e.match(p)) {
2094          this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
2095    	      new Template(c[i]).evaluate(m));
2096          e = e.replace(m[0], '');
2097          break;
2098        }
2099      }
2100    }
2101
2102    this.matcher.push("return h.unique(n);\n}");
2103    eval(this.matcher.join('\n'));
2104    Selector._cache[this.expression] = this.matcher;
2105  },
2106
2107  compileXPathMatcher: function() {
2108    var e = this.expression, ps = Selector.patterns,
2109        x = Selector.xpath, le,  m;
2110
2111    if (Selector._cache[e]) {
2112      this.xpath = Selector._cache[e]; return;
2113    }
2114
2115    this.matcher = ['.//*'];
2116    while (e && le != e && (/\S/).test(e)) {
2117      le = e;
2118      for (var i in ps) {
2119        if (m = e.match(ps[i])) {
2120          this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
2121            new Template(x[i]).evaluate(m));
2122          e = e.replace(m[0], '');
2123          break;
2124        }
2125      }
2126    }
2127
2128    this.xpath = this.matcher.join('');
2129    Selector._cache[this.expression] = this.xpath;
2130  },
2131
2132  findElements: function(root) {
2133    root = root || document;
2134    if (this.xpath) return document._getElementsByXPath(this.xpath, root);
2135    return this.matcher(root);
2136  },
2137
2138  match: function(element) {
2139    return this.findElements(document).include(element);
2140  },
2141
2142  toString: function() {
2143    return this.expression;
2144  },
2145
2146  inspect: function() {
2147    return "#<Selector:" + this.expression.inspect() + ">";
2148  }
2149};
2150
2151Object.extend(Selector, {
2152  _cache: {},
2153
2154  xpath: {
2155    descendant:   "//*",
2156    child:        "/*",
2157    adjacent:     "/following-sibling::*[1]",
2158    laterSibling: '/following-sibling::*',
2159    tagName:      function(m) {
2160      if (m[1] == '*') return '';
2161      return "[local-name()='" + m[1].toLowerCase() +
2162             "' or local-name()='" + m[1].toUpperCase() + "']";
2163    },
2164    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2165    id:           "[@id='#{1}']",
2166    attrPresence: "[@#{1}]",
2167    attr: function(m) {
2168      m[3] = m[5] || m[6];
2169      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2170    },
2171    pseudo: function(m) {
2172      var h = Selector.xpath.pseudos[m[1]];
2173      if (!h) return '';
2174      if (typeof h === 'function') return h(m);
2175      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
2176    },
2177    operators: {
2178      '=':  "[@#{1}='#{3}']",
2179      '!=': "[@#{1}!='#{3}']",
2180      '^=': "[starts-with(@#{1}, '#{3}')]",
2181      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
2182      '*=': "[contains(@#{1}, '#{3}')]",
2183      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
2184      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
2185    },
2186    pseudos: {
2187      'first-child': '[not(preceding-sibling::*)]',
2188      'last-child':  '[not(following-sibling::*)]',
2189      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
2190      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
2191      'checked':     "[@checked]",
2192      'disabled':    "[@disabled]",
2193      'enabled':     "[not(@disabled)]",
2194      'not': function(m) {
2195        var e = m[6], p = Selector.patterns,
2196            x = Selector.xpath, le, m, v;
2197
2198        var exclusion = [];
2199        while (e && le != e && (/\S/).test(e)) {
2200          le = e;
2201          for (var i in p) {
2202            if (m = e.match(p[i])) {
2203              v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
2204              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2205              e = e.replace(m[0], '');
2206              break;
2207            }
2208          }
2209        }
2210        return "[not(" + exclusion.join(" and ") + ")]";
2211      },
2212      'nth-child':      function(m) {
2213        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
2214      },
2215      'nth-last-child': function(m) {
2216        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
2217      },
2218      'nth-of-type':    function(m) {
2219        return Selector.xpath.pseudos.nth("position() ", m);
2220      },
2221      'nth-last-of-type': function(m) {
2222        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
2223      },
2224      'first-of-type':  function(m) {
2225        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
2226      },
2227      'last-of-type':   function(m) {
2228        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
2229      },
2230      'only-of-type':   function(m) {
2231        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
2232      },
2233      nth: function(fragment, m) {
2234        var mm, formula = m[6], predicate;
2235        if (formula == 'even') formula = '2n+0';
2236        if (formula == 'odd')  formula = '2n+1';
2237        if (mm = formula.match(/^(\d+)$/)) // digit only
2238          return '[' + fragment + "= " + mm[1] + ']';
2239        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
2240          if (mm[1] == "-") mm[1] = -1;
2241          var a = mm[1] ? Number(mm[1]) : 1;
2242          var b = mm[2] ? Number(mm[2]) : 0;
2243          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
2244          "((#{fragment} - #{b}) div #{a} >= 0)]";
2245          return new Template(predicate).evaluate({
2246            fragment: fragment, a: a, b: b });
2247        }
2248      }
2249    }
2250  },
2251
2252  criteria: {
2253    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;',
2254    className:    'n = h.className(n, r, "#{1}", c); c = false;',
2255    id:           'n = h.id(n, r, "#{1}", c);        c = false;',
2256    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
2257    attr: function(m) {
2258      m[3] = (m[5] || m[6]);
2259      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
2260    },
2261    pseudo:       function(m) {
2262      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
2263      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
2264    },
2265    descendant:   'c = "descendant";',
2266    child:        'c = "child";',
2267    adjacent:     'c = "adjacent";',
2268    laterSibling: 'c = "laterSibling";'
2269  },
2270
2271  patterns: {
2272    // combinators must be listed first
2273    // (and descendant needs to be last combinator)
2274    laterSibling: /^\s*~\s*/,
2275    child:        /^\s*>\s*/,
2276    adjacent:     /^\s*\+\s*/,
2277    descendant:   /^\s/,
2278
2279    // selectors follow
2280    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
2281    id:           /^#([\w\-\*]+)(\b|$)/,
2282    className:    /^\.([\w\-\*]+)(\b|$)/,
2283    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/,
2284    attrPresence: /^\[([\w]+)\]/,
2285    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/
2286  },
2287
2288  handlers: {
2289    // UTILITY FUNCTIONS
2290    // joins two collections
2291    concat: function(a, b) {
2292      for (var i = 0, node; node = b[i]; i++)
2293        a.push(node);
2294      return a;
2295    },
2296
2297    // marks an array of nodes for counting
2298    mark: function(nodes) {
2299      for (var i = 0, node; node = nodes[i]; i++)
2300        node._counted = true;
2301      return nodes;
2302    },
2303
2304    unmark: function(nodes) {
2305      for (var i = 0, node; node = nodes[i]; i++)
2306        node._counted = undefined;
2307      return nodes;
2308    },
2309
2310    // mark each child node with its position (for nth calls)
2311    // "ofType" flag indicates whether we're indexing for nth-of-type
2312    // rather than nth-child
2313    index: function(parentNode, reverse, ofType) {
2314      parentNode._counted = true;
2315      if (reverse) {
2316        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
2317          node = nodes[i];
2318          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
2319        }
2320      } else {
2321        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
2322          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
2323      }
2324    },
2325
2326    // filters out duplicates and extends all nodes
2327    unique: function(nodes) {
2328      if (nodes.length == 0) return nodes;
2329      var results = [], n;
2330      for (var i = 0, l = nodes.length; i < l; i++)
2331        if (!(n = nodes[i])._counted) {
2332          n._counted = true;
2333          results.push(Element.extend(n));
2334        }
2335      return Selector.handlers.unmark(results);
2336    },
2337
2338    // COMBINATOR FUNCTIONS
2339    descendant: function(nodes) {
2340      var h = Selector.handlers;
2341      for (var i = 0, results = [], node; node = nodes[i]; i++)
2342        h.concat(results, node.getElementsByTagName('*'));
2343      return results;
2344    },
2345
2346    child: function(nodes) {
2347      var h = Selector.handlers;
2348      for (var i = 0, results = [], node; node = nodes[i]; i++) {
2349        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
2350          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
2351      }
2352      return results;
2353    },
2354
2355    adjacent: function(nodes) {
2356      for (var i = 0, results = [], node; node = nodes[i]; i++) {
2357        var next = this.nextElementSibling(node);
2358        if (next) results.push(next);
2359      }
2360      return results;
2361    },
2362
2363    laterSibling: function(nodes) {
2364      var h = Selector.handlers;
2365      for (var i = 0, results = [], node; node = nodes[i]; i++)
2366        h.concat(results, Element.nextSiblings(node));
2367      return results;
2368    },
2369
2370    nextElementSibling: function(node) {
2371      while (node = node.nextSibling)
2372	      if (node.nodeType == 1) return node;
2373      return null;
2374    },
2375
2376    previousElementSibling: function(node) {
2377      while (node = node.previousSibling)
2378        if (node.nodeType == 1) return node;
2379      return null;
2380    },
2381
2382    // TOKEN FUNCTIONS
2383    tagName: function(nodes, root, tagName, combinator) {
2384      tagName = tagName.toUpperCase();
2385      var results = [], h = Selector.handlers;
2386      if (nodes) {
2387        if (combinator) {
2388          // fastlane for ordinary descendant combinators
2389          if (combinator == "descendant") {
2390            for (var i = 0, node; node = nodes[i]; i++)
2391              h.concat(results, node.getElementsByTagName(tagName));
2392            return results;
2393          } else nodes = this[combinator](nodes);
2394          if (tagName == "*") return nodes;
2395        }
2396        for (var i = 0, node; node = nodes[i]; i++)
2397          if (node.tagName.toUpperCase() == tagName) results.push(node);
2398        return results;
2399      } else return root.getElementsByTagName(tagName);
2400    },
2401
2402    id: function(nodes, root, id, combinator) {
2403      var targetNode = $(id), h = Selector.handlers;
2404      if (!nodes && root == document) return targetNode ? [targetNode] : [];
2405      if (nodes) {
2406        if (combinator) {
2407          if (combinator == 'child') {
2408            for (var i = 0, node; node = nodes[i]; i++)
2409              if (targetNode.parentNode == node) return [targetNode];
2410          } else if (combinator == 'descendant') {
2411            for (var i = 0, node; node = nodes[i]; i++)
2412              if (Element.descendantOf(targetNode, node)) return [targetNode];
2413          } else if (combinator == 'adjacent') {
2414            for (var i = 0, node; node = nodes[i]; i++)
2415              if (Selector.handlers.previousElementSibling(targetNode) == node)
2416                return [targetNode];
2417          } else nodes = h[combinator](nodes);
2418        }
2419        for (var i = 0, node; node = nodes[i]; i++)
2420          if (node == targetNode) return [targetNode];
2421        return [];
2422      }
2423      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
2424    },
2425
2426    className: function(nodes, root, className, combinator) {
2427      if (nodes && combinator) nodes = this[combinator](nodes);
2428      return Selector.handlers.byClassName(nodes, root, className);
2429    },
2430
2431    byClassName: function(nodes, root, className) {
2432      if (!nodes) nodes = Selector.handlers.descendant([root]);
2433      var needle = ' ' + className + ' ';
2434      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
2435        nodeClassName = node.className;
2436        if (nodeClassName.length == 0) continue;
2437        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
2438          results.push(node);
2439      }
2440      return results;
2441    },
2442
2443    attrPresence: function(nodes, root, attr) {
2444      var results = [];
2445      for (var i = 0, node; node = nodes[i]; i++)
2446        if (Element.hasAttribute(node, attr)) results.push(node);
2447      return results;
2448    },
2449
2450    attr: function(nodes, root, attr, value, operator) {
2451      if (!nodes) nodes = root.getElementsByTagName("*");
2452      var handler = Selector.operators[operator], results = [];
2453      for (var i = 0, node; node = nodes[i]; i++) {
2454        var nodeValue = Element.readAttribute(node, attr);
2455        if (nodeValue === null) continue;
2456        if (handler(nodeValue, value)) results.push(node);
2457      }
2458      return results;
2459    },
2460
2461    pseudo: function(nodes, name, value, root, combinator) {
2462      if (nodes && combinator) nodes = this[combinator](nodes);
2463      if (!nodes) nodes = root.getElementsByTagName("*");
2464      return Selector.pseudos[name](nodes, value, root);
2465    }
2466  },
2467
2468  pseudos: {
2469    'first-child': function(nodes, value, root) {
2470      for (var i = 0, results = [], node; node = nodes[i]; i++) {
2471        if (Selector.handlers.previousElementSibling(node)) continue;
2472          results.push(node);
2473      }
2474      return results;
2475    },
2476    'last-child': function(nodes, value, root) {
2477      for (var i = 0, results = [], node; node = nodes[i]; i++) {
2478        if (Selector.handlers.nextElementSibling(node)) continue;
2479          results.push(node);
2480      }
2481      return results;
2482    },
2483    'only-child': function(nodes, value, root) {
2484      var h = Selector.handlers;
2485      for (var i = 0, results = [], node; node = nodes[i]; i++)
2486        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
2487          results.push(node);
2488      return results;
2489    },
2490    'nth-child':        function(nodes, formula, root) {
2491      return Selector.pseudos.nth(nodes, formula, root);
2492    },
2493    'nth-last-child':   function(nodes, formula, root) {
2494      return Selector.pseudos.nth(nodes, formula, root, true);
2495    },
2496    'nth-of-type':      function(nodes, formula, root) {
2497      return Selector.pseudos.nth(nodes, formula, root, false, true);
2498    },
2499    'nth-last-of-type': function(nodes, formula, root) {
2500      return Selector.pseudos.nth(nodes, formula, root, true, true);
2501    },
2502    'first-of-type':    function(nodes, formula, root) {
2503      return Selector.pseudos.nth(nodes, "1", root, false, true);
2504    },
2505    'last-of-type':     function(nodes, formula, root) {
2506      return Selector.pseudos.nth(nodes, "1", root, true, true);
2507    },
2508    'only-of-type':     function(nodes, formula, root) {
2509      var p = Selector.pseudos;
2510      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
2511    },
2512
2513    // handles the an+b logic
2514    getIndices: function(a, b, total) {
2515      if (a == 0) return b > 0 ? [b] : [];
2516      return $R(1, total).inject([], function(memo, i) {
2517        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
2518        return memo;
2519      });
2520    },
2521
2522    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
2523    nth: function(nodes, formula, root, reverse, ofType) {
2524      if (nodes.length == 0) return [];
2525      if (formula == 'even') formula = '2n+0';
2526      if (formula == 'odd')  formula = '2n+1';
2527      var h = Selector.handlers, results = [], indexed = [], m;
2528      h.mark(nodes);
2529      for (var i = 0, node; node = nodes[i]; i++) {
2530        if (!node.parentNode._counted) {
2531          h.index(node.parentNode, reverse, ofType);
2532          indexed.push(node.parentNode);
2533        }
2534      }
2535      if (formula.match(/^\d+$/)) { // just a number
2536        formula = Number(formula);
2537        for (var i = 0, node; node = nodes[i]; i++)
2538          if (node.nodeIndex == formula) results.push(node);
2539      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
2540        if (m[1] == "-") m[1] = -1;
2541        var a = m[1] ? Number(m[1]) : 1;
2542        var b = m[2] ? Number(m[2]) : 0;
2543        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
2544        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
2545          for (var j = 0; j < l; j++)
2546            if (node.nodeIndex == indices[j]) results.push(node);
2547        }
2548      }
2549      h.unmark(nodes);
2550      h.unmark(indexed);
2551      return results;
2552    },
2553
2554    'empty': function(nodes, value, root) {
2555      for (var i = 0, results = [], node; node = nodes[i]; i++) {
2556        // IE treats comments as element nodes
2557        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
2558        results.push(node);
2559      }
2560      return results;
2561    },
2562
2563    'not': function(nodes, selector, root) {
2564      var h = Selector.handlers, selectorType, m;
2565      var exclusions = new Selector(selector).findElements(root);
2566      h.mark(exclusions);
2567      for (var i = 0, results = [], node; node = nodes[i]; i++)
2568        if (!node._counted) results.push(node);
2569      h.unmark(exclusions);
2570      return results;
2571    },
2572
2573    'enabled': function(nodes, value, root) {
2574      for (var i = 0, results = [], node; node = nodes[i]; i++)
2575        if (!node.disabled) results.push(node);
2576      return results;
2577    },
2578
2579    'disabled': function(nodes, value, root) {
2580      for (var i = 0, results = [], node; node = nodes[i]; i++)
2581        if (node.disabled) results.push(node);
2582      return results;
2583    },
2584
2585    'checked': function(nodes, value, root) {
2586      for (var i = 0, results = [], node; node = nodes[i]; i++)
2587        if (node.checked) results.push(node);
2588      return results;
2589    }
2590  },
2591
2592  operators: {
2593    '=':  function(nv, v) { return nv == v; },
2594    '!=': function(nv, v) { return nv != v; },
2595    '^=': function(nv, v) { return nv.startsWith(v); },
2596    '$=': function(nv, v) { return nv.endsWith(v); },
2597    '*=': function(nv, v) { return nv.include(v); },
2598    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
2599    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
2600  },
2601
2602  matchElements: function(elements, expression) {
2603    var matches = new Selector(expression).findElements(), h = Selector.handlers;
2604    h.mark(matches);
2605    for (var i = 0, results = [], element; element = elements[i]; i++)
2606      if (element._counted) results.push(element);
2607    h.unmark(matches);
2608    return results;
2609  },
2610
2611  findElement: function(elements, expression, index) {
2612    if (typeof expression == 'number') {
2613      index = expression; expression = false;
2614    }
2615    return Selector.matchElements(elements, expression || '*')[index || 0];
2616  },
2617
2618  findChildElements: function(element, expressions) {
2619    var exprs = expressions.join(','), expressions = [];
2620    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
2621      expressions.push(m[1].strip());
2622    });
2623    var results = [], h = Selector.handlers;
2624    for (var i = 0, l = expressions.length, selector; i < l; i++) {
2625      selector = new Selector(expressions[i].strip());
2626      h.concat(results, selector.findElements(element));
2627    }
2628    return (l > 1) ? h.unique(results) : results;
2629  }
2630});
2631
2632function $$() {
2633  return Selector.findChildElements(document, $A(arguments));
2634}
2635var Form = {
2636  reset: function(form) {
2637    $(form).reset();
2638    return form;
2639  },
2640
2641  serializeElements: function(elements, getHash) {
2642    var data = elements.inject({}, function(result, element) {
2643      if (!element.disabled && element.name) {
2644        var key = element.name, value = $(element).getValue();
2645        if (value != null) {
2646         	if (key in result) {
2647            if (result[key].constructor != Array) result[key] = [result[key]];
2648            result[key].push(value);
2649          }
2650          else result[key] = value;
2651        }
2652      }
2653      return result;
2654    });
2655
2656    return getHash ? data : Hash.toQueryString(data);
2657  }
2658};
2659
2660Form.Methods = {
2661  serialize: function(form, getHash) {
2662    return Form.serializeElements(Form.getElements(form), getHash);
2663  },
2664
2665  getElements: function(form) {
2666    return $A($(form).getElementsByTagName('*')).inject([],
2667      function(elements, child) {
2668        if (Form.Element.Serializers[child.tagName.toLowerCase()])
2669          elements.push(Element.extend(child));
2670        return elements;
2671      }
2672    );
2673  },
2674
2675  getInputs: function(form, typeName, name) {
2676    form = $(form);
2677    var inputs = form.getElementsByTagName('input');
2678
2679    if (!typeName && !name) return $A(inputs).map(Element.extend);
2680
2681    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
2682      var input = inputs[i];
2683      if ((typeName && input.type != typeName) || (name && input.name != name))
2684        continue;
2685      matchingInputs.push(Element.extend(input));
2686    }
2687
2688    return matchingInputs;
2689  },
2690
2691  disable: function(form) {
2692    form = $(form);
2693    Form.getElements(form).invoke('disable');
2694    return form;
2695  },
2696
2697  enable: function(form) {
2698    form = $(form);
2699    Form.getElements(form).invoke('enable');
2700    return form;
2701  },
2702
2703  findFirstElement: function(form) {
2704    return $(form).getElements().find(function(element) {
2705      return element.type != 'hidden' && !element.disabled &&
2706        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
2707    });
2708  },
2709
2710  focusFirstElement: function(form) {
2711    form = $(form);
2712    form.findFirstElement().activate();
2713    return form;
2714  },
2715
2716  request: function(form, options) {
2717    form = $(form), options = Object.clone(options || {});
2718
2719    var params = options.parameters;
2720    options.parameters = form.serialize(true);
2721
2722    if (params) {
2723      if (typeof params == 'string') params = params.toQueryParams();
2724      Object.extend(options.parameters, params);
2725    }
2726
2727    if (form.hasAttribute('method') && !options.method)
2728      options.method = form.method;
2729
2730    return new Ajax.Request(form.readAttribute('action'), options);
2731  }
2732}
2733
2734/*--------------------------------------------------------------------------*/
2735
2736Form.Element = {
2737  focus: function(element) {
2738    $(element).focus();
2739    return element;
2740  },
2741
2742  select: function(element) {
2743    $(element).select();
2744    return element;
2745  }
2746}
2747
2748Form.Element.Methods = {
2749  serialize: function(element) {
2750    element = $(element);
2751    if (!element.disabled && element.name) {
2752      var value = element.getValue();
2753      if (value != undefined) {
2754        var pair = {};
2755        pair[element.name] = value;
2756        return Hash.toQueryString(pair);
2757      }
2758    }
2759    return '';
2760  },
2761
2762  getValue: function(element) {
2763    element = $(element);
2764    var method = element.tagName.toLowerCase();
2765    return Form.Element.Serializers[method](element);
2766  },
2767
2768  clear: function(element) {
2769    $(element).value = '';
2770    return element;
2771  },
2772
2773  present: function(element) {
2774    return $(element).value != '';
2775  },
2776
2777  activate: function(element) {
2778    element = $(element);
2779    try {
2780      element.focus();
2781      if (element.select && (element.tagName.toLowerCase() != 'input' ||
2782        !['button', 'reset', 'submit'].include(element.type)))
2783        element.select();
2784    } catch (e) {}
2785    return element;
2786  },
2787
2788  disable: function(element) {
2789    element = $(element);
2790    element.blur();
2791    element.disabled = true;
2792    return element;
2793  },
2794
2795  enable: function(element) {
2796    element = $(element);
2797    element.disabled = false;
2798    return element;
2799  }
2800}
2801
2802/*--------------------------------------------------------------------------*/
2803
2804var Field = Form.Element;
2805var $F = Form.Element.Methods.getValue;
2806
2807/*--------------------------------------------------------------------------*/
2808
2809Form.Element.Serializers = {
2810  input: function(element) {
2811    switch (element.type.toLowerCase()) {
2812      case 'checkbox':
2813      case 'radio':
2814        return Form.Element.Serializers.inputSelector(element);
2815      default:
2816        return Form.Element.Serializers.textarea(element);
2817    }
2818  },
2819
2820  inputSelector: function(element) {
2821    return element.checked ? element.value : null;
2822  },
2823
2824  textarea: function(element) {
2825    return element.value;
2826  },
2827
2828  select: function(element) {
2829    return this[element.type == 'select-one' ?
2830      'selectOne' : 'selectMany'](element);
2831  },
2832
2833  selectOne: function(element) {
2834    var index = element.selectedIndex;
2835    return index >= 0 ? this.optionValue(element.options[index]) : null;
2836  },
2837
2838  selectMany: function(element) {
2839    var values, length = element.length;
2840    if (!length) return null;
2841
2842    for (var i = 0, values = []; i < length; i++) {
2843      var opt = element.options[i];
2844      if (opt.selected) values.push(this.optionValue(opt));
2845    }
2846    return values;
2847  },
2848
2849  optionValue: function(opt) {
2850    // extend element because hasAttribute may not be native
2851    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
2852  }
2853}
2854
2855/*--------------------------------------------------------------------------*/
2856
2857Abstract.TimedObserver = function() {}
2858Abstract.TimedObserver.prototype = {
2859  initialize: function(element, frequency, callback) {
2860    this.frequency = frequency;
2861    this.element   = $(element);
2862    this.callback  = callback;
2863
2864    this.lastValue = this.getValue();
2865    this.registerCallback();
2866  },
2867
2868  registerCallback: function() {
2869    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
2870  },
2871
2872  onTimerEvent: function() {
2873    var value = this.getValue();
2874    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
2875      ? this.lastValue != value : String(this.lastValue) != String(value));
2876    if (changed) {
2877      this.callback(this.element, value);
2878      this.lastValue = value;
2879    }
2880  }
2881}
2882
2883Form.Element.Observer = Class.create();
2884Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2885  getValue: function() {
2886    return Form.Element.getValue(this.element);
2887  }
2888});
2889
2890Form.Observer = Class.create();
2891Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2892  getValue: function() {
2893    return Form.serialize(this.element);
2894  }
2895});
2896
2897/*--------------------------------------------------------------------------*/
2898
2899Abstract.EventObserver = function() {}
2900Abstract.EventObserver.prototype = {
2901  initialize: function(element, callback) {
2902    this.element  = $(element);
2903    this.callback = callback;
2904
2905    this.lastValue = this.getValue();
2906    if (this.element.tagName.toLowerCase() == 'form')
2907      this.registerFormCallbacks();
2908    else
2909      this.registerCallback(this.element);
2910  },
2911
2912  onElementEvent: function() {
2913    var value = this.getValue();
2914    if (this.lastValue != value) {
2915      this.callback(this.element, value);
2916      this.lastValue = value;
2917    }
2918  },
2919
2920  registerFormCallbacks: function() {
2921    Form.getElements(this.element).each(this.registerCallback.bind(this));
2922  },
2923
2924  registerCallback: function(element) {
2925    if (element.type) {
2926      switch (element.type.toLowerCase()) {
2927        case 'checkbox':
2928        case 'radio':
2929          Event.observe(element, 'click', this.onElementEvent.bind(this));
2930          break;
2931        default:
2932          Event.observe(element, 'change', this.onElementEvent.bind(this));
2933          break;
2934      }
2935    }
2936  }
2937}
2938
2939Form.Element.EventObserver = Class.create();
2940Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2941  getValue: function() {
2942    return Form.Element.getValue(this.element);
2943  }
2944});
2945
2946Form.EventObserver = Class.create();
2947Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2948  getValue: function() {
2949    return Form.serialize(this.element);
2950  }
2951});
2952if (!window.Event) {
2953  var Event = new Object();
2954}
2955
2956Object.extend(Event, {
2957  KEY_BACKSPACE: 8,
2958  KEY_TAB:       9,
2959  KEY_RETURN:   13,
2960  KEY_ESC:      27,
2961  KEY_LEFT:     37,
2962  KEY_UP:       38,
2963  KEY_RIGHT:    39,
2964  KEY_DOWN:     40,
2965  KEY_DELETE:   46,
2966  KEY_HOME:     36,
2967  KEY_END:      35,
2968  KEY_PAGEUP:   33,
2969  KEY_PAGEDOWN: 34,
2970
2971  element: function(event) {
2972    return $(event.target || event.srcElement);
2973  },
2974
2975  isLeftClick: function(event) {
2976    return (((event.which) && (event.which == 1)) ||
2977            ((event.button) && (event.button == 1)));
2978  },
2979
2980  pointerX: function(event) {
2981    return event.pageX || (event.clientX +
2982      (document.documentElement.scrollLeft || document.body.scrollLeft));
2983  },
2984
2985  pointerY: function(event) {
2986    return event.pageY || (event.clientY +
2987      (document.documentElement.scrollTop || document.body.scrollTop));
2988  },
2989
2990  stop: function(event) {
2991    if (event.preventDefault) {
2992      event.preventDefault();
2993      event.stopPropagation();
2994    } else {
2995      event.returnValue = false;
2996      event.cancelBubble = true;
2997    }
2998  },
2999
3000  // find the first node with the given tagName, starting from the
3001  // node the event was triggered on; traverses the DOM upwards
3002  findElement: function(event, tagName) {
3003    var element = Event.element(event);
3004    while (element.parentNode && (!element.tagName ||
3005        (element.tagName.toUpperCase() != tagName.toUpperCase())))
3006      element = element.parentNode;
3007    return element;
3008  },
3009
3010  observers: false,
3011
3012  _observeAndCache: function(element, name, observer, useCapture) {
3013    if (!this.observers) this.observers = [];
3014    if (element.addEventListener) {
3015      this.observers.push([element, name, observer, useCapture]);
3016      element.addEventListener(name, observer, useCapture);
3017    } else if (element.attachEvent) {
3018      this.observers.push([element, name, observer, useCapture]);
3019      element.attachEvent('on' + name, observer);
3020    }
3021  },
3022
3023  unloadCache: function() {
3024    if (!Event.observers) return;
3025    for (var i = 0, length = Event.observers.length; i < length; i++) {
3026      Event.stopObserving.apply(this, Event.observers[i]);
3027      Event.observers[i][0] = null;
3028    }
3029    Event.observers = false;
3030  },
3031
3032  observe: function(element, name, observer, useCapture) {
3033    element = $(element);
3034    useCapture = useCapture || false;
3035
3036    if (name == 'keypress' &&
3037      (Prototype.Browser.WebKit || element.attachEvent))
3038      name = 'keydown';
3039
3040    Event._observeAndCache(element, name, observer, useCapture);
3041  },
3042
3043  stopObserving: function(element, name, observer, useCapture) {
3044    element = $(element);
3045    useCapture = useCapture || false;
3046
3047    if (name == 'keypress' &&
3048        (Prototype.Browser.WebKit || element.attachEvent))
3049      name = 'keydown';
3050
3051    if (element.removeEventListener) {
3052      element.removeEventListener(name, observer, useCapture);
3053    } else if (element.detachEvent) {
3054      try {
3055        element.detachEvent('on' + name, observer);
3056      } catch (e) {}
3057    }
3058  }
3059});
3060
3061/* prevent memory leaks in IE */
3062if (Prototype.Browser.IE)
3063  Event.observe(window, 'unload', Event.unloadCache, false);
3064var Position = {
3065  // set to true if needed, warning: firefox performance problems
3066  // NOT neeeded for page scrolling, only if draggable contained in
3067  // scrollable elements
3068  includeScrollOffsets: false,
3069
3070  // must be called before calling withinIncludingScrolloffset, every time the
3071  // page is scrolled
3072  prepare: function() {
3073    this.deltaX =  window.pageXOffset
3074                || document.documentElement.scrollLeft
3075                || document.body.scrollLeft
3076                || 0;
3077    this.deltaY =  window.pageYOffset
3078                || document.documentElement.scrollTop
3079                || document.body.scrollTop
3080                || 0;
3081  },
3082
3083  realOffset: function(element) {
3084    var valueT = 0, valueL = 0;
3085    do {
3086      valueT += element.scrollTop  || 0;
3087      valueL += element.scrollLeft || 0;
3088      element = element.parentNode;
3089    } while (element);
3090    return [valueL, valueT];
3091  },
3092
3093  cumulativeOffset: function(element) {
3094    var valueT = 0, valueL = 0;
3095    do {
3096      valueT += element.offsetTop  || 0;
3097      valueL += element.offsetLeft || 0;
3098      element = element.offsetParent;
3099    } while (element);
3100    return [valueL, valueT];
3101  },
3102
3103  positionedOffset: function(element) {
3104    var valueT = 0, valueL = 0;
3105    do {
3106      valueT += element.offsetTop  || 0;
3107      valueL += element.offsetLeft || 0;
3108      element = element.offsetParent;
3109      if (element) {
3110        if(element.tagName=='BODY') break;
3111        var p = Element.getStyle(element, 'position');
3112        if (p == 'relative' || p == 'absolute') break;
3113      }
3114    } while (element);
3115    return [valueL, valueT];
3116  },
3117
3118  offsetParent: function(element) {
3119    if (element.offsetParent) return element.offsetParent;
3120    if (element == document.body) return element;
3121
3122    while ((element = element.parentNode) && element != document.body)
3123      if (Element.getStyle(element, 'position') != 'static')
3124        return element;
3125
3126    return document.body;
3127  },
3128
3129  // caches x/y coordinate pair to use with overlap
3130  within: function(element, x, y) {
3131    if (this.includeScrollOffsets)
3132      return this.withinIncludingScrolloffsets(element, x, y);
3133    this.xcomp = x;
3134    this.ycomp = y;
3135    this.offset = this.cumulativeOffset(element);
3136
3137    return (y >= this.offset[1] &&
3138            y <  this.offset[1] + element.offsetHeight &&
3139            x >= this.offset[0] &&
3140            x <  this.offset[0] + element.offsetWidth);
3141  },
3142
3143  withinIncludingScrolloffsets: function(element, x, y) {
3144    var offsetcache = this.realOffset(element);
3145
3146    this.xcomp = x + offsetcache[0] - this.deltaX;
3147    this.ycomp = y + offsetcache[1] - this.deltaY;
3148    this.offset = this.cumulativeOffset(element);
3149
3150    return (this.ycomp >= this.offset[1] &&
3151            this.ycomp <  this.offset[1] + element.offsetHeight &&
3152            this.xcomp >= this.offset[0] &&
3153            this.xcomp <  this.offset[0] + element.offsetWidth);
3154  },
3155
3156  // within must be called directly before
3157  overlap: function(mode, element) {
3158    if (!mode) return 0;
3159    if (mode == 'vertical')
3160      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
3161        element.offsetHeight;
3162    if (mode == 'horizontal')
3163      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
3164        element.offsetWidth;
3165  },
3166
3167  page: function(forElement) {
3168    var valueT = 0, valueL = 0;
3169
3170    var element = forElement;
3171    do {
3172      valueT += element.offsetTop  || 0;
3173      valueL += element.offsetLeft || 0;
3174
3175      // Safari fix
3176      if (element.offsetParent == document.body)
3177        if (Element.getStyle(element,'position')=='absolute') break;
3178
3179    } while (element = element.offsetParent);
3180
3181    element = forElement;
3182    do {
3183      if (!window.opera || element.tagName=='BODY') {
3184        valueT -= element.scrollTop  || 0;
3185        valueL -= element.scrollLeft || 0;
3186      }
3187    } while (element = element.parentNode);
3188
3189    return [valueL, valueT];
3190  },
3191
3192  clone: function(source, target) {
3193    var options = Object.extend({
3194      setLeft:    true,
3195      setTop:     true,
3196      setWidth:   true,
3197      setHeight:  true,
3198      offsetTop:  0,
3199      offsetLeft: 0
3200    }, arguments[2] || {})
3201
3202    // find page position of source
3203    source = $(source);
3204    var p = Position.page(source);
3205
3206    // find coordinate system to use
3207    target = $(target);
3208    var delta = [0, 0];
3209    var parent = null;
3210    // delta [0,0] will do fine with position: fixed elements,
3211    // position:absolute needs offsetParent deltas
3212    if (Element.getStyle(target,'position') == 'absolute') {
3213      parent = Position.offsetParent(target);
3214      delta = Position.page(parent);
3215    }
3216
3217    // correct by body offsets (fixes Safari)
3218    if (parent == document.body) {
3219      delta[0] -= document.body.offsetLeft;
3220      delta[1] -= document.body.offsetTop;
3221    }
3222
3223    // set position
3224    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
3225    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
3226    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
3227    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
3228  },
3229
3230  absolutize: function(element) {
3231    element = $(element);
3232    if (element.style.position == 'absolute') return;
3233    Position.prepare();
3234
3235    var offsets = Position.positionedOffset(element);
3236    var top     = offsets[1];
3237    var left    = offsets[0];
3238    var width   = element.clientWidth;
3239    var height  = element.clientHeight;
3240
3241    element._originalLeft   = left - parseFloat(element.style.left  || 0);
3242    element._originalTop    = top  - parseFloat(element.style.top || 0);
3243    element._originalWidth  = element.style.width;
3244    element._originalHeight = element.style.height;
3245
3246    element.style.position = 'absolute';
3247    element.style.top    = top + 'px';
3248    element.style.left   = left + 'px';
3249    element.style.width  = width + 'px';
3250    element.style.height = height + 'px';
3251  },
3252
3253  relativize: function(element) {
3254    element = $(element);
3255    if (element.style.position == 'relative') return;
3256    Position.prepare();
3257
3258    element.style.position = 'relative';
3259    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
3260    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
3261
3262    element.style.top    = top + 'px';
3263    element.style.left   = left + 'px';
3264    element.style.height = element._originalHeight;
3265    element.style.width  = element._originalWidth;
3266  }
3267}
3268
3269// Safari returns margins on body which is incorrect if the child is absolutely
3270// positioned.  For performance reasons, redefine Position.cumulativeOffset for
3271// KHTML/WebKit only.
3272if (Prototype.Browser.WebKit) {
3273  Position.cumulativeOffset = function(element) {
3274    var valueT = 0, valueL = 0;
3275    do {
3276      valueT += element.offsetTop  || 0;
3277      valueL += element.offsetLeft || 0;
3278      if (element.offsetParent == document.body)
3279        if (Element.getStyle(element, 'position') == 'absolute') break;
3280
3281      element = element.offsetParent;
3282    } while (element);
3283
3284    return [valueL, valueT];
3285  }
3286}
3287
3288Element.addMethods();
3289/** End: prototype.js */
3290/** Start: element.js */
3291Ajax.Request.prototype.evalResponse=Prototype.emptyFunction;Ajax.Request.prototype.evalJSON=function(){if(this.options.evaluate===false||this.transport.readyState!==4){return }var contentType=this.getHeader("Content-type");if(contentType&&contentType.strip().match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)){try{return eval(this.transport.responseText)}catch(e){}}};var tc_ElementSubject=Class.create();tc_ElementSubject.instances={};tc_ElementSubject.prototype={_element:undefined,_observers:undefined,_status:undefined,_notify:function(){var observers=this._observers;for(var index=0;
3291index<observers.length;index++){observers[index].update(this)}},_setStatus:function(status){this._status=status;this._notify()},initialize:function(subject){if(tc_ElementSubject.instances[subject.id]!==true){tc_ElementSubject.instances[subject.id]=true}this._element=subject;this._observers=[]},add:function(observer){this._observers.push(observer)},getElement:function(){return this._element},getStatus:function(){return this._status},remove:function(observer){this._observers=this._observers.without(observer)}};var methods={removeEvents:function(element){var e=$(element);if(e.events){for(var type in e.events){for(var index in e.events[type]){if((Prototype.Browser.IE&&e.tagName=="IFRAME")||(!Prototype.Browser.IE&&type=="dataavailable")){Event._oldStopObserving(e,type,e.events[type][index])}if(index!="0"){delete e.events[type][index]}}}}return e},__destruct:function(element){var e=$(element);if(e.subject){e.subject._setStatus("deleted");delete tc_ElementSubject.instances[e.id]}e.removeEvents();e.remove()},getCurrentStyle:function(element,stylename){var e=$(element);var style=null;if(Prototype.Browser.WebKit&&!["visibillity","position","display"].include(stylename)){var els=e.style;var originalVisibility=els.visibility;var originalPosition=els.position;var originalDisplay=els.display;els.visibility="hidden";els.position="absolute";els.display="block"}if(e.currentStyle!==undefined){style=e.currentStyle[stylename]}else{style=window.getComputedStyle(e,null)[stylename]}if(Prototype.Browser.WebKit&&!["visibillity","position","display"].include(stylename)){els.display=originalDisplay;els.position=originalPosition;els.visibility=originalVisibility}return style},cumulativeOffset:function(element){var valueT=0,valueL=0;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;element=element.offsetParent}while(element);return{left:valueL,top:valueT}},visibleOffset:function(element){return Position.visibleOffset(element)},isScrolled:function(element){return element.scrollTop>0||element.scrollLeft>0},getInnerDimensions:function(element){var tmpZoom;var width=0,height=0;var paddingLeft=0,paddingRight=0,paddingTop=0,paddingBottom=0;paddingLeft=parseInt(element.getCurrentStyle("paddingLeft"),10);paddingRight=parseInt(element.getCurrentStyle("paddingRight"),10);paddingTop=parseInt(element.getCurrentStyle("paddingTop"),10);paddingBottom=parseInt(element.getCurrentStyle("paddingBottom"),10);if(Prototype.Browser.IE){tmpZoom=element.style.zoom;element.style.zoom="1"}width=element.clientWidth-paddingLeft-paddingRight;height=element.clientHeight-paddingTop-paddingBottom;if(Prototype.Browser.IE){element.style.zoom=tmpZoom}return{width:width,height:height,padding:{top:paddingTop,bottom:paddingBottom,right:paddingRight,left:paddingLeft}}},getVisibleDimensions:function(element){var width=0,height=0,dimensions,element,child,childDimensions,scrollElement,scrollElementDimensions,scrollElements,childVisibleOffset,visibleOffset;element=$(element);visibleOffset=Position.visibleOffset(element);if(visibleOffset.visible==true){dimensions=element.getDimensions();width=dimensions.width;height=dimensions.height;scrollElements=visibleOffset.scrollElements;child=element;childDimensions=dimensions;for(var i=0;i<scrollElements.length;i++){scrollElement=$(scrollElements[i]);scrollElementDimensions=scrollElement.getDimensions();childVisibleOffset=Position.relativeVisibleOffset(child,scrollElement);if(childVisibleOffset.top<0){height=height+childVisibleOffset.top}if(childDimensions.height+childVisibleOffset.top>scrollElementDimensions.height){height=height-(childDimensions.height+childVisibleOffset.top-scrollElementDimensions.height)}if(childVisibleOffset.left<0){width=width+childVisibleOffet.left}if(childDimensions.width+childVisibleOffset.left>scrollElementDimensions.width){width=width-(childDimensions.width+childVisibleOffset.left-scrollElementDimensions.width)}childDimensions=scrollElementDimensions;child=scrollElement}}return{width:width,height:height}},getPositionedElement:function(element){do{if(element.tagName==="BODY"){return element}var p=Element.getStyle(element,"position");if(p!=="static"){return element}element=element.offsetParent}while(element);return element}};methods.getId=(function(){var elementIdCount=1;return function(element){if(typeof element==="string"){return element}
3291if(typeof element.id!=="string"||element.id.length===0){element.id="_tcGeneratedId"+elementIdCount++}return element.id}})();Element.addMethods(methods);if(Element.tcBaseExtend===undefined){Element.tcBaseExtend=Element.extend;Element.extend=function(element){if(!element||element.nodeType==3){return element}if(!element.subject&&element.tagName&&element.id){element.subject=new tc_ElementSubject(element)}return Element.tcBaseExtend(element)};Element.extend.cache=Element.tcBaseExtend.cache}Object.extend(Event,{KEY_SHIFT:16,_oldObserveAndCache:Event._observeAndCache,_oldStopObserving:Event.stopObserving,_observeAndCache:function(el,type,func,useCapture){if(el.$$euid===undefined){el.$$euid=Event._euid++}if(!func.$$guid){func.$$guid=Event._guid++}if(type.match(/:/)){var subType=type;var handler=func;var wrapper=function(event){if(event.eventName&&event.eventName!=subType){return }handler.call(el,event)};wrapper.$$guid=func.$$guid;type="dataavailable";func=wrapper}else{if(tc_Events.mouseenter.check(el,type)===true){tc_Events.mouseenter.observe(el,type,func,useCapture);return }else{if(tc_Events.mouseleave.check(el,type)===true){tc_Events.mouseleave.observe(el,type,func,useCapture);return }}}if(!el.events){el.events={}}if((Prototype.Browser.IE&&el.tagName=="IFRAME")||(!Prototype.Browser.IE&&type=="dataavailable")){if(!el.events[type]){el.events[type]={}}el.events[type][func.$$guid]=func;Event._oldObserveAndCache(el,type,func,useCapture);return }var handlers=el.events[type];if(!handlers){handlers=el.events[type]={};if(el["on"+type]){handlers[0]=el["on"+type]}el["on"+type]=Event._handleEvent}handlers[func.$$guid]=func},stopObserving:function(el,type,func){el=$(el);if((Prototype.Browser.IE&&el.tagName=="IFRAME")||(!Prototype.Browser.IE&&type=="dataavailable")){Event._oldStopObserving(el,type,func)}else{if(tc_Events.mouseenter.check(el,type)===true){tc_Events.mouseenter.stopObserving(el,type,func);return }else{if(tc_Events.mouseleave.check(el,type)===true){tc_Events.mouseleave.stopObserving(el,type,func);return }}}if(type=="keypress"&&(Prototype.Browser.WebKit||el.attachEvent)){type="keydown"}if(el.events&&el.events[type]){delete el.events[type][func.$$guid]}},
3292_handleEvent:function(e){
3293    if(e === undefined && window.event === undefined) {
3294        // console.log(arguments.callee.caller.toString());
3295    }else {
3296        var returnValue=true;e=e||Event._fixEvent(window.event);var handlers=this.events[e.type];if(handlers===undefined){handlers={}}var el=$(this);for(var i in handlers){el.$$handleEvent=handlers[i];if(el.$$handleEvent(e)===false){returnValue=false}}if(returnValue===false){Event.stop(e)}return returnValue
3297    }
3298},
3299_fixEvent:function(e){e.preventDefault=Event._preventDefault;e.stopPropagation=Event._stopPropagation;if(e.target===undefined){e.target=e.srcElement};return e},_preventDefault:function(){this.returnValue=false},_stopPropagation:function(){this.cancelBubble=true},_guid:1,_euid:1});var tc_Events={};tc_Events.mouseenter={_count:0,_elements:{},check:function(element,type){return type==="mouseenter"&&Prototype.Browser.IE!==true},observe:function(el,type,func,useCapture){if(this._count===0){this._elements={};Event.observe(document.getElementsByTagName("html")[0],"mousemove",this.handler)}el.getId();if(this._elements[el.id]===undefined||el.$$euid!==this._elements[el.id].element.$$euid){if(this._elements[el.id]===undefined){this._count++}this._elements[el.id]={element:el,funcs:{},status:undefined}}this._elements[el.id].funcs[func.$$guid]=func},stopObserving:function(el,type,func){delete this._elements[el.id].funcs[func.$$guid];for(var temp in this._elements[el.id].funcs){return }delete this._elements[el.id];this._count--;if(this._count===0){Event.stopObserving(document.getElementsByTagName("html")[0],"mousemove",this.handler)}},_getElements:function(){var elements={};for(var id in this._elements){element=$(this._elements[id].element);if(element===undefined||element===null){delete this._elements[id];this._count--;continue}this._elements[id].object=element;elements[id]=this._elements[id]}if(this._count===0){Event.stopObserving(document.getElementsByTagName("html")[0],"mouseover",this.handler)}return{elements:elements,count:this._count}},handler:function(event){var data=tc_Events.mouseenter._getElements();var elements=data.elements,count=data.count;var parent=Event.element(event);while(count>0&&parent){for(id in elements){if(parent==elements[id].object){if(elements[id].status!=="over"){elements[id].status="over";for(var func in elements[id].funcs){elements[id].object.$$handleEvent=elements[id].funcs[func];elements[id].object.$$handleEvent(event)}}delete elements[id];count--}}try{parent=parent.parentNode}catch(error){parent=null}}for(id in elements){elements[id].status="out"}}};tc_Events.mouseleave=Object.extend({},tc_Events.mouseenter);tc_Events.mouseleave.check=function(element,type){return type==="mouseleave"&&Prototype.Browser.IE!==true};tc_Events.mouseleave.handler=function(event){var data=tc_Events.mouseleave._getElements();var elements=data.elements,count=data.count;var parent=Event.element(event);while(count>0&&parent){for(id in elements){if(parent==elements[id].object){if(elements[id].status!=="over"){elements[id].status="over"}delete elements[id];count--}}try{parent=parent.parentNode}catch(error){parent=null}}for(id in elements){if(elements[id].status!=="out"){elements[id].status="out";for(var func in elements[id].funcs){elements[id].object.$$handleEvent=elements[id].funcs[func];elements[id].object.$$handleEvent(event)}}}};Event.pointer=function(event){return{x:event.pageX||(event.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft)),y:event.pageY||(event.clientY+(document.documentElement.scrollTop||document.body.scrollTop))}};Event.fire=function(element,eventName,memo){element=$(element);if(element==document&&document.createEvent&&!element.dispatchEvent){element=document.documentElement}var event;if(document.createEvent){event=document.createEvent("HTMLEvents");event.initEvent("dataavailable",true,true)}else{event=document.createEventObject();event.eventType="ondataavailable"}event.eventName=eventName;event.memo=memo||{};if(document.createEvent){element.dispatchEvent(event)}else{element.fireEvent(event.eventType,event)}return event};var contentLoaded=function(){var timer,fired=false;function fireContentLoadedEvent(){if(fired){return }if(timer){window.clearInterval(timer)}Event.fire(document,"dom:loaded");fired=true}if(document.addEventListener){if(Prototype.Browser.WebKit){timer=window.setInterval(function(){if(/loaded|complete/.test(document.readyState)){fireContentLoadedEvent()}},0);Event.observe(window,"load",fireContentLoadedEvent)}else{document.addEventListener("DOMContentLoaded",fireContentLoadedEvent,false)}}else{document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");$("__onDOMContentLoaded").onreadystatechange=function(){if(this.readyState=="complete"){this.onreadystatechange=null;fireContentLoadedEvent()}}}};contentLoaded();Position.relativeCumulativeOffset=function(element,parent){var valueT=0,valueL=0;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;element=element.offsetParent}
3299while(element&&parent.id!=element.id);return[valueL,valueT]};Position.parentNodeOffset=function(element){var top=0,left=0,p,rTop=0,rLeft=0,rPos;var ePos=Position.cumulativeOffset(element);top=ePos[1];left=ePos[0];if(element.parentNode){var pPos=Position.cumulativeOffset(element.parentNode);top-=pPos[1];left-=pPos[0]}return{top:top,left:left}};Position.visibleOffsetCounter=0;Position.visibleOffsetCounter1=0;Position.viewableOffsetCounter=0;Position.relativeVisibleOffset=function(element,parent){var valueT=0,valueL=0,valueRealT=0,valueRealL=0,scrollElements=[],pos,p,end;var visible=true;end=parent;if(element!=parent){while(element&&element!=end){p=element.parentNode;pos=Position.parentNodeOffset(element);if(p!=document.getElementsByTagName("body")[0]){valueT+=pos.top-p.scrollTop;valueL+=pos.left-p.scrollLeft}else{valueT+=pos.top;valueL+=pos.left}valueRealT+=pos.top;valueRealL+=pos.left;if(p!=document.getElementsByTagName("body")[0]){if(p.scrollHeight>p.offsetHeight||p.scrollWidth>p.offsetWidth){if(p.id==undefined||p.id===""){p.id="tc_viewable_offset"+(++Position.viewableOffsetCounter)}scrollElements.push(p.id)}if(valueT>=p.offsetHeight||valueT<0){if($(p).getCurrentStyle("overflow")!="visible"){visible=false}}if(visible===true&&(valueL>=p.offsetWidth||valueL<0)){if($(p).getCurrentStyle("overflow")!="visible"){visible=false}}}element=p}}return{top:valueT,left:valueL,realTop:valueRealT,realLeft:valueRealL,visible:(scrollElements.length>0?visible:true),scrollElements:scrollElements}};Position.visibleOffset=function(element){return Position.relativeVisibleOffset(element,document.getElementsByTagName("body")[0])};document.isDomLoaded=false;Event.observe(document,"dom:loaded",function(){this.isDomLoaded=true});document.isCssLoaded=false;Event.observe(document,"css:loaded",function(){document.isCssLoaded=true});Event.observe(window,"load",function(){Event.fire(document,"css:loaded")});
3300
3301/** End: element.js */
3302/** Start: pageSize.js */
3303if(window.tc_PageSize===undefined){var tc_PageSize=function(){};tc_PageSize.getSize=function(){var size=tc_PageSize.getVisibleSize();var htmlElement=document.getElementsByTagName("html")[0];var bodyElement=document.getElementsByTagName("body")[0];var height=htmlElement.scrollHeight;if(height<size.height){height=size.height}if(height<bodyElement.scrollHeight){height=bodyElement.scrollHeight}var width=htmlElement.scrollWidth;if(width<size.width){width=size.width}if(width<bodyElement.scrollWidth){width=bodyElement.scrollWidth}return{width:width,height:height}};tc_PageSize.getVisibleSize=function(){var htmlElement=document.getElementsByTagName("html")[0];var width=htmlElement.clientWidth;var height=htmlElement.clientHeight;if(window.opera){height=window.innerHeight;width=window.innerWidth;if(htmlElement.clientWidth>width){height-=16}if(htmlElement.clientHeight>height){width-=16}}return{width:width,height:height}};tc_PageSize.getVisiblePosition=function(){var top=0;var left=0;if(window.pageXOffset===undefined){if(document.documentElement.scrollTop===undefined){top=document.body.scrollTop;left=document.body.scrollLeft}else{top=document.documentElement.scrollTop;left=document.documentElement.scrollLeft}}else{top=window.pageYOffset;left=window.pageXOffset}return{top:top,left:left}}};
3304
3305/** End: pageSize.js */
3306/** Start: form.js */
3307if (window.tcc_package_tcsmainloader === undefined) {tc_load("/packages/tc-loader-main.js");};tcc_Form_Active="";function tcc_Form(name){this.name=name;this._observers=[];setTimeout(function(){var form=$(name);if(form){form.defaultSubmit=form.submit;form.submit=function(e){var rs=true;if(this.onsubmit!==undefined){if(Prototype.Browser.IE){rs=this.onsubmit()}else{rs=this.onsubmit(e)}}if(rs!==false){this.defaultSubmit();return }};form.subject.add(this)}}.bind(this),10)}tcc_Form.prototype._status=1;tcc_Form.prototype._observers=[];tcc_Form.prototype._ajaxResponse="";tcc_Form.prototype._jsonResponse=undefined;tcc_Form.prototype.formRequest={};tcc_Form.prototype.showLoading=true;tcc_Form.prototype.addObserver=function(observer){for(var i=0;i<this._observers.length;i++){if(this._observers[i]===observer){return }}this._observers.push(observer)};tcc_Form.prototype.removeObserver=function(observer){for(var i=0;i<this._observers.length;i++){if(this._observers[i]===observer){this._observers.splice(i,1)}}};tcc_Form.prototype.notify=function(){this._observers._each(function(observer){observer.update(this)}.bind(this))};tcc_Form.prototype.getAjaxResponse=function(){return this._ajaxResponse};tcc_Form.prototype.getJsonResponse=function(){return this._jsonResponse};tcc_Form.prototype.setStatus=function(status){this._status=status;this.notify()};tcc_Form.prototype.update=function(subject){if(subject.getStatus()=="deleted"){}};tcc_Form.prototype.getStatus=function(){return this._status};tcc_Form.prototype.validate=function(formElement){return this.updateElement(formElement.name,"validate")};tcc_Form.prototype.observe=function(formElement){return this.updateElement(formElement.name,"observe")};tcc_Form.prototype.buildAdditionalParam=function(name){return"tcc_Form_"+name};tcc_Form.prototype.getForm=function(){return $(this.name)};tcc_Form.prototype.updateElement=function(fieldname,action){var params=$H({});params[this.buildAdditionalParam("field")]=fieldname;this.sendRequest(params,action,this.updateElements.bind(this))};tcc_Form.prototype.updateElements=function(response,json){response=eval(response.responseText.stripScripts());var oldElement=null;var html="";var oldValues=null;var newElement=null;var oldVisibility;if(response.length>0){for(var i=0;i<response.length;i++){oldElement=$(response[i][0]);html=response[i][1];if(oldElement==undefined){if(response[i][2]!=undefined&&response[i][3]!=undefined){oldElement=$(response[i][3]);switch(response[i][2]){case 1:new Insertion.After(oldElement,html);break;case 2:new Insertion.Before(oldElement,html);break;default:break}}}else{oldVisibility=oldElement.visible();new Insertion.After(oldElement,html.stripScripts());setTimeout(function(){try{html.evalScripts()}catch(e){}},10);oldValues=Form.getElements(oldElement);oldElement.__destruct();if(oldVisibility==false){$(response[i][0]).hide()}for(var j=0;j<oldValues.length;j++){document.getElementsByName(oldValues[j].name)[0].value=oldValues[j].value}}}}
3307if(tcc_Form_Active!=""){document.getElementsByName(tcc_Form_Active)[0].focus()}};tcc_Form.prototype.getRequestProgress=function(setProgress){if(this.getForm()===null||this.getForm()===undefined){setProgress(100);return }new Ajax.Request("/s/tcc/UploadProgress.php",{method:"get",parameters:{UPLOAD_IDENTIFIER:this.getForm().getInputs("hidden","UPLOAD_IDENTIFIER")[0].value,time:new Date().getTime()},onComplete:function(request,response){if(response===null){response={percent:100}}setProgress(response.percent)}})};tcc_Form.prototype.submitForm=function(){this.setStatus(4);var loading=undefined;if(this.showLoading){loading=function(request){var load;if(this.getForm()!==null&&this.getForm().getInputs("hidden","UPLOAD_IDENTIFIER").length===0){var r=request;load={get:function(setLoading){var status=true;try{status=r!==undefined&&r.status===0}catch(e){}setLoading(status)}}}else{load={get:this.getRequestProgress.bind(this),percent:true}}tc_Loading.add(load)}.bind(this)}var complete;if(this.getForm().getInputs("file").length===0){complete=function(response,json){this._ajaxResponse=response;this._jsonResponse=json;this.setStatus(5)}.bind(this);this.sendRequest(new Hash(),undefined,complete,loading,this.formRequest)}else{loading();complete=function(){Event.stopObserving(this.name+"_FileUploadIframe","load",complete);this._ajaxResponse=$(this.name+"_FileUploadIframe").contentWindow;this._jsonResponse=$(this.name+"_FileUploadIframe").contentWindow.response;this.setStatus(5)}.bind(this);Event.observe(this.name+"_FileUploadIframe","load",complete)}};tcc_Form.prototype.sendRequest=function(params,action,complete,loading,request){if(request===undefined){request={}}var normalSubmit=false;if(action!=undefined){params[this.buildAdditionalParam("action")]=action}else{normalSubmit=true}var date=new Date();params.t=date.getTime();var form=this.getForm();var url=form.action;if(form.action.lastIndexOf("?")==-1){url+="?"}if(normalSubmit===false){url+="&tcc_Form_action_request="+form.id}request.method=form.method;request.parameters=Form.serialize(form);request.onSuccess=complete;if(loading!==undefined){request.onLoading=loading}new Ajax.Request(url+"&"+params.toQueryString(),request)};tcc_Form.prototype.setActive=function(e){tcc_Form_Active=Event.element(e).name};tcc_Form.prototype.setInactive=function(e){};function tcc_Form_Element(id,name,form,type){this.id=id;this.name=name;this.tcc_Form=form;switch(type){case"ParentGroup":this.behavior=new tcc_Form_Element_Behavior_ParentGroup(this,form);break;case"Editor":this.behavior=new tcc_Form_Element_Behavior_Editor(this,form);break;case"Normal":default:this.behavior=new tcc_Form_Element_Behavior_Normal(this,form);break}}tcc_Form_Element.prototype.behavior=null;tcc_Form_Element.prototype.validate=true;tcc_Form_Element.prototype.observe=false;tcc_Form_Element.prototype.changed=true;tcc_Form_Element.prototype.getFormElements=function(){return this.behavior.getFormElements()};tcc_Form_Element.prototype.setObserve=function(observe){this.observe=observe};tcc_Form_Element.prototype.setValidate=function(validate){this.validate=validate};tcc_Form_Element.prototype.update=function(e){if(this.validate==true||this.observe==true){return this.behavior.update(e)}};tcc_Form_Element.prototype.callUpdate=function(){if(this.observe==true){this.tcc_Form.observe(this);return }if(this.validate==true){this.tcc_Form.validate(this);return }return };tcc_Form_Element.prototype.getValue=function(){return this.behavior.getValue()};tcc_Form_Element.prototype.serialize=function(){return this.behavior.serialize()};function tcc_Form_Element_Behavior_Normal(formElement){this.tcc_Form_Element=formElement;this.element=document.getElementById(this.tcc_Form_Element.id);Event.observe(this.element,"change",this.tcc_Form_Element.update.bind(this.tcc_Form_Element));Event.observe(this.element,"blur",this.tcc_Form_Element.tcc_Form.setInactive.bind(this));Event.observe(this.element,"focus",this.tcc_Form_Element.tcc_Form.setActive.bind(this))}tcc_Form_Element_Behavior_Normal.prototype.getFormElements=function(){return([this.element])};tcc_Form_Element_Behavior_Normal.prototype.update=function(e){if(this.tcc_Form_Element.observe==true){this.tcc_Form_Element.tcc_Form.observe(this.tcc_Form_Element);return }if(this.tcc_Form_Element.validate==true){this.tcc_Form_Element.tcc_Form.validate(this.tcc_Form_Element);return }return };tcc_Form_Element_Behavior_Normal.prototype.getValue=function(){return Form.Element.getValue(this.element.i
3307d)};tcc_Form_Element_Behavior_Normal.prototype.serialize=function(){return Form.Element.serialize(this.element.id)};function tcc_Form_Element_Behavior_ParentGroup(formElement){this.tcc_Form_Element=formElement;this.changed=[];this.elements=[];var elements=Form.getElements(this.tcc_Form_Element.id);var elementCount=0;var changed=false;for(var i=0;i<elements.length;i++){if(elements[i].value!=""){changed=true}this.changed[elements[i].name]=changed;this.elements[elementCount++]=elements[i].name;Event.observe(elements[i],"change",this.tcc_Form_Element.update.bind(this.tcc_Form_Element));Event.observe(elements[i],"focus",this.tcc_Form_Element.tcc_Form.setActive.bind(this));Event.observe(elements[i],"blur",this.tcc_Form_Element.tcc_Form.setInactive.bind(this))}}tcc_Form_Element_Behavior_ParentGroup.prototype.getFormElements=function(){return Form.getElements(this.tcc_Form_Element.id)};tcc_Form_Element_Behavior_ParentGroup.prototype.update=function(e){var element=Event.element(e);var allChanged=true;this.changed[element.name]=true;for(var i=0;i<this.elements.length;i++){if(this.changed[this.elements[i]]==false){allChanged=false}}if(allChanged==true){this.tcc_Form_Element.callUpdate()}};tcc_Form_Element_Behavior_ParentGroup.prototype.getValue=function(){};tcc_Form_Element_Behavior_ParentGroup.prototype.serialize=function(){};function tcc_Form_Element_Behavior_Editor(formElement,form){this.tcc_Form_Element=formElement;this.element=document.getElementById(this.tcc_Form_Element.id);form.addObserver(this)}tcc_Form_Element_Behavior_Editor.prototype.getFormElements=function(){return([this.element])};tcc_Form_Element_Behavior_Editor.prototype.update=function(subject){if(window["tc_Editor_"+this.element.id]===undefined){return }this.element.value=window["tc_Editor_"+this.element.id].getHTML();if(subject.getStatus()==4){window["tc_Editor_"+this.element.id].remove()}};tcc_Form_Element_Behavior_Editor.prototype.getValue=function(){};tcc_Form_Element_Behavior_Editor.prototype.serialize=function(){};function tcc_Form_Element_Value(tcc_Form_Element,action){this.tcc_Form_Element=tcc_Form_Element;this.action=action}tcc_Form_Element_Value.prototype.tcc_Form_Element=null;tcc_Form_Element_Value.prototype.action="";tcc_Form_Element_Value.prototype.positionElement=null;tcc_Form_Element_Value.prototype.containerElement=null;tcc_Form_Element_Value.prototype.show=function(positionElement){this.positionElement=positionElement;var params=$H({});this.tcc_Form_Element.tcc_Form.sendRequest(params,this.action,this.display.bind(this),this.loading.bind(this))};tcc_Form_Element_Value.prototype.loading=function(){this.setContainerContent('<div class="formElementValueLoading"><span>Loading</span></div>')};tcc_Form_Element_Value.prototype.getContainerElement=function(){if(this.containerElement==undefined){this.containerElement=document.createElement("div");var innerElement=document.createElement("div");innerElement.style.clear="both";innerElement.style.zIndex="100";innerElement.style.position="absolute";innerElement.style.marginTop=(0+5)+"px";Element.addClassName(innerElement,"formElementValueContainer");this.containerElement.appendChild(innerElement);this.positionElement.appendChild(this.containerElement)}return this.containerElement};tcc_Form_Element_Value.prototype.setContainerContent=function(html){this.getContainerElement().firstChild.innerHTML=html};tcc_Form_Element_Value.prototype.start=function(){this.show(this.positionElement)};tcc_Form_Element_Value.prototype.display=function(response,json){this.setContainerContent(response.responseText);var starts=document.getElementsByClassName("start",this.containerElement);for(var i=0;i<starts.length;i++){Event.observe(starts[i],"click",this.start.bind(this));starts[i].style.cursor="pointer"}var closes=document.getElementsByClassName("close",this.containerElement);for(var i=0;i<closes.length;i++){Event.observe(closes[i],"click",this.close.bind(this));closes[i].style.cursor="pointer"}var folders=document.getElementsByClassName("folder",this.containerElement);for(var i=0;i<folders.length;i++){Event.observe(folders[i],"click",this.updateShow.bind(this));folders[i].style.cursor="pointer"}var values=document.getElementsByClassName("value",this.containerElement);for(var i=0;i<values.length;i++){Event.observe(values[i],"click",this.setValue.bind(this));values[i].style.cursor="pointer"}};tcc_Form_Element_Value.prototype.updateShow=function(e){var params=$H({});value=this.sliceValue(Event.element(e));if(value!=false){params[this.tcc_Form_Element.tcc_Form.buildAdditionalParam("folder")]=value;this.tcc_Form_Element.tcc_Form.sendRequest(params,this.action,this.update.bind(this))}};tcc_Form_Element_Value.prototype.update=function(response,json){this.display(response,json)};tcc_Form_Element_Value.prototype.close=function(){Element.remove(this.containerElement);this.containerElement=null};tcc_Form_Element_Value.prototype.setValue=function(e){var element=Event.element(e);
3307var startPosition=element.id.indexOf("_");var value=this.sliceValue(element);if(value!=false){$(this.tcc_Form_Element.id).value=value;var e=null;this.tcc_Form_Element.update(e)}this.close()};tcc_Form_Element_Value.prototype.sliceValue=function(element){var startPosition=0;if(element!=undefined){startPosition=element.id.indexOf("_");if(startPosition==-1){return false}return element.id.slice(startPosition+1,element.id.length)}return false};function tcc_Form_Element_TextSelect(element,multiple){this._element=element;this._options=$(element).value.evalJSON();this._multiple=multiple}tcc_Form_Element_TextSelect.prototype={_element:undefined,_multiple:false,_options:undefined,select:function(value){if(this._multiple){var deleted=false;for(var index=0;index<this._options.length;index++){if(this._options[index]==value){$(this._element+"_item_"+value).removeClassName("selected");this._options.splice(index,1);deleted=true;break}}if(!deleted){this._options.push(value);$(this._element+"_item_"+value).className+=" selected"}}else{if(this._options.length==1&&this._options[0]!=value){var element=$(this._element+"_item_"+this._options[0]);if(element){element.removeClassName("selected")}}this._options=[value];$(this._element+"_item_"+value).addClassName("selected")}$(this._element).value=this._options.toJSON()},setSelected:function(options){for(var index=0;index<this._options.length;index++){$(this._element+"_item_"+this._options[index]).removeClassName("selected")}if(!this._multiple){options=[options]}this._options=options;for(index=0;index<this._options.length;index++){var element=$(this._element+"_item_"+this._options[index]);if(element){element.className+=" selected"}}$(this._element).value=this._options.toJSON()}};function tcc_Form_Element_Color(element,label,defaultColors){this._element=element;this._label=label;this._defaultColors=defaultColors}tcc_Form_Element_Color.prototype={_defaultColors:undefined,_element:undefined,_label:undefined,show:function(){tc_load("/s/tc-www/js/colorPicker.js");var instance=this;var code='<div id="tcc_'+this._element+'_color_picker" style="width: 300px; padding: 10px;" class="tcc_color_picker"></div><div id="tcc_'+this._element+'_color_buttons" class="tcc_color_buttons"><ul><li id="tcc_'+this._element+'_color_button_apply" class="tcc_color_button tcc_color_button_apply"><a href="javascript:void(0);">'+tc_translate("apply")+'</a></li><li id="tcc_'+this._element+'_color_button_cancel" class="tcc_color_button tcc_color_button_cancel"><a href="javascript:void(0);">'+tc_translate("cancel")+'</a></li></ul></div><div class="clear"></div>';var overlay=new tc_Overlay(this._element+"_color");overlay.get().addClassName("tcc_color_picker_overlay");overlay.setCloseOnClick(false);overlay.open();var w=new tc_Window(this._element+"_color");w.get().addClassName("tcc_color_picker_window");w.setTitle(this._label);w.setContentHTML(code);var colorPicker=new tc_ColorPicker("tcc_"+this._element+"_color_picker",$(this._element).value);colorPicker.defaultColors=this._defaultColors;var close=function(){colorPicker.destruct();overlay.close();w.close()};var actions=new tc_Window_Actions();actions.add({id:"close",title:tc_translate("close"),callback:close});w.setActions(actions);w.open();colorPicker.run();w.refresh();Event.observe("tcc_"+this._element+"_color_button_apply","click",function(){$(instance._element).value=colorPicker.getColor();$(instance._element+"_color_preview").style.backgroundColor="#"+colorPicker.getColor();close()});Event.observe("tcc_"+this._element+"_color_button_cancel","click",close)}};
3308
3309/** End: form.js */
3310
3311}
3312/* Function to detect mobile user agent */
3313function RedirectMobile(url){if(navigator.userAgent.match(/Android/i)||navigator.userAgent.match(/webOS/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPad/i)||navigator.userAgent.match(/iPod/i)||navigator.userAgent.match(/BlackBerry/i)||navigator.userAgent.match(/Windows Phone/i)){window.location.href = url}}

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.