

/*  Prototype JavaScript framework, version 1.6.1
 *  (c) 2005-2009 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
 *--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.6.1',

  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
    }
  })(),

  BrowserFeatures: {
    XPath: !!document.evaluate,
    SelectorsAPI: !!document.querySelector,
    ElementExtensions: (function() {
      var constructor = window.Element || window.HTMLElement;
      return !!(constructor && constructor.prototype);
    })(),
    SpecificElementExtensions: (function() {
      if (typeof window.HTMLDivElement !== 'undefined')
        return true;

      var div = document.createElement('div');
      var form = document.createElement('form');
      var isSupported = false;

      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
        isSupported = true;
      }

      div = form = null;

      return isSupported;
    })()
  },

  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

  emptyFunction: function() { },
  K: function(x) { return x }
};

if (Prototype.Browser.MobileSafari)
  Prototype.BrowserFeatures.SpecificElementExtensions = false;


var Abstract = { };


var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) { }
    }

    return returnValue;
  }
};

/* Based on Alex Arnell's inheritance implementation. */

var Class = (function() {
  function subclass() {};
  function create() {
    var parent = null, properties = $A(arguments);
    if (Object.isFunction(properties[0]))
      parent = properties.shift();

    function klass() {
      this.initialize.apply(this, arguments);
    }

    Object.extend(klass, Class.Methods);
    klass.superclass = parent;
    klass.subclasses = [];

    if (parent) {
      subclass.prototype = parent.prototype;
      klass.prototype = new subclass;
      parent.subclasses.push(klass);
    }

    for (var i = 0; i < properties.length; i++)
      klass.addMethods(properties[i]);

    if (!klass.prototype.initialize)
      klass.prototype.initialize = Prototype.emptyFunction;

    klass.prototype.constructor = klass;
    return klass;
  }

  function addMethods(source) {
    var ancestor   = this.superclass && this.superclass.prototype;
    var properties = Object.keys(source);

    if (!Object.keys({ toString: true }).length) {
      if (source.toString != Object.prototype.toString)
        properties.push("toString");
      if (source.valueOf != Object.prototype.valueOf)
        properties.push("valueOf");
    }

    for (var i = 0, length = properties.length; i < length; i++) {
      var property = properties[i], value = source[property];
      if (ancestor && Object.isFunction(value) &&
          value.argumentNames().first() == "$super") {
        var method = value;
        value = (function(m) {
          return function() { return ancestor[m].apply(this, arguments); };
        })(property).wrap(method);

        value.valueOf = method.valueOf.bind(method);
        value.toString = method.toString.bind(method);
      }
      this.prototype[property] = value;
    }

    return this;
  }

  return {
    create: create,
    Methods: {
      addMethods: addMethods
    }
  };
})();
(function() {

  var _toString = Object.prototype.toString;

  function extend(destination, source) {
    for (var property in source)
      destination[property] = source[property];
    return destination;
  }

  function inspect(object) {
    try {
      if (isUndefined(object)) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : String(object);
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  }

  function toJSON(object) {
    var type = typeof object;
    switch (type) {
      case 'undefined':
      case 'function':
      case 'unknown': return;
      case 'boolean': return object.toString();
    }

    if (object === null) return 'null';
    if (object.toJSON) return object.toJSON();
    if (isElement(object)) return;

    var results = [];
    for (var property in object) {
      var value = toJSON(object[property]);
      if (!isUndefined(value))
        results.push(property.toJSON() + ': ' + value);
    }

    return '{' + results.join(', ') + '}';
  }

  function toQueryString(object) {
    return $H(object).toQueryString();
  }

  function toHTML(object) {
    return object && object.toHTML ? object.toHTML() : String.interpret(object);
  }

  function keys(object) {
    var results = [];
    for (var property in object)
      results.push(property);
    return results;
  }

  function values(object) {
    var results = [];
    for (var property in object)
      results.push(object[property]);
    return results;
  }

  function clone(object) {
    return extend({ }, object);
  }

  function isElement(object) {
    return !!(object && object.nodeType == 1);
  }

  function isArray(object) {
    return _toString.call(object) == "[object Array]";
  }


  function isHash(object) {
    return object instanceof Hash;
  }

  function isFunction(object) {
    return typeof object === "function";
  }

  function isString(object) {
    return _toString.call(object) == "[object String]";
  }

  function isNumber(object) {
    return _toString.call(object) == "[object Number]";
  }

  function isUndefined(object) {
    return typeof object === "undefined";
  }

  extend(Object, {
    extend:        extend,
    inspect:       inspect,
    toJSON:        toJSON,
    toQueryString: toQueryString,
    toHTML:        toHTML,
    keys:          keys,
    values:        values,
    clone:         clone,
    isElement:     isElement,
    isArray:       isArray,
    isHash:        isHash,
    isFunction:    isFunction,
    isString:      isString,
    isNumber:      isNumber,
    isUndefined:   isUndefined
  });
})();
Object.extend(Function.prototype, (function() {
  var slice = Array.prototype.slice;

  function update(array, args) {
    var arrayLength = array.length, length = args.length;
    while (length--) array[arrayLength + length] = args[length];
    return array;
  }

  function merge(array, args) {
    array = slice.call(array, 0);
    return update(array, args);
  }

  function argumentNames() {
    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
      .replace(/\s+/g, '').split(',');
    return names.length == 1 && !names[0] ? [] : names;
  }

  function bind(context) {
    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
    var __method = this, args = slice.call(arguments, 1);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(context, a);
    }
  }

  function bindAsEventListener(context) {
    var __method = this, args = slice.call(arguments, 1);
    return function(event) {
      var a = update([event || window.event], args);
      return __method.apply(context, a);
    }
  }

  function curry() {
    if (!arguments.length) return this;
    var __method = this, args = slice.call(arguments, 0);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(this, a);
    }
  }

  function delay(timeout) {
    var __method = this, args = slice.call(arguments, 1);
    timeout = timeout * 1000
    return window.setTimeout(function() {
      return __method.apply(__method, args);
    }, timeout);
  }

  function defer() {
    var args = update([0.01], arguments);
    return this.delay.apply(this, args);
  }

  function wrap(wrapper) {
    var __method = this;
    return function() {
      var a = update([__method.bind(this)], arguments);
      return wrapper.apply(this, a);
    }
  }

  function methodize() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      var a = update([this], arguments);
      return __method.apply(null, a);
    };
  }

  return {
    argumentNames:       argumentNames,
    bind:                bind,
    bindAsEventListener: bindAsEventListener,
    curry:               curry,
    delay:               delay,
    defer:               defer,
    wrap:                wrap,
    methodize:           methodize
  }
})());


Date.prototype.toJSON = function() {
  return '"' + this.getUTCFullYear() + '-' +
    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
    this.getUTCDate().toPaddedString(2) + 'T' +
    this.getUTCHours().toPaddedString(2) + ':' +
    this.getUTCMinutes().toPaddedString(2) + ':' +
    this.getUTCSeconds().toPaddedString(2) + 'Z"';
};


RegExp.prototype.match = RegExp.prototype.test;

RegExp.escape = function(str) {
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  execute: function() {
    this.callback(this);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.execute();
        this.currentlyExecuting = false;
      } catch(e) {
        this.currentlyExecuting = false;
        throw e;
      }
    }
  }
});
Object.extend(String, {
  interpret: function(value) {
    return value == null ? '' : String(value);
  },
  specialChar: {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '\\': '\\\\'
  }
});

Object.extend(String.prototype, (function() {

  function prepareReplacement(replacement) {
    if (Object.isFunction(replacement)) return replacement;
    var template = new Template(replacement);
    return function(match) { return template.evaluate(match) };
  }

  function gsub(pattern, replacement) {
    var result = '', source = this, match;
    replacement = prepareReplacement(replacement);

    if (Object.isString(pattern))
      pattern = RegExp.escape(pattern);

    if (!(pattern.length || pattern.source)) {
      replacement = replacement('');
      return replacement + source.split('').join(replacement) + replacement;
    }

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += String.interpret(replacement(match));
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  }

  function sub(pattern, replacement, count) {
    replacement = prepareReplacement(replacement);
    count = Object.isUndefined(count) ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  }

  function scan(pattern, iterator) {
    this.gsub(pattern, iterator);
    return String(this);
  }

  function truncate(length, truncation) {
    length = length || 30;
    truncation = Object.isUndefined(truncation) ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : String(this);
  }

  function strip() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  }

  function stripTags() {
    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
  }

  function stripScripts() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  }

  function extractScripts() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  }

  function evalScripts() {
    return this.extractScripts().map(function(script) { return eval(script) });
  }

  function escapeHTML() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  }

  function unescapeHTML() {
    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
  }


  function toQueryParams(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return { };

    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var key = decodeURIComponent(pair.shift());
        var value = pair.length > 1 ? pair.join('=') : pair[0];
        if (value != undefined) value = decodeURIComponent(value);

        if (key in hash) {
          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
          hash[key].push(value);
        }
        else hash[key] = value;
      }
      return hash;
    });
  }

  function toArray() {
    return this.split('');
  }

  function succ() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  }

  function times(count) {
    return count < 1 ? '' : new Array(count + 1).join(this);
  }

  function camelize() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  }

  function capitalize() {
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  }

  function underscore() {
    return this.replace(/::/g, '/')
               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
               .replace(/-/g, '_')
               .toLowerCase();
  }

  function dasherize() {
    return this.replace(/_/g, '-');
  }

  function inspect(useDoubleQuotes) {
    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
      if (character in String.specialChar) {
        return String.specialChar[character];
      }
      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
    });
    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }

  function toJSON() {
    return this.inspect(true);
  }

  function unfilterJSON(filter) {
    return this.replace(filter || Prototype.JSONFilter, '$1');
  }

  function isJSON() {
    var str = this;
    if (str.blank()) return false;
    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
  }

  function evalJSON(sanitize) {
    var json = this.unfilterJSON();
    try {
      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
    } catch (e) { }
    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
  }

  function include(pattern) {
    return this.indexOf(pattern) > -1;
  }

  function startsWith(pattern) {
    return this.indexOf(pattern) === 0;
  }

  function endsWith(pattern) {
    var d = this.length - pattern.length;
    return d >= 0 && this.lastIndexOf(pattern) === d;
  }

  function empty() {
    return this == '';
  }

  function blank() {
    return /^\s*$/.test(this);
  }

  function interpolate(object, pattern) {
    return new Template(this, pattern).evaluate(object);
  }

  return {
    gsub:           gsub,
    sub:            sub,
    scan:           scan,
    truncate:       truncate,
    strip:          String.prototype.trim ? String.prototype.trim : strip,
    stripTags:      stripTags,
    stripScripts:   stripScripts,
    extractScripts: extractScripts,
    evalScripts:    evalScripts,
    escapeHTML:     escapeHTML,
    unescapeHTML:   unescapeHTML,
    toQueryParams:  toQueryParams,
    parseQuery:     toQueryParams,
    toArray:        toArray,
    succ:           succ,
    times:          times,
    camelize:       camelize,
    capitalize:     capitalize,
    underscore:     underscore,
    dasherize:      dasherize,
    inspect:        inspect,
    toJSON:         toJSON,
    unfilterJSON:   unfilterJSON,
    isJSON:         isJSON,
    evalJSON:       evalJSON,
    include:        include,
    startsWith:     startsWith,
    endsWith:       endsWith,
    empty:          empty,
    blank:          blank,
    interpolate:    interpolate
  };
})());

var Template = Class.create({
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    if (object && Object.isFunction(object.toTemplateReplacements))
      object = object.toTemplateReplacements();

    return this.template.gsub(this.pattern, function(match) {
      if (object == null) return (match[1] + '');

      var before = match[1] || '';
      if (before == '\\') return match[2];

      var ctx = object, expr = match[3];
      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
      match = pattern.exec(expr);
      if (match == null) return before;

      while (match != null) {
        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
        ctx = ctx[comp];
        if (null == ctx || '' == match[3]) break;
        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
        match = pattern.exec(expr);
      }

      return before + String.interpret(ctx);
    });
  }
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

var $break = { };

var Enumerable = (function() {
  function each(iterator, context) {
    var index = 0;
    try {
      this._each(function(value) {
        iterator.call(context, value, index++);
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  }

  function eachSlice(number, iterator, context) {
    var index = -number, slices = [], array = this.toArray();
    if (number < 1) return array;
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.collect(iterator, context);
  }

  function all(iterator, context) {
    iterator = iterator || Prototype.K;
    var result = true;
    this.each(function(value, index) {
      result = result && !!iterator.call(context, value, index);
      if (!result) throw $break;
    });
    return result;
  }

  function any(iterator, context) {
    iterator = iterator || Prototype.K;
    var result = false;
    this.each(function(value, index) {
      if (result = !!iterator.call(context, value, index))
        throw $break;
    });
    return result;
  }

  function collect(iterator, context) {
    iterator = iterator || Prototype.K;
    var results = [];
    this.each(function(value, index) {
      results.push(iterator.call(context, value, index));
    });
    return results;
  }

  function detect(iterator, context) {
    var result;
    this.each(function(value, index) {
      if (iterator.call(context, value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  }

  function findAll(iterator, context) {
    var results = [];
    this.each(function(value, index) {
      if (iterator.call(context, value, index))
        results.push(value);
    });
    return results;
  }

  function grep(filter, iterator, context) {
    iterator = iterator || Prototype.K;
    var results = [];

    if (Object.isString(filter))
      filter = new RegExp(RegExp.escape(filter));

    this.each(function(value, index) {
      if (filter.match(value))
        results.push(iterator.call(context, value, index));
    });
    return results;
  }

  function include(object) {
    if (Object.isFunction(this.indexOf))
      if (this.indexOf(object) != -1) return true;

    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  }

  function inGroupsOf(number, fillWith) {
    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  }

  function inject(memo, iterator, context) {
    this.each(function(value, index) {
      memo = iterator.call(context, memo, value, index);
    });
    return memo;
  }

  function invoke(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  }

  function max(iterator, context) {
    iterator = iterator || Prototype.K;
    var result;
    this.each(function(value, index) {
      value = iterator.call(context, value, index);
      if (result == null || value >= result)
        result = value;
    });
    return result;
  }

  function min(iterator, context) {
    iterator = iterator || Prototype.K;
    var result;
    this.each(function(value, index) {
      value = iterator.call(context, value, index);
      if (result == null || value < result)
        result = value;
    });
    return result;
  }

  function partition(iterator, context) {
    iterator = iterator || Prototype.K;
    var trues = [], falses = [];
    this.each(function(value, index) {
      (iterator.call(context, value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  }

  function pluck(property) {
    var results = [];
    this.each(function(value) {
      results.push(value[property]);
    });
    return results;
  }

  function reject(iterator, context) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator.call(context, value, index))
        results.push(value);
    });
    return results;
  }

  function sortBy(iterator, context) {
    return this.map(function(value, index) {
      return {
        value: value,
        criteria: iterator.call(context, value, index)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  }

  function toArray() {
    return this.map();
  }

  function zip() {
    var iterator = Prototype.K, args = $A(arguments);
    if (Object.isFunction(args.last()))
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  }

  function size() {
    return this.toArray().length;
  }

  function inspect() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }









  return {
    each:       each,
    eachSlice:  eachSlice,
    all:        all,
    every:      all,
    any:        any,
    some:       any,
    collect:    collect,
    map:        collect,
    detect:     detect,
    findAll:    findAll,
    select:     findAll,
    filter:     findAll,
    grep:       grep,
    include:    include,
    member:     include,
    inGroupsOf: inGroupsOf,
    inject:     inject,
    invoke:     invoke,
    max:        max,
    min:        min,
    partition:  partition,
    pluck:      pluck,
    reject:     reject,
    sortBy:     sortBy,
    toArray:    toArray,
    entries:    toArray,
    zip:        zip,
    size:       size,
    inspect:    inspect,
    find:       detect
  };
})();
function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

function $w(string) {
  if (!Object.isString(string)) return [];
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

Array.from = $A;


(function() {
  var arrayProto = Array.prototype,
      slice = arrayProto.slice,
      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

  function each(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  }
  if (!_each) _each = each;

  function clear() {
    this.length = 0;
    return this;
  }

  function first() {
    return this[0];
  }

  function last() {
    return this[this.length - 1];
  }

  function compact() {
    return this.select(function(value) {
      return value != null;
    });
  }

  function flatten() {
    return this.inject([], function(array, value) {
      if (Object.isArray(value))
        return array.concat(value.flatten());
      array.push(value);
      return array;
    });
  }

  function without() {
    var values = slice.call(arguments, 0);
    return this.select(function(value) {
      return !values.include(value);
    });
  }

  function reverse(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  }

  function uniq(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  }

  function intersect(array) {
    return this.uniq().findAll(function(item) {
      return array.detect(function(value) { return item === value });
    });
  }


  function clone() {
    return slice.call(this, 0);
  }

  function size() {
    return this.length;
  }

  function inspect() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }

  function toJSON() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (!Object.isUndefined(value)) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }

  function indexOf(item, i) {
    i || (i = 0);
    var length = this.length;
    if (i < 0) i = length + i;
    for (; i < length; i++)
      if (this[i] === item) return i;
    return -1;
  }

  function lastIndexOf(item, i) {
    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
    var n = this.slice(0, i).reverse().indexOf(item);
    return (n < 0) ? n : i - n - 1;
  }

  function concat() {
    var array = slice.call(this, 0), item;
    for (var i = 0, length = arguments.length; i < length; i++) {
      item = arguments[i];
      if (Object.isArray(item) && !('callee' in item)) {
        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
          array.push(item[j]);
      } else {
        array.push(item);
      }
    }
    return array;
  }

  Object.extend(arrayProto, Enumerable);

  if (!arrayProto._reverse)
    arrayProto._reverse = arrayProto.reverse;

  Object.extend(arrayProto, {
    _each:     _each,
    clear:     clear,
    first:     first,
    last:      last,
    compact:   compact,
    flatten:   flatten,
    without:   without,
    reverse:   reverse,
    uniq:      uniq,
    intersect: intersect,
    clone:     clone,
    toArray:   clone,
    size:      size,
    inspect:   inspect,
    toJSON:    toJSON
  });

  var CONCAT_ARGUMENTS_BUGGY = (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2)

  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object) {
  return new Hash(object);
};

var Hash = Class.create(Enumerable, (function() {
  function initialize(object) {
    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
  }

  function _each(iterator) {
    for (var key in this._object) {
      var value = this._object[key], pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  }

  function set(key, value) {
    return this._object[key] = value;
  }

  function get(key) {
    if (this._object[key] !== Object.prototype[key])
      return this._object[key];
  }

  function unset(key) {
    var value = this._object[key];
    delete this._object[key];
    return value;
  }

  function toObject() {
    return Object.clone(this._object);
  }

  function keys() {
    return this.pluck('key');
  }

  function values() {
    return this.pluck('value');
  }

  function index(value) {
    var match = this.detect(function(pair) {
      return pair.value === value;
    });
    return match && match.key;
  }

  function merge(object) {
    return this.clone().update(object);
  }

  function update(object) {
    return new Hash(object).inject(this, function(result, pair) {
      result.set(pair.key, pair.value);
      return result;
    });
  }

  function toQueryPair(key, value) {
    if (Object.isUndefined(value)) return key;
    return key + '=' + encodeURIComponent(String.interpret(value));
  }

  function toQueryString() {
    return this.inject([], function(results, pair) {
      var key = encodeURIComponent(pair.key), values = pair.value;

      if (values && typeof values == 'object') {
        if (Object.isArray(values))
          return results.concat(values.map(toQueryPair.curry(key)));
      } else results.push(toQueryPair(key, values));
      return results;
    }).join('&');
  }

  function inspect() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }

  function toJSON() {
    return Object.toJSON(this.toObject());
  }

  function clone() {
    return new Hash(this);
  }

  return {
    initialize:             initialize,
    _each:                  _each,
    set:                    set,
    get:                    get,
    unset:                  unset,
    toObject:               toObject,
    toTemplateReplacements: toObject,
    keys:                   keys,
    values:                 values,
    index:                  index,
    merge:                  merge,
    update:                 update,
    toQueryString:          toQueryString,
    inspect:                inspect,
    toJSON:                 toJSON,
    clone:                  clone
  };
})());

Hash.from = $H;
Object.extend(Number.prototype, (function() {
  function toColorPart() {
    return this.toPaddedString(2, 16);
  }

  function succ() {
    return this + 1;
  }

  function times(iterator, context) {
    $R(0, this, true).each(iterator, context);
    return this;
  }

  function toPaddedString(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  }

  function toJSON() {
    return isFinite(this) ? this.toString() : 'null';
  }

  function abs() {
    return Math.abs(this);
  }

  function round() {
    return Math.round(this);
  }

  function ceil() {
    return Math.ceil(this);
  }

  function floor() {
    return Math.floor(this);
  }

  return {
    toColorPart:    toColorPart,
    succ:           succ,
    times:          times,
    toPaddedString: toPaddedString,
    toJSON:         toJSON,
    abs:            abs,
    round:          round,
    ceil:           ceil,
    floor:          floor
  };
})());

function $R(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var ObjectRange = Class.create(Enumerable, (function() {
  function initialize(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  }

  function _each(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  }

  function include(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }

  return {
    initialize: initialize,
    _each:      _each,
    include:    include
  };
})());



var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
};

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responder) {
    if (!this.include(responder))
      this.responders.push(responder);
  },

  unregister: function(responder) {
    this.responders = this.responders.without(responder);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (Object.isFunction(responder[callback])) {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) { }
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate:   function() { Ajax.activeRequestCount++ },
  onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
  initialize: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      encoding:     'UTF-8',
      parameters:   '',
      evalJSON:     true,
      evalJS:       true
    };
    Object.extend(this.options, options || { });

    this.options.method = this.options.method.toLowerCase();

    if (Object.isString(this.options.parameters))
      this.options.parameters = this.options.parameters.toQueryParams();
    else if (Object.isHash(this.options.parameters))
      this.options.parameters = this.options.parameters.toObject();
  }
});
Ajax.Request = Class.create(Ajax.Base, {
  _complete: false,

  initialize: function($super, url, options) {
    $super(options);
    this.transport = Ajax.getTransport();
    this.request(url);
  },

  request: function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = Object.clone(this.options.parameters);

    if (!['get', 'post'].include(this.method)) {
      params['_method'] = this.method;
      this.method = 'post';
    }

    this.parameters = params;

    if (params = Object.toQueryString(params)) {
      if (this.method == 'get')
        this.url += (this.url.include('?') ? '&' : '?') + params;
      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
        params += '&_=';
    }

    try {
      var response = new Ajax.Response(this);
      if (this.options.onCreate) this.options.onCreate(response);
      Ajax.Responders.dispatch('onCreate', this, response);

      this.transport.open(this.method.toUpperCase(), this.url,
        this.options.asynchronous);

      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
      this.transport.send(this.body);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    }
    catch (e) {
      this.dispatchException(e);
    }
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState > 1 && !((readyState == 4) && this._complete))
      this.respondToReadyState(this.transport.readyState);
  },

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if (this.method == 'post') {
      headers['Content-type'] = this.options.contentType +
        (this.options.encoding ? '; charset=' + this.options.encoding : '');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

      if (Object.isFunction(extras.push))
        for (var i = 0, length = extras.length; i < length; i += 2)
          headers[extras[i]] = extras[i+1];
      else
        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
    }

    for (var name in headers)
      this.transport.setRequestHeader(name, headers[name]);
  },

  success: function() {
    var status = this.getStatus();
    return !status || (status >= 200 && status < 300);
  },

  getStatus: function() {
    try {
      return this.transport.status || 0;
    } catch (e) { return 0 }
  },

  respondToReadyState: function(readyState) {
    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);

    if (state == 'Complete') {
      try {
        this._complete = true;
        (this.options['on' + response.status]
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(response, response.headerJSON);
      } catch (e) {
        this.dispatchException(e);
      }

      var contentType = response.getHeader('Content-type');
      if (this.options.evalJS == 'force'
          || (this.options.evalJS && this.isSameOrigin() && contentType
          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
        this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
    } catch (e) {
      this.dispatchException(e);
    }

    if (state == 'Complete') {
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

  isSameOrigin: function() {
    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
      protocol: location.protocol,
      domain: document.domain,
      port: location.port ? ':' + location.port : ''
    }));
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name) || null;
    } catch (e) { return null; }
  },

  evalResponse: function() {
    try {
      return eval((this.transport.responseText || '').unfilterJSON());
    } catch (e) {
      this.dispatchException(e);
    }
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];








Ajax.Response = Class.create({
  initialize: function(request){
    this.request = request;
    var transport  = this.transport  = request.transport,
        readyState = this.readyState = transport.readyState;

    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
      this.status       = this.getStatus();
      this.statusText   = this.getStatusText();
      this.responseText = String.interpret(transport.responseText);
      this.headerJSON   = this._getHeaderJSON();
    }

    if(readyState == 4) {
      var xml = transport.responseXML;
      this.responseXML  = Object.isUndefined(xml) ? null : xml;
      this.responseJSON = this._getResponseJSON();
    }
  },

  status:      0,

  statusText: '',

  getStatus: Ajax.Request.prototype.getStatus,

  getStatusText: function() {
    try {
      return this.transport.statusText || '';
    } catch (e) { return '' }
  },

  getHeader: Ajax.Request.prototype.getHeader,

  getAllHeaders: function() {
    try {
      return this.getAllResponseHeaders();
    } catch (e) { return null }
  },

  getResponseHeader: function(name) {
    return this.transport.getResponseHeader(name);
  },

  getAllResponseHeaders: function() {
    return this.transport.getAllResponseHeaders();
  },

  _getHeaderJSON: function() {
    var json = this.getHeader('X-JSON');
    if (!json) return null;
    json = decodeURIComponent(escape(json));
    try {
      return json.evalJSON(this.request.options.sanitizeJSON ||
        !this.request.isSameOrigin());
    } catch (e) {
      this.request.dispatchException(e);
    }
  },

  _getResponseJSON: function() {
    var options = this.request.options;
    if (!options.evalJSON || (options.evalJSON != 'force' &&
      !(this.getHeader('Content-type') || '').include('application/json')) ||
        this.responseText.blank())
          return null;
    try {
      return this.responseText.evalJSON(options.sanitizeJSON ||
        !this.request.isSameOrigin());
    } catch (e) {
      this.request.dispatchException(e);
    }
  }
});

Ajax.Updater = Class.create(Ajax.Request, {
  initialize: function($super, container, url, options) {
    this.container = {
      success: (container.success || container),
      failure: (container.failure || (container.success ? null : container))
    };

    options = Object.clone(options);
    var onComplete = options.onComplete;
    options.onComplete = (function(response, json) {
      this.updateContent(response.responseText);
      if (Object.isFunction(onComplete)) onComplete(response, json);
    }).bind(this);

    $super(url, options);
  },

  updateContent: function(responseText) {
    var receiver = this.container[this.success() ? 'success' : 'failure'],
        options = this.options;

    if (!options.evalScripts) responseText = responseText.stripScripts();

    if (receiver = $(receiver)) {
      if (options.insertion) {
        if (Object.isString(options.insertion)) {
          var insertion = { }; insertion[options.insertion] = responseText;
          receiver.insert(insertion);
        }
        else options.insertion(receiver, responseText);
      }
      else receiver.update(responseText);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
  initialize: function($super, container, url, options) {
    $super(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = { };
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(response) {
    if (this.options.decay) {
      this.decay = (response.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = response.responseText;
    }
    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});



function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element))
    element = document.getElementById(element);
  return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(Element.extend(query.snapshotItem(i)));
    return results;
  };
}

/*--------------------------------------------------------------------------*/

if (!window.Node) var Node = { };

if (!Node.ELEMENT_NODE) {
  Object.extend(Node, {
    ELEMENT_NODE: 1,
    ATTRIBUTE_NODE: 2,
    TEXT_NODE: 3,
    CDATA_SECTION_NODE: 4,
    ENTITY_REFERENCE_NODE: 5,
    ENTITY_NODE: 6,
    PROCESSING_INSTRUCTION_NODE: 7,
    COMMENT_NODE: 8,
    DOCUMENT_NODE: 9,
    DOCUMENT_TYPE_NODE: 10,
    DOCUMENT_FRAGMENT_NODE: 11,
    NOTATION_NODE: 12
  });
}


(function(global) {

  var SETATTRIBUTE_IGNORES_NAME = (function(){
    var elForm = document.createElement("form");
    var elInput = document.createElement("input");
    var root = document.documentElement;
    elInput.setAttribute("name", "test");
    elForm.appendChild(elInput);
    root.appendChild(elForm);
    var isBuggy = elForm.elements
      ? (typeof elForm.elements.test == "undefined")
      : null;
    root.removeChild(elForm);
    elForm = elInput = null;
    return isBuggy;
  })();

  var element = global.Element;
  global.Element = function(tagName, attributes) {
    attributes = attributes || { };
    tagName = tagName.toLowerCase();
    var cache = Element.cache;
    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
      tagName = '<' + tagName + ' name="' + attributes.name + '">';
      delete attributes.name;
      return Element.writeAttribute(document.createElement(tagName), attributes);
    }
    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
  };
  Object.extend(global.Element, element || { });
  if (element) global.Element.prototype = element.prototype;
})(this);

Element.cache = { };
Element.idCounter = 1;

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },


  hide: function(element) {
    element = $(element);
    element.style.display = 'none';
    return element;
  },

  show: function(element) {
    element = $(element);
    element.style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: (function(){

    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
      var el = document.createElement("select"),
          isBuggy = true;
      el.innerHTML = "<option value=\"test\">test</option>";
      if (el.options && el.options[0]) {
        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
      }
      el = null;
      return isBuggy;
    })();

    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
      try {
        var el = document.createElement("table");
        if (el && el.tBodies) {
          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
          var isBuggy = typeof el.tBodies[0] == "undefined";
          el = null;
          return isBuggy;
        }
      } catch (e) {
        return true;
      }
    })();

    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
      var s = document.createElement("script"),
          isBuggy = false;
      try {
        s.appendChild(document.createTextNode(""));
        isBuggy = !s.firstChild ||
          s.firstChild && s.firstChild.nodeType !== 3;
      } catch (e) {
        isBuggy = true;
      }
      s = null;
      return isBuggy;
    })();

    function update(element, content) {
      element = $(element);

      if (content && content.toElement)
        content = content.toElement();

      if (Object.isElement(content))
        return element.update().insert(content);

      content = Object.toHTML(content);

      var tagName = element.tagName.toUpperCase();

      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
        element.text = content;
        return element;
      }

      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
        if (tagName in Element._insertionTranslations.tags) {
          while (element.firstChild) {
            element.removeChild(element.firstChild);
          }
          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
            .each(function(node) {
              element.appendChild(node)
            });
        }
        else {
          element.innerHTML = content.stripScripts();
        }
      }
      else {
        element.innerHTML = content.stripScripts();
      }

      content.evalScripts.bind(content).defer();
      return element;
    }

    return update;
  })(),

  replace: function(element, content) {
    element = $(element);
    if (content && content.toElement) content = content.toElement();
    else if (!Object.isElement(content)) {
      content = Object.toHTML(content);
      var range = element.ownerDocument.createRange();
      range.selectNode(element);
      content.evalScripts.bind(content).defer();
      content = range.createContextualFragment(content.stripScripts());
    }
    element.parentNode.replaceChild(content, element);
    return element;
  },

  insert: function(element, insertions) {
    element = $(element);

    if (Object.isString(insertions) || Object.isNumber(insertions) ||
        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
          insertions = {bottom:insertions};

    var content, insert, tagName, childNodes;

    for (var position in insertions) {
      content  = insertions[position];
      position = position.toLowerCase();
      insert = Element._insertionTranslations[position];

      if (content && content.toElement) content = content.toElement();
      if (Object.isElement(content)) {
        insert(element, content);
        continue;
      }

      content = Object.toHTML(content);

      tagName = ((position == 'before' || position == 'after')
        ? element.parentNode : element).tagName.toUpperCase();

      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());

      if (position == 'top' || position == 'after') childNodes.reverse();
      childNodes.each(insert.curry(element));

      content.evalScripts.bind(content).defer();
    }

    return element;
  },

  wrap: function(element, wrapper, attributes) {
    element = $(element);
    if (Object.isElement(wrapper))
      $(wrapper).writeAttribute(attributes || { });
    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
    else wrapper = new Element('div', wrapper);
    if (element.parentNode)
      element.parentNode.replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return wrapper;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return Element.recursivelyCollect(element, 'parentNode');
  },

  descendants: function(element) {
    return Element.select(element, "*");
  },

  firstDescendant: function(element) {
    element = $(element).firstChild;
    while (element && element.nodeType != 1) element = element.nextSibling;
    return $(element);
  },

  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  previousSiblings: function(element) {
    return Element.recursivelyCollect(element, 'previousSibling');
  },

  nextSiblings: function(element) {
    return Element.recursivelyCollect(element, 'nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return Element.previousSiblings(element).reverse()
      .concat(Element.nextSiblings(element));
  },

  match: function(element, selector) {
    if (Object.isString(selector))
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(element.parentNode);
    var ancestors = Element.ancestors(element);
    return Object.isNumber(expression) ? ancestors[expression] :
      Selector.findElement(ancestors, expression, index);
  },

  down: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return Element.firstDescendant(element);
    return Object.isNumber(expression) ? Element.descendants(element)[expression] :
      Element.select(element, expression)[index || 0];
  },

  previous: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
    var previousSiblings = Element.previousSiblings(element);
    return Object.isNumber(expression) ? previousSiblings[expression] :
      Selector.findElement(previousSiblings, expression, index);
  },

  next: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
    var nextSiblings = Element.nextSiblings(element);
    return Object.isNumber(expression) ? nextSiblings[expression] :
      Selector.findElement(nextSiblings, expression, index);
  },


  select: function(element) {
    var args = Array.prototype.slice.call(arguments, 1);
    return Selector.findChildElements(element, args);
  },

  adjacent: function(element) {
    var args = Array.prototype.slice.call(arguments, 1);
    return Selector.findChildElements(element.parentNode, args).without(element);
  },

  identify: function(element) {
    element = $(element);
    var id = Element.readAttribute(element, 'id');
    if (id) return id;
    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
    Element.writeAttribute(element, 'id', id);
    return id;
  },

  readAttribute: function(element, name) {
    element = $(element);
    if (Prototype.Browser.IE) {
      var t = Element._attributeTranslations.read;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name]) name = t.names[name];
      if (name.include(':')) {
        return (!element.attributes || !element.attributes[name]) ? null :
         element.attributes[name].value;
      }
    }
    return element.getAttribute(name);
  },

  writeAttribute: function(element, name, value) {
    element = $(element);
    var attributes = { }, t = Element._attributeTranslations.write;

    if (typeof name == 'object') attributes = name;
    else attributes[name] = Object.isUndefined(value) ? true : value;

    for (var attr in attributes) {
      name = t.names[attr] || attr;
      value = attributes[attr];
      if (t.values[attr]) name = t.values[attr](element, value);
      if (value === false || value === null)
        element.removeAttribute(name);
      else if (value === true)
        element.setAttribute(name, name);
      else element.setAttribute(name, value);
    }
    return element;
  },

  getHeight: function(element) {
    return Element.getDimensions(element).height;
  },

  getWidth: function(element) {
    return Element.getDimensions(element).width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    return (elementClassName.length > 0 && (elementClassName == className ||
      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    if (!Element.hasClassName(element, className))
      element.className += (element.className ? ' ' : '') + className;
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    element.className = element.className.replace(
      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element[Element.hasClassName(element, className) ?
      'removeClassName' : 'addClassName'](element, className);
  },

  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.blank();
  },

  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);

    if (element.compareDocumentPosition)
      return (element.compareDocumentPosition(ancestor) & 8) === 8;

    if (ancestor.contains)
      return ancestor.contains(element) && ancestor !== element;

    while (element = element.parentNode)
      if (element == ancestor) return true;

    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var pos = Element.cumulativeOffset(element);
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    style = style == 'float' ? 'cssFloat' : style.camelize();
    var value = element.style[style];
    if (!value || value == 'auto') {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    }
    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
    return value == 'auto' ? null : value;
  },

  getOpacity: function(element) {
    return $(element).getStyle('opacity');
  },

  setStyle: function(element, styles) {
    element = $(element);
    var elementStyle = element.style, match;
    if (Object.isString(styles)) {
      element.style.cssText += ';' + styles;
      return styles.include('opacity') ?
        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
    }
    for (var property in styles)
      if (property == 'opacity') element.setOpacity(styles[property]);
      else
        elementStyle[(property == 'float' || property == 'cssFloat') ?
          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
            property] = styles[property];

    return element;
  },

  setOpacity: function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    var display = Element.getStyle(element, 'display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
      els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      if (Prototype.Browser.Opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
    if (element._overflow !== 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (element.tagName.toUpperCase() == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p !== 'static') break;
      }
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  absolutize: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'position') == 'absolute') return element;

    var offsets = Element.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.width  = width + 'px';
    element.style.height = height + 'px';
    return element;
  },

  relativize: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'position') == 'relative') return element;

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
    return element;
  },

  cumulativeScrollOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  getOffsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return $(element);

    return $(document.body);
  },

  viewportOffset: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') == 'absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return Element._returnOffset(valueL, valueT);
  },

  clonePosition: function(element, source) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || { });

    source = $(source);
    var p = Element.viewportOffset(source);

    element = $(element);
    var delta = [0, 0];
    var parent = null;
    if (Element.getStyle(element, 'position') == 'absolute') {
      parent = Element.getOffsetParent(element);
      delta = Element.viewportOffset(parent);
    }

    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
    return element;
  }
};

Object.extend(Element.Methods, {
  getElementsBySelector: Element.Methods.select,

  childElements: Element.Methods.immediateDescendants
});

Element._attributeTranslations = {
  write: {
    names: {
      className: 'class',
      htmlFor:   'for'
    },
    values: { }
  }
};

if (Prototype.Browser.Opera) {
  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
    function(proceed, element, style) {
      switch (style) {
        case 'left': case 'top': case 'right': case 'bottom':
          if (proceed(element, 'position') === 'static') return null;
        case 'height': case 'width':
          if (!Element.visible(element)) return null;

          var dim = parseInt(proceed(element, style), 10);

          if (dim !== element['offset' + style.capitalize()])
            return dim + 'px';

          var properties;
          if (style === 'height') {
            properties = ['border-top-width', 'padding-top',
             'padding-bottom', 'border-bottom-width'];
          }
          else {
            properties = ['border-left-width', 'padding-left',
             'padding-right', 'border-right-width'];
          }
          return properties.inject(dim, function(memo, property) {
            var val = proceed(element, property);
            return val === null ? memo : memo - parseInt(val, 10);
          }) + 'px';
        default: return proceed(element, style);
      }
    }
  );

  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
    function(proceed, element, attribute) {
      if (attribute === 'title') return element.title;
      return proceed(element, attribute);
    }
  );
}

else if (Prototype.Browser.IE) {
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    function(proceed, element) {
      element = $(element);
      try { element.offsetParent }
      catch(e) { return $(document.body) }
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);
      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    }
  );

  $w('positionedOffset viewportOffset').each(function(method) {
    Element.Methods[method] = Element.Methods[method].wrap(
      function(proceed, element) {
        element = $(element);
        try { element.offsetParent }
        catch(e) { return Element._returnOffset(0,0) }
        var position = element.getStyle('position');
        if (position !== 'static') return proceed(element);
        var offsetParent = element.getOffsetParent();
        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
          offsetParent.setStyle({ zoom: 1 });
        element.setStyle({ position: 'relative' });
        var value = proceed(element);
        element.setStyle({ position: position });
        return value;
      }
    );
  });

  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
    function(proceed, element) {
      try { element.offsetParent }
      catch(e) { return Element._returnOffset(0,0) }
      return proceed(element);
    }
  );

  Element.Methods.getStyle = function(element, style) {
    element = $(element);
    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
    var value = element.style[style];
    if (!value && element.currentStyle) value = element.currentStyle[style];

    if (style == 'opacity') {
      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if (value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }

    if (value == 'auto') {
      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
        return element['offset' + style.capitalize()] + 'px';
      return null;
    }
    return value;
  };

  Element.Methods.setOpacity = function(element, value) {
    function stripAlpha(filter){
      return filter.replace(/alpha\([^\)]*\)/gi,'');
    }
    element = $(element);
    var currentStyle = element.currentStyle;
    if ((currentStyle && !currentStyle.hasLayout) ||
      (!currentStyle && element.style.zoom == 'normal'))
        element.style.zoom = 1;

    var filter = element.getStyle('filter'), style = element.style;
    if (value == 1 || value === '') {
      (filter = stripAlpha(filter)) ?
        style.filter = filter : style.removeAttribute('filter');
      return element;
    } else if (value < 0.00001) value = 0;
    style.filter = stripAlpha(filter) +
      'alpha(opacity=' + (value * 100) + ')';
    return element;
  };

  Element._attributeTranslations = (function(){

    var classProp = 'className';
    var forProp = 'for';

    var el = document.createElement('div');

    el.setAttribute(classProp, 'x');

    if (el.className !== 'x') {
      el.setAttribute('class', 'x');
      if (el.className === 'x') {
        classProp = 'class';
      }
    }
    el = null;

    el = document.createElement('label');
    el.setAttribute(forProp, 'x');
    if (el.htmlFor !== 'x') {
      el.setAttribute('htmlFor', 'x');
      if (el.htmlFor === 'x') {
        forProp = 'htmlFor';
      }
    }
    el = null;

    return {
      read: {
        names: {
          'class':      classProp,
          'className':  classProp,
          'for':        forProp,
          'htmlFor':    forProp
        },
        values: {
          _getAttr: function(element, attribute) {
            return element.getAttribute(attribute);
          },
          _getAttr2: function(element, attribute) {
            return element.getAttribute(attribute, 2);
          },
          _getAttrNode: function(element, attribute) {
            var node = element.getAttributeNode(attribute);
            return node ? node.value : "";
          },
          _getEv: (function(){

            var el = document.createElement('div');
            el.onclick = Prototype.emptyFunction;
            var value = el.getAttribute('onclick');
            var f;

            if (String(value).indexOf('{') > -1) {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                attribute = attribute.toString();
                attribute = attribute.split('{')[1];
                attribute = attribute.split('}')[0];
                return attribute.strip();
              };
            }
            else if (value === '') {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                return attribute.strip();
              };
            }
            el = null;
            return f;
          })(),
          _flag: function(element, attribute) {
            return $(element).hasAttribute(attribute) ? attribute : null;
          },
          style: function(element) {
            return element.style.cssText.toLowerCase();
          },
          title: function(element) {
            return element.title;
          }
        }
      }
    }
  })();

  Element._attributeTranslations.write = {
    names: Object.extend({
      cellpadding: 'cellPadding',
      cellspacing: 'cellSpacing'
    }, Element._attributeTranslations.read.names),
    values: {
      checked: function(element, value) {
        element.checked = !!value;
      },

      style: function(element, value) {
        element.style.cssText = value ? value : '';
      }
    }
  };

  Element._attributeTranslations.has = {};

  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
  });

  (function(v) {
    Object.extend(v, {
      href:        v._getAttr2,
      src:         v._getAttr2,
      type:        v._getAttr,
      action:      v._getAttrNode,
      disabled:    v._flag,
      checked:     v._flag,
      readonly:    v._flag,
      multiple:    v._flag,
      onload:      v._getEv,
      onunload:    v._getEv,
      onclick:     v._getEv,
      ondblclick:  v._getEv,
      onmousedown: v._getEv,
      onmouseup:   v._getEv,
      onmouseover: v._getEv,
      onmousemove: v._getEv,
      onmouseout:  v._getEv,
      onfocus:     v._getEv,
      onblur:      v._getEv,
      onkeypress:  v._getEv,
      onkeydown:   v._getEv,
      onkeyup:     v._getEv,
      onsubmit:    v._getEv,
      onreset:     v._getEv,
      onselect:    v._getEv,
      onchange:    v._getEv
    });
  })(Element._attributeTranslations.read.values);

  if (Prototype.BrowserFeatures.ElementExtensions) {
    (function() {
      function _descendants(element) {
        var nodes = element.getElementsByTagName('*'), results = [];
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName !== "!") // Filter out comment nodes.
            results.push(node);
        return results;
      }

      Element.Methods.down = function(element, expression, index) {
        element = $(element);
        if (arguments.length == 1) return element.firstDescendant();
        return Object.isNumber(expression) ? _descendants(element)[expression] :
          Element.select(element, expression)[index || 0];
      }
    })();
  }

}

else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1) ? 0.999999 :
      (value === '') ? '' : (value < 0.00001) ? 0 : value;
    return element;
  };
}

else if (Prototype.Browser.WebKit) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;

    if (value == 1)
      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
        element.width++; element.width--;
      } else try {
        var n = document.createTextNode(' ');
        element.appendChild(n);
        element.removeChild(n);
      } catch (e) { }

    return element;
  };

  Element.Methods.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return Element._returnOffset(valueL, valueT);
  };
}

if ('outerHTML' in document.documentElement) {
  Element.Methods.replace = function(element, content) {
    element = $(element);

    if (content && content.toElement) content = content.toElement();
    if (Object.isElement(content)) {
      element.parentNode.replaceChild(content, element);
      return element;
    }

    content = Object.toHTML(content);
    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();

    if (Element._insertionTranslations.tags[tagName]) {
      var nextSibling = element.next();
      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
      parent.removeChild(element);
      if (nextSibling)
        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
      else
        fragments.each(function(node) { parent.appendChild(node) });
    }
    else element.outerHTML = content.stripScripts();

    content.evalScripts.bind(content).defer();
    return element;
  };
}

Element._returnOffset = function(l, t) {
  var result = [l, t];
  result.left = l;
  result.top = t;
  return result;
};

Element._getContentFromAnonymousElement = function(tagName, html) {
  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
  if (t) {
    div.innerHTML = t[0] + html + t[1];
    t[2].times(function() { div = div.firstChild });
  } else div.innerHTML = html;
  return $A(div.childNodes);
};

Element._insertionTranslations = {
  before: function(element, node) {
    element.parentNode.insertBefore(node, element);
  },
  top: function(element, node) {
    element.insertBefore(node, element.firstChild);
  },
  bottom: function(element, node) {
    element.appendChild(node);
  },
  after: function(element, node) {
    element.parentNode.insertBefore(node, element.nextSibling);
  },
  tags: {
    TABLE:  ['<table>',                '</table>',                   1],
    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
    SELECT: ['<select>',               '</select>',                  1]
  }
};

(function() {
  var tags = Element._insertionTranslations.tags;
  Object.extend(tags, {
    THEAD: tags.TBODY,
    TFOOT: tags.TBODY,
    TH:    tags.TD
  });
})();

Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    attribute = Element._attributeTranslations.has[attribute] || attribute;
    var node = $(element).getAttributeNode(attribute);
    return !!(node && node.specified);
  }
};

Element.Methods.ByTag = { };

Object.extend(Element, Element.Methods);

(function(div) {

  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
    window.HTMLElement = { };
    window.HTMLElement.prototype = div['__proto__'];
    Prototype.BrowserFeatures.ElementExtensions = true;
  }

  div = null;

})(document.createElement('div'))

Element.extend = (function() {

  function checkDeficiency(tagName) {
    if (typeof window.Element != 'undefined') {
      var proto = window.Element.prototype;
      if (proto) {
        var id = '_' + (Math.random()+'').slice(2);
        var el = document.createElement(tagName);
        proto[id] = 'x';
        var isBuggy = (el[id] !== 'x');
        delete proto[id];
        el = null;
        return isBuggy;
      }
    }
    return false;
  }

  function extendElementWith(element, methods) {
    for (var property in methods) {
      var value = methods[property];
      if (Object.isFunction(value) && !(property in element))
        element[property] = value.methodize();
    }
  }

  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');

  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
      return function(element) {
        if (element && typeof element._extendedByPrototype == 'undefined') {
          var t = element.tagName;
          if (t && (/^(?:object|applet|embed)$/i.test(t))) {
            extendElementWith(element, Element.Methods);
            extendElementWith(element, Element.Methods.Simulated);
            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
          }
        }
        return element;
      }
    }
    return Prototype.K;
  }

  var Methods = { }, ByTag = Element.Methods.ByTag;

  var extend = Object.extend(function(element) {
    if (!element || typeof element._extendedByPrototype != 'undefined' ||
        element.nodeType != 1 || element == window) return element;

    var methods = Object.clone(Methods),
        tagName = element.tagName.toUpperCase();

    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

    extendElementWith(element, methods);

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

  }, {
    refresh: function() {
      if (!Prototype.BrowserFeatures.ElementExtensions) {
        Object.extend(Methods, Element.Methods);
        Object.extend(Methods, Element.Methods.Simulated);
      }
    }
  });

  extend.refresh();
  return extend;
})();

Element.hasAttribute = function(element, attribute) {
  if (element.hasAttribute) return element.hasAttribute(attribute);
  return Element.Methods.Simulated.hasAttribute(element, attribute);
};

Element.addMethods = function(methods) {
  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

  if (!methods) {
    Object.extend(Form, Form.Methods);
    Object.extend(Form.Element, Form.Element.Methods);
    Object.extend(Element.Methods.ByTag, {
      "FORM":     Object.clone(Form.Methods),
      "INPUT":    Object.clone(Form.Element.Methods),
      "SELECT":   Object.clone(Form.Element.Methods),
      "TEXTAREA": Object.clone(Form.Element.Methods)
    });
  }

  if (arguments.length == 2) {
    var tagName = methods;
    methods = arguments[1];
  }

  if (!tagName) Object.extend(Element.Methods, methods || { });
  else {
    if (Object.isArray(tagName)) tagName.each(extend);
    else extend(tagName);
  }

  function extend(tagName) {
    tagName = tagName.toUpperCase();
    if (!Element.Methods.ByTag[tagName])
      Element.Methods.ByTag[tagName] = { };
    Object.extend(Element.Methods.ByTag[tagName], methods);
  }

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    for (var property in methods) {
      var value = methods[property];
      if (!Object.isFunction(value)) continue;
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = value.methodize();
    }
  }

  function findDOMClass(tagName) {
    var klass;
    var trans = {
      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
      "FrameSet", "IFRAME": "IFrame"
    };
    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName.capitalize() + 'Element';
    if (window[klass]) return window[klass];

    var element = document.createElement(tagName);
    var proto = element['__proto__'] || element.constructor.prototype;
    element = null;
    return proto;
  }

  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
   Element.prototype;

  if (F.ElementExtensions) {
    copy(Element.Methods, elementPrototype);
    copy(Element.Methods.Simulated, elementPrototype, true);
  }

  if (F.SpecificElementExtensions) {
    for (var tag in Element.Methods.ByTag) {
      var klass = findDOMClass(tag);
      if (Object.isUndefined(klass)) continue;
      copy(T[tag], klass.prototype);
    }
  }

  Object.extend(Element, Element.Methods);
  delete Element.ByTag;

  if (Element.extend.refresh) Element.extend.refresh();
  Element.cache = { };
};


document.viewport = {

  getDimensions: function() {
    return { width: this.getWidth(), height: this.getHeight() };
  },

  getScrollOffsets: function() {
    return Element._returnOffset(
      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
  }
};

(function(viewport) {
  var B = Prototype.Browser, doc = document, element, property = {};

  function getRootElement() {
    if (B.WebKit && !doc.evaluate)
      return document;

    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
      return document.body;

    return document.documentElement;
  }

  function define(D) {
    if (!element) element = getRootElement();

    property[D] = 'client' + D;

    viewport['get' + D] = function() { return element[property[D]] };
    return viewport['get' + D]();
  }

  viewport.getWidth  = define.curry('Width');

  viewport.getHeight = define.curry('Height');
})(document.viewport);


Element.Storage = {
  UID: 1
};

Element.addMethods({
  getStorage: function(element) {
    if (!(element = $(element))) return;

    var uid;
    if (element === window) {
      uid = 0;
    } else {
      if (typeof element._prototypeUID === "undefined")
        element._prototypeUID = [Element.Storage.UID++];
      uid = element._prototypeUID[0];
    }

    if (!Element.Storage[uid])
      Element.Storage[uid] = $H();

    return Element.Storage[uid];
  },

  store: function(element, key, value) {
    if (!(element = $(element))) return;

    if (arguments.length === 2) {
      Element.getStorage(element).update(key);
    } else {
      Element.getStorage(element).set(key, value);
    }

    return element;
  },

  retrieve: function(element, key, defaultValue) {
    if (!(element = $(element))) return;
    var hash = Element.getStorage(element), value = hash.get(key);

    if (Object.isUndefined(value)) {
      hash.set(key, defaultValue);
      value = defaultValue;
    }

    return value;
  },

  clone: function(element, deep) {
    if (!(element = $(element))) return;
    var clone = element.cloneNode(deep);
    clone._prototypeUID = void 0;
    if (deep) {
      var descendants = Element.select(clone, '*'),
          i = descendants.length;
      while (i--) {
        descendants[i]._prototypeUID = void 0;
      }
    }
    return Element.extend(clone);
  }
});
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license.  Please see http://www.yui-ext.com/ for more information. */

var Selector = Class.create({
  initialize: function(expression) {
    this.expression = expression.strip();

    if (this.shouldUseSelectorsAPI()) {
      this.mode = 'selectorsAPI';
    } else if (this.shouldUseXPath()) {
      this.mode = 'xpath';
      this.compileXPathMatcher();
    } else {
      this.mode = "normal";
      this.compileMatcher();
    }

  },

  shouldUseXPath: (function() {

    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
      var isBuggy = false;
      if (document.evaluate && window.XPathResult) {
        var el = document.createElement('div');
        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';

        var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
          "//*[local-name()='li' or local-name()='LI']";

        var result = document.evaluate(xpath, el, null,
          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

        isBuggy = (result.snapshotLength !== 2);
        el = null;
      }
      return isBuggy;
    })();

    return function() {
      if (!Prototype.BrowserFeatures.XPath) return false;

      var e = this.expression;

      if (Prototype.Browser.WebKit &&
       (e.include("-of-type") || e.include(":empty")))
        return false;

      if ((/(\[[\w-]*?:|:checked)/).test(e))
        return false;

      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;

      return true;
    }

  })(),

  shouldUseSelectorsAPI: function() {
    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;

    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;

    if (!Selector._div) Selector._div = new Element('div');

    try {
      Selector._div.querySelector(this.expression);
    } catch(e) {
      return false;
    }

    return true;
  },

  compileMatcher: function() {
    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
        c = Selector.criteria, le, p, m, len = ps.length, name;

    if (Selector._cache[e]) {
      this.matcher = Selector._cache[e];
      return;
    }

    this.matcher = ["this.matcher = function(root) {",
                    "var r = root, h = Selector.handlers, c = false, n;"];

    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        p = ps[i].re;
        name = ps[i].name;
        if (m = e.match(p)) {
          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
            new Template(c[name]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.matcher.push("return h.unique(n);\n}");
    eval(this.matcher.join('\n'));
    Selector._cache[this.expression] = this.matcher;
  },

  compileXPathMatcher: function() {
    var e = this.expression, ps = Selector.patterns,
        x = Selector.xpath, le, m, len = ps.length, name;

    if (Selector._cache[e]) {
      this.xpath = Selector._cache[e]; return;
    }

    this.matcher = ['.//*'];
    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        name = ps[i].name;
        if (m = e.match(ps[i].re)) {
          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
            new Template(x[name]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.xpath = this.matcher.join('');
    Selector._cache[this.expression] = this.xpath;
  },

  findElements: function(root) {
    root = root || document;
    var e = this.expression, results;

    switch (this.mode) {
      case 'selectorsAPI':
        if (root !== document) {
          var oldId = root.id, id = $(root).identify();
          id = id.replace(/([\.:])/g, "\\$1");
          e = "#" + id + " " + e;
        }

        results = $A(root.querySelectorAll(e)).map(Element.extend);
        root.id = oldId;

        return results;
      case 'xpath':
        return document._getElementsByXPath(this.xpath, root);
      default:
       return this.matcher(root);
    }
  },

  match: function(element) {
    this.tokens = [];

    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
    var le, p, m, len = ps.length, name;

    while (e && le !== e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        p = ps[i].re;
        name = ps[i].name;
        if (m = e.match(p)) {
          if (as[name]) {
            this.tokens.push([name, Object.clone(m)]);
            e = e.replace(m[0], '');
          } else {
            return this.findElements(document).include(element);
          }
        }
      }
    }

    var match = true, name, matches;
    for (var i = 0, token; token = this.tokens[i]; i++) {
      name = token[0], matches = token[1];
      if (!Selector.assertions[name](element, matches)) {
        match = false; break;
      }
    }

    return match;
  },

  toString: function() {
    return this.expression;
  },

  inspect: function() {
    return "#<Selector:" + this.expression.inspect() + ">";
  }
});

if (Prototype.BrowserFeatures.SelectorsAPI &&
 document.compatMode === 'BackCompat') {
  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
    var div = document.createElement('div'),
     span = document.createElement('span');

    div.id = "prototype_test_id";
    span.className = 'Test';
    div.appendChild(span);
    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
    div = span = null;
    return isIgnored;
  })();
}

Object.extend(Selector, {
  _cache: { },

  xpath: {
    descendant:   "//*",
    child:        "/*",
    adjacent:     "/following-sibling::*[1]",
    laterSibling: '/following-sibling::*',
    tagName:      function(m) {
      if (m[1] == '*') return '';
      return "[local-name()='" + m[1].toLowerCase() +
             "' or local-name()='" + m[1].toUpperCase() + "']";
    },
    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
    id:           "[@id='#{1}']",
    attrPresence: function(m) {
      m[1] = m[1].toLowerCase();
      return new Template("[@#{1}]").evaluate(m);
    },
    attr: function(m) {
      m[1] = m[1].toLowerCase();
      m[3] = m[5] || m[6];
      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
    },
    pseudo: function(m) {
      var h = Selector.xpath.pseudos[m[1]];
      if (!h) return '';
      if (Object.isFunction(h)) return h(m);
      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
    },
    operators: {
      '=':  "[@#{1}='#{3}']",
      '!=': "[@#{1}!='#{3}']",
      '^=': "[starts-with(@#{1}, '#{3}')]",
      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
      '*=': "[contains(@#{1}, '#{3}')]",
      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
    },
    pseudos: {
      'first-child': '[not(preceding-sibling::*)]',
      'last-child':  '[not(following-sibling::*)]',
      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
      'checked':     "[@checked]",
      'disabled':    "[(@disabled) and (@type!='hidden')]",
      'enabled':     "[not(@disabled) and (@type!='hidden')]",
      'not': function(m) {
        var e = m[6], p = Selector.patterns,
            x = Selector.xpath, le, v, len = p.length, name;

        var exclusion = [];
        while (e && le != e && (/\S/).test(e)) {
          le = e;
          for (var i = 0; i<len; i++) {
            name = p[i].name
            if (m = e.match(p[i].re)) {
              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
              e = e.replace(m[0], '');
              break;
            }
          }
        }
        return "[not(" + exclusion.join(" and ") + ")]";
      },
      'nth-child':      function(m) {
        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
      },
      'nth-last-child': function(m) {
        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
      },
      'nth-of-type':    function(m) {
        return Selector.xpath.pseudos.nth("position() ", m);
      },
      'nth-last-of-type': function(m) {
        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
      },
      'first-of-type':  function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
      },
      'last-of-type':   function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
      },
      'only-of-type':   function(m) {
        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
      },
      nth: function(fragment, m) {
        var mm, formula = m[6], predicate;
        if (formula == 'even') formula = '2n+0';
        if (formula == 'odd')  formula = '2n+1';
        if (mm = formula.match(/^(\d+)$/)) // digit only
          return '[' + fragment + "= " + mm[1] + ']';
        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
          if (mm[1] == "-") mm[1] = -1;
          var a = mm[1] ? Number(mm[1]) : 1;
          var b = mm[2] ? Number(mm[2]) : 0;
          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
          "((#{fragment} - #{b}) div #{a} >= 0)]";
          return new Template(predicate).evaluate({
            fragment: fragment, a: a, b: b });
        }
      }
    }
  },

  criteria: {
    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
    attr: function(m) {
      m[3] = (m[5] || m[6]);
      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
    },
    pseudo: function(m) {
      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
    },
    descendant:   'c = "descendant";',
    child:        'c = "child";',
    adjacent:     'c = "adjacent";',
    laterSibling: 'c = "laterSibling";'
  },

  patterns: [
    { name: 'laterSibling', re: /^\s*~\s*/ },
    { name: 'child',        re: /^\s*>\s*/ },
    { name: 'adjacent',     re: /^\s*\+\s*/ },
    { name: 'descendant',   re: /^\s/ },

    { name: 'tagName',      re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
    { name: 'id',           re: /^#([\w\-\*]+)(\b|$)/ },
    { name: 'className',    re: /^\.([\w\-\*]+)(\b|$)/ },
    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
    { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
    { name: 'attr',         re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
  ],

  assertions: {
    tagName: function(element, matches) {
      return matches[1].toUpperCase() == element.tagName.toUpperCase();
    },

    className: function(element, matches) {
      return Element.hasClassName(element, matches[1]);
    },

    id: function(element, matches) {
      return element.id === matches[1];
    },

    attrPresence: function(element, matches) {
      return Element.hasAttribute(element, matches[1]);
    },

    attr: function(element, matches) {
      var nodeValue = Element.readAttribute(element, matches[1]);
      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
    }
  },

  handlers: {
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        a.push(node);
      return a;
    },

    mark: function(nodes) {
      var _true = Prototype.emptyFunction;
      for (var i = 0, node; node = nodes[i]; i++)
        node._countedByPrototype = _true;
      return nodes;
    },

    unmark: (function(){

      var PROPERTIES_ATTRIBUTES_MAP = (function(){
        var el = document.createElement('div'),
            isBuggy = false,
            propName = '_countedByPrototype',
            value = 'x'
        el[propName] = value;
        isBuggy = (el.getAttribute(propName) === value);
        el = null;
        return isBuggy;
      })();

      return PROPERTIES_ATTRIBUTES_MAP ?
        function(nodes) {
          for (var i = 0, node; node = nodes[i]; i++)
            node.removeAttribute('_countedByPrototype');
          return nodes;
        } :
        function(nodes) {
          for (var i = 0, node; node = nodes[i]; i++)
            node._countedByPrototype = void 0;
          return nodes;
        }
    })(),

    index: function(parentNode, reverse, ofType) {
      parentNode._countedByPrototype = Prototype.emptyFunction;
      if (reverse) {
        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
          var node = nodes[i];
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
      }
    },

    unique: function(nodes) {
      if (nodes.length == 0) return nodes;
      var results = [], n;
      for (var i = 0, l = nodes.length; i < l; i++)
        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
          n._countedByPrototype = Prototype.emptyFunction;
          results.push(Element.extend(n));
        }
      return Selector.handlers.unmark(results);
    },

    descendant: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, node.getElementsByTagName('*'));
      return results;
    },

    child: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        for (var j = 0, child; child = node.childNodes[j]; j++)
          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
      }
      return results;
    },

    adjacent: function(nodes) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        var next = this.nextElementSibling(node);
        if (next) results.push(next);
      }
      return results;
    },

    laterSibling: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, Element.nextSiblings(node));
      return results;
    },

    nextElementSibling: function(node) {
      while (node = node.nextSibling)
        if (node.nodeType == 1) return node;
      return null;
    },

    previousElementSibling: function(node) {
      while (node = node.previousSibling)
        if (node.nodeType == 1) return node;
      return null;
    },

    tagName: function(nodes, root, tagName, combinator) {
      var uTagName = tagName.toUpperCase();
      var results = [], h = Selector.handlers;
      if (nodes) {
        if (combinator) {
          if (combinator == "descendant") {
            for (var i = 0, node; node = nodes[i]; i++)
              h.concat(results, node.getElementsByTagName(tagName));
            return results;
          } else nodes = this[combinator](nodes);
          if (tagName == "*") return nodes;
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName.toUpperCase() === uTagName) results.push(node);
        return results;
      } else return root.getElementsByTagName(tagName);
    },

    id: function(nodes, root, id, combinator) {
      var targetNode = $(id), h = Selector.handlers;

      if (root == document) {
        if (!targetNode) return [];
        if (!nodes) return [targetNode];
      } else {
        if (!root.sourceIndex || root.sourceIndex < 1) {
          var nodes = root.getElementsByTagName('*');
          for (var j = 0, node; node = nodes[j]; j++) {
            if (node.id === id) return [node];
          }
        }
      }

      if (nodes) {
        if (combinator) {
          if (combinator == 'child') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (targetNode.parentNode == node) return [targetNode];
          } else if (combinator == 'descendant') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Element.descendantOf(targetNode, node)) return [targetNode];
          } else if (combinator == 'adjacent') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Selector.handlers.previousElementSibling(targetNode) == node)
                return [targetNode];
          } else nodes = h[combinator](nodes);
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node == targetNode) return [targetNode];
        return [];
      }
      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
    },

    className: function(nodes, root, className, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      return Selector.handlers.byClassName(nodes, root, className);
    },

    byClassName: function(nodes, root, className) {
      if (!nodes) nodes = Selector.handlers.descendant([root]);
      var needle = ' ' + className + ' ';
      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
        nodeClassName = node.className;
        if (nodeClassName.length == 0) continue;
        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
          results.push(node);
      }
      return results;
    },

    attrPresence: function(nodes, root, attr, combinator) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      if (nodes && combinator) nodes = this[combinator](nodes);
      var results = [];
      for (var i = 0, node; node = nodes[i]; i++)
        if (Element.hasAttribute(node, attr)) results.push(node);
      return results;
    },

    attr: function(nodes, root, attr, value, operator, combinator) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      if (nodes && combinator) nodes = this[combinator](nodes);
      var handler = Selector.operators[operator], results = [];
      for (var i = 0, node; node = nodes[i]; i++) {
        var nodeValue = Element.readAttribute(node, attr);
        if (nodeValue === null) continue;
        if (handler(nodeValue, value)) results.push(node);
      }
      return results;
    },

    pseudo: function(nodes, name, value, root, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      if (!nodes) nodes = root.getElementsByTagName("*");
      return Selector.pseudos[name](nodes, value, root);
    }
  },

  pseudos: {
    'first-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.previousElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'last-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.nextElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'only-child': function(nodes, value, root) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
          results.push(node);
      return results;
    },
    'nth-child':        function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root);
    },
    'nth-last-child':   function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true);
    },
    'nth-of-type':      function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, false, true);
    },
    'nth-last-of-type': function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true, true);
    },
    'first-of-type':    function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, false, true);
    },
    'last-of-type':     function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, true, true);
    },
    'only-of-type':     function(nodes, formula, root) {
      var p = Selector.pseudos;
      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
    },

    getIndices: function(a, b, total) {
      if (a == 0) return b > 0 ? [b] : [];
      return $R(1, total).inject([], function(memo, i) {
        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
        return memo;
      });
    },

    nth: function(nodes, formula, root, reverse, ofType) {
      if (nodes.length == 0) return [];
      if (formula == 'even') formula = '2n+0';
      if (formula == 'odd')  formula = '2n+1';
      var h = Selector.handlers, results = [], indexed = [], m;
      h.mark(nodes);
      for (var i = 0, node; node = nodes[i]; i++) {
        if (!node.parentNode._countedByPrototype) {
          h.index(node.parentNode, reverse, ofType);
          indexed.push(node.parentNode);
        }
      }
      if (formula.match(/^\d+$/)) { // just a number
        formula = Number(formula);
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.nodeIndex == formula) results.push(node);
      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
        if (m[1] == "-") m[1] = -1;
        var a = m[1] ? Number(m[1]) : 1;
        var b = m[2] ? Number(m[2]) : 0;
        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
          for (var j = 0; j < l; j++)
            if (node.nodeIndex == indices[j]) results.push(node);
        }
      }
      h.unmark(nodes);
      h.unmark(indexed);
      return results;
    },

    'empty': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (node.tagName == '!' || node.firstChild) continue;
        results.push(node);
      }
      return results;
    },

    'not': function(nodes, selector, root) {
      var h = Selector.handlers, selectorType, m;
      var exclusions = new Selector(selector).findElements(root);
      h.mark(exclusions);
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node._countedByPrototype) results.push(node);
      h.unmark(exclusions);
      return results;
    },

    'enabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node.disabled && (!node.type || node.type !== 'hidden'))
          results.push(node);
      return results;
    },

    'disabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.disabled) results.push(node);
      return results;
    },

    'checked': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.checked) results.push(node);
      return results;
    }
  },

  operators: {
    '=':  function(nv, v) { return nv == v; },
    '!=': function(nv, v) { return nv != v; },
    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
     '-').include('-' + (v || "").toUpperCase() + '-'); }
  },

  split: function(expression) {
    var expressions = [];
    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
      expressions.push(m[1].strip());
    });
    return expressions;
  },

  matchElements: function(elements, expression) {
    var matches = $$(expression), h = Selector.handlers;
    h.mark(matches);
    for (var i = 0, results = [], element; element = elements[i]; i++)
      if (element._countedByPrototype) results.push(element);
    h.unmark(matches);
    return results;
  },

  findElement: function(elements, expression, index) {
    if (Object.isNumber(expression)) {
      index = expression; expression = false;
    }
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    expressions = Selector.split(expressions.join(','));
    var results = [], h = Selector.handlers;
    for (var i = 0, l = expressions.length, selector; i < l; i++) {
      selector = new Selector(expressions[i].strip());
      h.concat(results, selector.findElements(element));
    }
    return (l > 1) ? h.unique(results) : results;
  }
});

if (Prototype.Browser.IE) {
  Object.extend(Selector.handlers, {
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        if (node.tagName !== "!") a.push(node);
      return a;
    }
  });
}

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}

var Form = {
  reset: function(form) {
    form = $(form);
    form.reset();
    return form;
  },

  serializeElements: function(elements, options) {
    if (typeof options != 'object') options = { hash: !!options };
    else if (Object.isUndefined(options.hash)) options.hash = true;
    var key, value, submitted = false, submit = options.submit;

    var data = elements.inject({ }, function(result, element) {
      if (!element.disabled && element.name) {
        key = element.name; value = $(element).getValue();
        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
            submit !== false && (!submit || key == submit) && (submitted = true)))) {
          if (key in result) {
            if (!Object.isArray(result[key])) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return options.hash ? data : Object.toQueryString(data);
  }
};

Form.Methods = {
  serialize: function(form, options) {
    return Form.serializeElements(Form.getElements(form), options);
  },

  getElements: function(form) {
    var elements = $(form).getElementsByTagName('*'),
        element,
        arr = [ ],
        serializers = Form.Element.Serializers;
    for (var i = 0; element = elements[i]; i++) {
      arr.push(element);
    }
    return arr.inject([], function(elements, child) {
      if (serializers[child.tagName.toLowerCase()])
        elements.push(Element.extend(child));
      return elements;
    })
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name) return $A(inputs).map(Element.extend);

    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) || (name && input.name != name))
        continue;
      matchingInputs.push(Element.extend(input));
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('disable');
    return form;
  },

  enable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('enable');
    return form;
  },

  findFirstElement: function(form) {
    var elements = $(form).getElements().findAll(function(element) {
      return 'hidden' != element.type && !element.disabled;
    });
    var firstByIndex = elements.findAll(function(element) {
      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
    }).sortBy(function(element) { return element.tabIndex }).first();

    return firstByIndex ? firstByIndex : elements.find(function(element) {
      return /^(?:input|select|textarea)$/i.test(element.tagName);
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    form.findFirstElement().activate();
    return form;
  },

  request: function(form, options) {
    form = $(form), options = Object.clone(options || { });

    var params = options.parameters, action = form.readAttribute('action') || '';
    if (action.blank()) action = window.location.href;
    options.parameters = form.serialize(true);

    if (params) {
      if (Object.isString(params)) params = params.toQueryParams();
      Object.extend(options.parameters, params);
    }

    if (form.hasAttribute('method') && !options.method)
      options.method = form.method;

    return new Ajax.Request(action, options);
  }
};

/*--------------------------------------------------------------------------*/


Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
};

Form.Element.Methods = {

  serialize: function(element) {
    element = $(element);
    if (!element.disabled && element.name) {
      var value = element.getValue();
      if (value != undefined) {
        var pair = { };
        pair[element.name] = value;
        return Object.toQueryString(pair);
      }
    }
    return '';
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

  setValue: function(element, value) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    Form.Element.Serializers[method](element, value);
    return element;
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
          !(/^(?:button|reset|submit)$/i.test(element.type))))
        element.select();
    } catch (e) { }
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.disabled = true;
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.disabled = false;
    return element;
  }
};

/*--------------------------------------------------------------------------*/

var Field = Form.Element;

var $F = Form.Element.Methods.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element, value) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element, value);
      default:
        return Form.Element.Serializers.textarea(element, value);
    }
  },

  inputSelector: function(element, value) {
    if (Object.isUndefined(value)) return element.checked ? element.value : null;
    else element.checked = !!value;
  },

  textarea: function(element, value) {
    if (Object.isUndefined(value)) return element.value;
    else element.value = value;
  },

  select: function(element, value) {
    if (Object.isUndefined(value))
      return this[element.type == 'select-one' ?
        'selectOne' : 'selectMany'](element);
    else {
      var opt, currentValue, single = !Object.isArray(value);
      for (var i = 0, length = element.length; i < length; i++) {
        opt = element.options[i];
        currentValue = this.optionValue(opt);
        if (single) {
          if (currentValue == value) {
            opt.selected = true;
            return;
          }
        }
        else opt.selected = value.include(currentValue);
      }
    }
  },

  selectOne: function(element) {
    var index = element.selectedIndex;
    return index >= 0 ? this.optionValue(element.options[index]) : null;
  },

  selectMany: function(element) {
    var values, length = element.length;
    if (!length) return null;

    for (var i = 0, values = []; i < length; i++) {
      var opt = element.options[i];
      if (opt.selected) values.push(this.optionValue(opt));
    }
    return values;
  },

  optionValue: function(opt) {
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
};

/*--------------------------------------------------------------------------*/


Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
  initialize: function($super, element, frequency, callback) {
    $super(callback, frequency);
    this.element   = $(element);
    this.lastValue = this.getValue();
  },

  execute: function() {
    var value = this.getValue();
    if (Object.isString(this.lastValue) && Object.isString(value) ?
        this.lastValue != value : String(this.lastValue) != String(value)) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
});

Form.Element.Observer = Class.create(Abstract.TimedObserver, {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create(Abstract.TimedObserver, {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = Class.create({
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    Form.getElements(this.element).each(this.registerCallback, this);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
});

Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create(Abstract.EventObserver, {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
(function() {

  var Event = {
    KEY_BACKSPACE: 8,
    KEY_TAB:       9,
    KEY_RETURN:   13,
    KEY_ESC:      27,
    KEY_LEFT:     37,
    KEY_UP:       38,
    KEY_RIGHT:    39,
    KEY_DOWN:     40,
    KEY_DELETE:   46,
    KEY_HOME:     36,
    KEY_END:      35,
    KEY_PAGEUP:   33,
    KEY_PAGEDOWN: 34,
    KEY_INSERT:   45,

    cache: {}
  };

  var docEl = document.documentElement;
  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
    && 'onmouseleave' in docEl;

  var _isButton;
  if (Prototype.Browser.IE) {
    var buttonMap = { 0: 1, 1: 4, 2: 2 };
    _isButton = function(event, code) {
      return event.button === buttonMap[code];
    };
  } else if (Prototype.Browser.WebKit) {
    _isButton = function(event, code) {
      switch (code) {
        case 0: return event.which == 1 && !event.metaKey;
        case 1: return event.which == 1 && event.metaKey;
        default: return false;
      }
    };
  } else {
    _isButton = function(event, code) {
      return event.which ? (event.which === code + 1) : (event.button === code);
    };
  }

  function isLeftClick(event)   { return _isButton(event, 0) }

  function isMiddleClick(event) { return _isButton(event, 1) }

  function isRightClick(event)  { return _isButton(event, 2) }

  function element(event) {
    event = Event.extend(event);

    var node = event.target, type = event.type,
     currentTarget = event.currentTarget;

    if (currentTarget && currentTarget.tagName) {
      if (type === 'load' || type === 'error' ||
        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
          && currentTarget.type === 'radio'))
            node = currentTarget;
    }

    if (node.nodeType == Node.TEXT_NODE)
      node = node.parentNode;

    return Element.extend(node);
  }

  function findElement(event, expression) {
    var element = Event.element(event);
    if (!expression) return element;
    var elements = [element].concat(element.ancestors());
    return Selector.findElement(elements, expression, 0);
  }

  function pointer(event) {
    return { x: pointerX(event), y: pointerY(event) };
  }

  function pointerX(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollLeft: 0 };

    return event.pageX || (event.clientX +
      (docElement.scrollLeft || body.scrollLeft) -
      (docElement.clientLeft || 0));
  }

  function pointerY(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollTop: 0 };

    return  event.pageY || (event.clientY +
       (docElement.scrollTop || body.scrollTop) -
       (docElement.clientTop || 0));
  }


  function stop(event) {
    Event.extend(event);
    event.preventDefault();
    event.stopPropagation();

    event.stopped = true;
  }

  Event.Methods = {
    isLeftClick: isLeftClick,
    isMiddleClick: isMiddleClick,
    isRightClick: isRightClick,

    element: element,
    findElement: findElement,

    pointer: pointer,
    pointerX: pointerX,
    pointerY: pointerY,

    stop: stop
  };


  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
    m[name] = Event.Methods[name].methodize();
    return m;
  });

  if (Prototype.Browser.IE) {
    function _relatedTarget(event) {
      var element;
      switch (event.type) {
        case 'mouseover': element = event.fromElement; break;
        case 'mouseout':  element = event.toElement;   break;
        default: return null;
      }
      return Element.extend(element);
    }

    Object.extend(methods, {
      stopPropagation: function() { this.cancelBubble = true },
      preventDefault:  function() { this.returnValue = false },
      inspect: function() { return '[object Event]' }
    });

    Event.extend = function(event, element) {
      if (!event) return false;
      if (event._extendedByPrototype) return event;

      event._extendedByPrototype = Prototype.emptyFunction;
      var pointer = Event.pointer(event);

      Object.extend(event, {
        target: event.srcElement || element,
        relatedTarget: _relatedTarget(event),
        pageX:  pointer.x,
        pageY:  pointer.y
      });

      return Object.extend(event, methods);
    };
  } else {
    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
    Object.extend(Event.prototype, methods);
    Event.extend = Prototype.K;
  }

  function _createResponder(element, eventName, handler) {
    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) {
      CACHE.push(element);
      registry = Element.retrieve(element, 'prototype_event_registry', $H());
    }

    var respondersForEvent = registry.get(eventName);
    if (Object.isUndefined(respondersForEvent)) {
      respondersForEvent = [];
      registry.set(eventName, respondersForEvent);
    }

    if (respondersForEvent.pluck('handler').include(handler)) return false;

    var responder;
    if (eventName.include(":")) {
      responder = function(event) {
        if (Object.isUndefined(event.eventName))
          return false;

        if (event.eventName !== eventName)
          return false;

        Event.extend(event, element);
        handler.call(element, event);
      };
    } else {
      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
       (eventName === "mouseenter" || eventName === "mouseleave")) {
        if (eventName === "mouseenter" || eventName === "mouseleave") {
          responder = function(event) {
            Event.extend(event, element);

            var parent = event.relatedTarget;
            while (parent && parent !== element) {
              try { parent = parent.parentNode; }
              catch(e) { parent = element; }
            }

            if (parent === element) return;

            handler.call(element, event);
          };
        }
      } else {
        responder = function(event) {
          Event.extend(event, element);
          handler.call(element, event);
        };
      }
    }

    responder.handler = handler;
    respondersForEvent.push(responder);
    return responder;
  }

  function _destroyCache() {
    for (var i = 0, length = CACHE.length; i < length; i++) {
      Event.stopObserving(CACHE[i]);
      CACHE[i] = null;
    }
  }

  var CACHE = [];

  if (Prototype.Browser.IE)
    window.attachEvent('onunload', _destroyCache);

  if (Prototype.Browser.WebKit)
    window.addEventListener('unload', Prototype.emptyFunction, false);


  var _getDOMEventName = Prototype.K;

  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
    _getDOMEventName = function(eventName) {
      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
      return eventName in translations ? translations[eventName] : eventName;
    };
  }

  function observe(element, eventName, handler) {
    element = $(element);

    var responder = _createResponder(element, eventName, handler);

    if (!responder) return element;

    if (eventName.include(':')) {
      if (element.addEventListener)
        element.addEventListener("dataavailable", responder, false);
      else {
        element.attachEvent("ondataavailable", responder);
        element.attachEvent("onfilterchange", responder);
      }
    } else {
      var actualEventName = _getDOMEventName(eventName);

      if (element.addEventListener)
        element.addEventListener(actualEventName, responder, false);
      else
        element.attachEvent("on" + actualEventName, responder);
    }

    return element;
  }

  function stopObserving(element, eventName, handler) {
    element = $(element);

    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) return element;

    if (eventName && !handler) {
      var responders = registry.get(eventName);

      if (Object.isUndefined(responders)) return element;

      responders.each( function(r) {
        Element.stopObserving(element, eventName, r.handler);
      });
      return element;
    } else if (!eventName) {
      registry.each( function(pair) {
        var eventName = pair.key, responders = pair.value;

        responders.each( function(r) {
          Element.stopObserving(element, eventName, r.handler);
        });
      });
      return element;
    }

    var responders = registry.get(eventName);

    if (!responders) return;

    var responder = responders.find( function(r) { return r.handler === handler; });
    if (!responder) return element;

    var actualEventName = _getDOMEventName(eventName);

    if (eventName.include(':')) {
      if (element.removeEventListener)
        element.removeEventListener("dataavailable", responder, false);
      else {
        element.detachEvent("ondataavailable", responder);
        element.detachEvent("onfilterchange",  responder);
      }
    } else {
      if (element.removeEventListener)
        element.removeEventListener(actualEventName, responder, false);
      else
        element.detachEvent('on' + actualEventName, responder);
    }

    registry.set(eventName, responders.without(responder));

    return element;
  }

  function fire(element, eventName, memo, bubble) {
    element = $(element);

    if (Object.isUndefined(bubble))
      bubble = true;

    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 = bubble ? 'ondataavailable' : 'onfilterchange';
    }

    event.eventName = eventName;
    event.memo = memo || { };

    if (document.createEvent)
      element.dispatchEvent(event);
    else
      element.fireEvent(event.eventType, event);

    return Event.extend(event);
  }


  Object.extend(Event, Event.Methods);

  Object.extend(Event, {
    fire:          fire,
    observe:       observe,
    stopObserving: stopObserving
  });

  Element.addMethods({
    fire:          fire,

    observe:       observe,

    stopObserving: stopObserving
  });

  Object.extend(document, {
    fire:          fire.methodize(),

    observe:       observe.methodize(),

    stopObserving: stopObserving.methodize(),

    loaded:        false
  });

  if (window.Event) Object.extend(window.Event, Event);
  else window.Event = Event;
})();

(function() {
  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */

  var timer;

  function fireContentLoadedEvent() {
    if (document.loaded) return;
    if (timer) window.clearTimeout(timer);
    document.loaded = true;
    document.fire('dom:loaded');
  }

  function checkReadyState() {
    if (document.readyState === 'complete') {
      document.stopObserving('readystatechange', checkReadyState);
      fireContentLoadedEvent();
    }
  }

  function pollDoScroll() {
    try { document.documentElement.doScroll('left'); }
    catch(e) {
      timer = pollDoScroll.defer();
      return;
    }
    fireContentLoadedEvent();
  }

  if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
  } else {
    document.observe('readystatechange', checkReadyState);
    if (window == top)
      timer = pollDoScroll.defer();
  }

  Event.observe(window, 'load', fireContentLoadedEvent);
})();

Element.addMethods();

/*------------------------------- DEPRECATED -------------------------------*/

Hash.toQueryString = Object.toQueryString;

var Toggle = { display: Element.toggle };

Element.Methods.childOf = Element.Methods.descendantOf;

var Insertion = {
  Before: function(element, content) {
    return Element.insert(element, {before:content});
  },

  Top: function(element, content) {
    return Element.insert(element, {top:content});
  },

  Bottom: function(element, content) {
    return Element.insert(element, {bottom:content});
  },

  After: function(element, content) {
    return Element.insert(element, {after:content});
  }
};

var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

var Position = {
  includeScrollOffsets: false,

  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = Element.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = Element.cumulativeScrollOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = Element.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },


  cumulativeOffset: Element.Methods.cumulativeOffset,

  positionedOffset: Element.Methods.positionedOffset,

  absolutize: function(element) {
    Position.prepare();
    return Element.absolutize(element);
  },

  relativize: function(element) {
    Position.prepare();
    return Element.relativize(element);
  },

  realOffset: Element.Methods.cumulativeScrollOffset,

  offsetParent: Element.Methods.getOffsetParent,

  page: Element.Methods.viewportOffset,

  clone: function(source, target, options) {
    options = options || { };
    return Element.clonePosition(target, source, options);
  }
};

/*--------------------------------------------------------------------------*/

if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
  function iter(name) {
    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
  }

  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
  function(element, className) {
    className = className.toString().strip();
    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
  } : function(element, className) {
    className = className.toString().strip();
    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
    if (!classNames && !className) return elements;

    var nodes = $(element).getElementsByTagName('*');
    className = ' ' + className + ' ';

    for (var i = 0, child, cn; child = nodes[i]; i++) {
      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
          (classNames && classNames.all(function(name) {
            return !name.toString().blank() && cn.include(' ' + name + ' ');
          }))))
        elements.push(Element.extend(child));
    }
    return elements;
  };

  return function(className, parentElement) {
    return $(parentElement || document.body).getElementsByClassName(className);
  };
}(Element.Methods);

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};

Object.extend(Element.ClassNames.prototype, Enumerable);

/*--------------------------------------------------------------------------*/


// script.aculo.us scriptaculous.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/

var Scriptaculous = {
  Version: '1.8.3',
  require: function(libraryName) {
    try{
      // inserting via DOM fails in Safari 2.0, so brute force approach
      document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
    } catch(e) {
      // for xhtml+xml served content, fall back to DOM methods
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = libraryName;
      document.getElementsByTagName('head')[0].appendChild(script);
    }
  },
  REQUIRED_PROTOTYPE: '1.6.0.3',
  load: function() {
    function convertVersionString(versionString) {
      var v = versionString.replace(/_.*|\./g, '');
      v = parseInt(v + '0'.times(4-v.length));
      return versionString.indexOf('_') > -1 ? v-1 : v;
    }

    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       (convertVersionString(Prototype.Version) <
        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
        Scriptaculous.REQUIRED_PROTOTYPE);

    var js = /scriptaculous\.js(\?.*)?$/;
    $$('head script[src]').findAll(function(s) {
      return s.src.match(js);
    }).each(function(s) {
      var path = s.src.replace(js, ''),
      includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
       function(include) { Scriptaculous.require(path+include+'.js') });
    });
  }
};

Scriptaculous.load();

// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// converts rgb() and #xxx to #xxxxxx format,
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
  var color = '#';
  if (this.slice(0,4) == 'rgb(') {
    var cols = this.slice(4,this.length-1).split(',');
    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
  } else {
    if (this.slice(0,1) == '#') {
      if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
      if (this.length==7) color = this.toLowerCase();
    }
  }
  return (color.length==7 ? color : (arguments[0] || this));
};

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
  }).flatten().join('');
};

Element.collectTextNodesIgnoreClass = function(element, className) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
        Element.collectTextNodesIgnoreClass(node, className) : ''));
  }).flatten().join('');
};

Element.setContentZoom = function(element, percent) {
  element = $(element);
  element.setStyle({fontSize: (percent/100) + 'em'});
  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
  return element;
};

Element.getInlineOpacity = function(element){
  return $(element).style.opacity || '';
};

Element.forceRerendering = function(element) {
  try {
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    element.removeChild(n);
  } catch(e) { }
};

/*--------------------------------------------------------------------------*/

var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  Transitions: {
    linear: Prototype.K,
    sinoidal: function(pos) {
      return (-Math.cos(pos*Math.PI)/2) + .5;
    },
    reverse: function(pos) {
      return 1-pos;
    },
    flicker: function(pos) {
      var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
      return pos > 1 ? 1 : pos;
    },
    wobble: function(pos) {
      return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
    },
    pulse: function(pos, pulses) {
      return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
    },
    spring: function(pos) {
      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
    },
    none: function(pos) {
      return 0;
    },
    full: function(pos) {
      return 1;
    }
  },
  DefaultOptions: {
    duration:   1.0,   // seconds
    fps:        100,   // 100= assume 66fps max.
    sync:       false, // true for combining
    from:       0.0,
    to:         1.0,
    delay:      0.0,
    queue:      'parallel'
  },
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';

    element = $(element);
    $A(element.childNodes).each( function(child) {
      if (child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            new Element('span', {style: tagifyStyle}).update(
              character == ' ' ? String.fromCharCode(160) : character),
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if (((typeof element == 'object') ||
        Object.isFunction(element)) &&
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;

    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || { });
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect, options) {
    element = $(element);
    effect  = (effect || 'appear').toLowerCase();
    
    return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
    }, options || {}));
  }
};

Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create(Enumerable, {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();

    var position = Object.isString(effect.options.queue) ?
      effect.options.queue : effect.options.queue.position;

    switch(position) {
      case 'front':
        // move unstarted effects after this effect
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'with-last':
        timestamp = this.effects.pluck('startOn').max() || timestamp;
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }

    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);

    if (!this.interval)
      this.interval = setInterval(this.loop.bind(this), 15);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if (this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    for(var i=0, len=this.effects.length;i<len;i++)
      this.effects[i] && this.effects[i].loop(timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if (!Object.isString(queueName)) return queueName;

    return this.instances.get(queueName) ||
      this.instances.set(queueName, new Effect.ScopedQueue());
  }
};
Effect.Queue = Effect.Queues.get('global');

Effect.Base = Class.create({
  position: null,
  start: function(options) {
    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
    this.options      = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn+(this.options.duration*1000);
    this.fromToDelta  = this.options.to-this.options.from;
    this.totalTime    = this.finishOn-this.startOn;
    this.totalFrames  = this.options.fps*this.options.duration;

    this.render = (function() {
      function dispatch(effect, eventName) {
        if (effect.options[eventName + 'Internal'])
          effect.options[eventName + 'Internal'](effect);
        if (effect.options[eventName])
          effect.options[eventName](effect);
      }

      return function(pos) {
        if (this.state === "idle") {
          this.state = "running";
          dispatch(this, 'beforeSetup');
          if (this.setup) this.setup();
          dispatch(this, 'afterSetup');
        }
        if (this.state === "running") {
          pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
          this.position = pos;
          dispatch(this, 'beforeUpdate');
          if (this.update) this.update(pos);
          dispatch(this, 'afterUpdate');
        }
      };
    })();

    this.event('beforeStart');
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if (timePos >= this.startOn) {
      if (timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if (this.finish) this.finish();
        this.event('afterFinish');
        return;
      }
      var pos   = (timePos - this.startOn) / this.totalTime,
          frame = (pos * this.totalFrames).round();
      if (frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  cancel: function() {
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if (this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    var data = $H();
    for(property in this)
      if (!Object.isFunction(this[property])) data.set(property, this[property]);
    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
});

Effect.Parallel = Class.create(Effect.Base, {
  initialize: function(effects) {
    this.effects = effects || [];
    this.start(arguments[1]);
  },
  update: function(position) {
    this.effects.invoke('render', position);
  },
  finish: function(position) {
    this.effects.each( function(effect) {
      effect.render(1.0);
      effect.cancel();
      effect.event('beforeFinish');
      if (effect.finish) effect.finish(position);
      effect.event('afterFinish');
    });
  }
});

Effect.Tween = Class.create(Effect.Base, {
  initialize: function(object, from, to) {
    object = Object.isString(object) ? $(object) : object;
    var args = $A(arguments), method = args.last(),
      options = args.length == 5 ? args[3] : null;
    this.method = Object.isFunction(method) ? method.bind(object) :
      Object.isFunction(object[method]) ? object[method].bind(object) :
      function(value) { object[method] = value };
    this.start(Object.extend({ from: from, to: to }, options || { }));
  },
  update: function(position) {
    this.method(position);
  }
});

Effect.Event = Class.create(Effect.Base, {
  initialize: function() {
    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
  },
  update: Prototype.emptyFunction
});

Effect.Opacity = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    // make this work on IE on elements without 'layout'
    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
      this.element.setStyle({zoom: 1});
    var options = Object.extend({
      from: this.element.getOpacity() || 0.0,
      to:   1.0
    }, arguments[1] || { });
    this.start(options);
  },
  update: function(position) {
    this.element.setOpacity(position);
  }
});

Effect.Move = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if (this.options.mode == 'absolute') {
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: (this.options.x  * position + this.originalLeft).round() + 'px',
      top:  (this.options.y  * position + this.originalTop).round()  + 'px'
    });
  }
});

// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
  return new Effect.Move(element,
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};

Effect.Scale = Class.create(Effect.Base, {
  initialize: function(element, percent) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or { } with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || { });
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');

    this.originalStyle = { };
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));

    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;

    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].each( function(fontSizeType) {
      if (fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));

    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;

    this.dims = null;
    if (this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if (/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if (!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if (this.options.scaleContent && this.fontSize)
      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = { };
    if (this.options.scaleX) d.width = width.round() + 'px';
    if (this.options.scaleY) d.height = height.round() + 'px';
    if (this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if (this.elementPositioning == 'absolute') {
        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if (this.options.scaleY) d.top = -topd + 'px';
        if (this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

Effect.Highlight = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if (this.element.getStyle('display')=='none') { this.cancel(); return; }
    // Disable background image during the effect
    this.oldStyle = { };
    if (!this.options.keepBackgroundImage) {
      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
      this.element.setStyle({backgroundImage: 'none'});
    }
    if (!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
    if (!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('background-color');
    // init color calculations
    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
      return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
  },
  finish: function() {
    this.element.setStyle(Object.extend(this.oldStyle, {
      backgroundColor: this.options.restorecolor
    }));
  }
});

Effect.ScrollTo = function(element) {
  var options = arguments[1] || { },
  scrollOffsets = document.viewport.getScrollOffsets(),
  elementOffsets = $(element).cumulativeOffset();

  if (options.offset) elementOffsets[1] += options.offset;

  return new Effect.Tween(null,
    scrollOffsets.top,
    elementOffsets[1],
    options,
    function(p){ scrollTo(scrollOffsets.left, p.round()); }
  );
};

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
    from: element.getOpacity() || 1.0,
    to:   0.0,
    afterFinishInternal: function(effect) {
      if (effect.options.to!=0) return;
      effect.element.hide().setStyle({opacity: oldOpacity});
    }
  }, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Appear = function(element) {
  element = $(element);
  var options = Object.extend({
  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
  to:   1.0,
  // force Safari to render floated elements properly
  afterFinishInternal: function(effect) {
    effect.element.forceRerendering();
  },
  beforeSetup: function(effect) {
    effect.element.setOpacity(effect.options.from).show();
  }}, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = {
    opacity: element.getInlineOpacity(),
    position: element.getStyle('position'),
    top:  element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height
  };
  return new Effect.Parallel(
   [ new Effect.Scale(element, 200,
      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
     Object.extend({ duration: 1.0,
      beforeSetupInternal: function(effect) {
        Position.absolutize(effect.effects[0].element);
      },
      afterFinishInternal: function(effect) {
         effect.effects[0].element.hide().setStyle(oldStyle); }
     }, arguments[1] || { })
   );
};

Effect.BlindUp = function(element) {
  element = $(element);
  element.makeClipping();
  return new Effect.Scale(element, 0,
    Object.extend({ scaleContent: false,
      scaleX: false,
      restoreAfterFinish: true,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping();
      }
    }, arguments[1] || { })
  );
};

Effect.BlindDown = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  }, arguments[1] || { }));
};

Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  return new Effect.Appear(element, Object.extend({
    duration: 0.4,
    from: 0,
    transition: Effect.Transitions.flicker,
    afterFinishInternal: function(effect) {
      new Effect.Scale(effect.element, 1, {
        duration: 0.3, scaleFromCenter: true,
        scaleX: false, scaleContent: false, restoreAfterFinish: true,
        beforeSetup: function(effect) {
          effect.element.makePositioned().makeClipping();
        },
        afterFinishInternal: function(effect) {
          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
        }
      });
    }
  }, arguments[1] || { }));
};

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left'),
    opacity: element.getInlineOpacity() };
  return new Effect.Parallel(
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
    Object.extend(
      { duration: 0.5,
        beforeSetup: function(effect) {
          effect.effects[0].element.makePositioned();
        },
        afterFinishInternal: function(effect) {
          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
        }
      }, arguments[1] || { }));
};

Effect.Shake = function(element) {
  element = $(element);
  var options = Object.extend({
    distance: 20,
    duration: 0.5
  }, arguments[1] || {});
  var distance = parseFloat(options.distance);
  var split = parseFloat(options.duration) / 10.0;
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element,
      { x:  distance, y: 0, duration: split, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
        effect.element.undoPositioned().setStyle(oldStyle);
  }}); }}); }}); }}); }}); }});
};

Effect.SlideDown = function(element) {
  element = $(element).cleanWhitespace();
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: window.opera ? 0 : 1,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
    }, arguments[1] || { })
  );
};

Effect.SlideUp = function(element) {
  element = $(element).cleanWhitespace();
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, window.opera ? 0 : 1,
   Object.extend({ scaleContent: false,
    scaleX: false,
    scaleMode: 'box',
    scaleFrom: 100,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
    }
   }, arguments[1] || { })
  );
};

// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
  return new Effect.Scale(element, window.opera ? 1 : 0, {
    restoreAfterFinish: true,
    beforeSetup: function(effect) {
      effect.element.makeClipping();
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping();
    }
  });
};

Effect.Grow = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.full
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var initialMoveX, initialMoveY;
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      initialMoveX = initialMoveY = moveX = moveY = 0;
      break;
    case 'top-right':
      initialMoveX = dims.width;
      initialMoveY = moveY = 0;
      moveX = -dims.width;
      break;
    case 'bottom-left':
      initialMoveX = moveX = 0;
      initialMoveY = dims.height;
      moveY = -dims.height;
      break;
    case 'bottom-right':
      initialMoveX = dims.width;
      initialMoveY = dims.height;
      moveX = -dims.width;
      moveY = -dims.height;
      break;
    case 'center':
      initialMoveX = dims.width / 2;
      initialMoveY = dims.height / 2;
      moveX = -dims.width / 2;
      moveY = -dims.height / 2;
      break;
  }

  return new Effect.Move(element, {
    x: initialMoveX,
    y: initialMoveY,
    duration: 0.01,
    beforeSetup: function(effect) {
      effect.element.hide().makeClipping().makePositioned();
    },
    afterFinishInternal: function(effect) {
      new Effect.Parallel(
        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
          new Effect.Scale(effect.element, 100, {
            scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
        ], Object.extend({
             beforeSetup: function(effect) {
               effect.effects[0].element.setStyle({height: '0px'}).show();
             },
             afterFinishInternal: function(effect) {
               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
             }
           }, options)
      );
    }
  });
};

Effect.Shrink = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.none
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      moveX = moveY = 0;
      break;
    case 'top-right':
      moveX = dims.width;
      moveY = 0;
      break;
    case 'bottom-left':
      moveX = 0;
      moveY = dims.height;
      break;
    case 'bottom-right':
      moveX = dims.width;
      moveY = dims.height;
      break;
    case 'center':
      moveX = dims.width / 2;
      moveY = dims.height / 2;
      break;
  }

  return new Effect.Parallel(
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
    ], Object.extend({
         beforeStartInternal: function(effect) {
           effect.effects[0].element.makePositioned().makeClipping();
         },
         afterFinishInternal: function(effect) {
           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
       }, options)
  );
};

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || { },
    oldOpacity = element.getInlineOpacity(),
    transition = options.transition || Effect.Transitions.linear,
    reverser   = function(pos){
      return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
    };

  return new Effect.Opacity(element,
    Object.extend(Object.extend({  duration: 2.0, from: 0,
      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
    }, options), {transition: reverser}));
};

Effect.Fold = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height };
  element.makeClipping();
  return new Effect.Scale(element, 5, Object.extend({
    scaleContent: false,
    scaleX: false,
    afterFinishInternal: function(effect) {
    new Effect.Scale(element, 1, {
      scaleContent: false,
      scaleY: false,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping().setStyle(oldStyle);
      } });
  }}, arguments[1] || { }));
};

Effect.Morph = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      style: { }
    }, arguments[1] || { });

    if (!Object.isString(options.style)) this.style = $H(options.style);
    else {
      if (options.style.include(':'))
        this.style = options.style.parseStyle();
      else {
        this.element.addClassName(options.style);
        this.style = $H(this.element.getStyles());
        this.element.removeClassName(options.style);
        var css = this.element.getStyles();
        this.style = this.style.reject(function(style) {
          return style.value == css[style.key];
        });
        options.afterFinishInternal = function(effect) {
          effect.element.addClassName(effect.options.style);
          effect.transforms.each(function(transform) {
            effect.element.style[transform.style] = '';
          });
        };
      }
    }
    this.start(options);
  },

  setup: function(){
    function parseColor(color){
      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
      color = color.parseColor();
      return $R(0,2).map(function(i){
        return parseInt( color.slice(i*2+1,i*2+3), 16 );
      });
    }
    this.transforms = this.style.map(function(pair){
      var property = pair[0], value = pair[1], unit = null;

      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
        value = value.parseColor();
        unit  = 'color';
      } else if (property == 'opacity') {
        value = parseFloat(value);
        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
          this.element.setStyle({zoom: 1});
      } else if (Element.CSS_LENGTH.test(value)) {
          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
          value = parseFloat(components[1]);
          unit = (components.length == 3) ? components[2] : null;
      }

      var originalValue = this.element.getStyle(property);
      return {
        style: property.camelize(),
        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
        targetValue: unit=='color' ? parseColor(value) : value,
        unit: unit
      };
    }.bind(this)).reject(function(transform){
      return (
        (transform.originalValue == transform.targetValue) ||
        (
          transform.unit != 'color' &&
          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
        )
      );
    });
  },
  update: function(position) {
    var style = { }, transform, i = this.transforms.length;
    while(i--)
      style[(transform = this.transforms[i]).style] =
        transform.unit=='color' ? '#'+
          (Math.round(transform.originalValue[0]+
            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
          (Math.round(transform.originalValue[1]+
            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
          (Math.round(transform.originalValue[2]+
            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
        (transform.originalValue +
          (transform.targetValue - transform.originalValue) * position).toFixed(3) +
            (transform.unit === null ? '' : transform.unit);
    this.element.setStyle(style, true);
  }
});

Effect.Transform = Class.create({
  initialize: function(tracks){
    this.tracks  = [];
    this.options = arguments[1] || { };
    this.addTracks(tracks);
  },
  addTracks: function(tracks){
    tracks.each(function(track){
      track = $H(track);
      var data = track.values().first();
      this.tracks.push($H({
        ids:     track.keys().first(),
        effect:  Effect.Morph,
        options: { style: data }
      }));
    }.bind(this));
    return this;
  },
  play: function(){
    return new Effect.Parallel(
      this.tracks.map(function(track){
        var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
        var elements = [$(ids) || $$(ids)].flatten();
        return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
      }).flatten(),
      this.options
    );
  }
});

Element.CSS_PROPERTIES = $w(
  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  'fontSize fontWeight height left letterSpacing lineHeight ' +
  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  'right textIndent top width wordSpacing zIndex');

Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
  var style, styleRules = $H();
  if (Prototype.Browser.WebKit)
    style = new Element('div',{style:this}).style;
  else {
    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
    style = String.__parseStyleElement.childNodes[0].style;
  }

  Element.CSS_PROPERTIES.each(function(property){
    if (style[property]) styleRules.set(property, style[property]);
  });

  if (Prototype.Browser.IE && this.include('opacity'))
    styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);

  return styleRules;
};

if (document.defaultView && document.defaultView.getComputedStyle) {
  Element.getStyles = function(element) {
    var css = document.defaultView.getComputedStyle($(element), null);
    return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
      styles[property] = css[property];
      return styles;
    });
  };
} else {
  Element.getStyles = function(element) {
    element = $(element);
    var css = element.currentStyle, styles;
    styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
      results[property] = css[property];
      return results;
    });
    if (!styles.opacity) styles.opacity = element.getOpacity();
    return styles;
  };
}

Effect.Methods = {
  morph: function(element, style) {
    element = $(element);
    new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
    return element;
  },
  visualEffect: function(element, effect, options) {
    element = $(element);
    var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
    new Effect[klass](element, options);
    return element;
  },
  highlight: function(element, options) {
    element = $(element);
    new Effect.Highlight(element, options);
    return element;
  }
};

$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
  'pulsate shake puff squish switchOff dropOut').each(
  function(effect) {
    Effect.Methods[effect] = function(element, options){
      element = $(element);
      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
      return element;
    };
  }
);

$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
  function(f) { Effect.Methods[f] = Element[f]; }
);

Element.addMethods(Effect.Methods);

/*
transitions.js

Based on Easing Equations v2.0
(c) 2003 Robert Penner, all rights reserved.
This work is subject to the terms in http://www.robertpenner.com/easing_terms_of_use.html

Adapted for Scriptaculous by Ken Snyder (kendsnyder ~at~ gmail ~dot~ com) June 2006
*/


/*
Overshooting Transitions
*/

// Elastic (adapted from "EaseOutElastic")
Effect.Transitions.Elastic = function(pos) {
    return -1*Math.pow(4,-8*pos) * Math.sin((pos*6-1)*(2*Math.PI)/2) + 1;
};

// SwingFromTo (adapted from "BackEaseInOut")
Effect.Transitions.SwingFromTo = function(pos) {
    var s = 1.70158;
    if ((pos/=0.5) < 1) return 0.5*(pos*pos*(((s*=(1.525))+1)*pos - s));
    return 0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos + s) + 2);
};

// SwingFrom (adapted from "BackEaseIn")
Effect.Transitions.SwingFrom = function(pos) {
    var s = 1.70158;
    return pos*pos*((s+1)*pos - s);
};

// SwingTo (adapted from "BackEaseOut")
Effect.Transitions.SwingTo = function(pos) {
    var s = 1.70158;
    return (pos-=1)*pos*((s+1)*pos + s) + 1;
};


/*
Bouncing Transitions
*/

// Bounce (adapted from "EaseOutBounce")
Effect.Transitions.Bounce = function(pos) {
    if (pos < (1/2.75)) {
        return (7.5625*pos*pos);
    } else if (pos < (2/2.75)) {
        return (7.5625*(pos-=(1.5/2.75))*pos + .75);
    } else if (pos < (2.5/2.75)) {
        return (7.5625*(pos-=(2.25/2.75))*pos + .9375);
    } else {
        return (7.5625*(pos-=(2.625/2.75))*pos + .984375);
    }
};

// BouncePast (new creation based on "EaseOutBounce")
Effect.Transitions.BouncePast = function(pos) {
    if (pos < (1/2.75)) {
        return (7.5625*pos*pos);
    } else if (pos < (2/2.75)) {
        return 2 - (7.5625*(pos-=(1.5/2.75))*pos + .75);
    } else if (pos < (2.5/2.75)) {
        return 2 - (7.5625*(pos-=(2.25/2.75))*pos + .9375);
    } else {
        return 2 - (7.5625*(pos-=(2.625/2.75))*pos + .984375);
    }
};


/*
Gradual Transitions
*/

// EaseFromTo (adapted from "Quart.EaseInOut")
Effect.Transitions.EaseFromTo = function(pos) {
    if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,4);
    return -0.5 * ((pos-=2)*Math.pow(pos,3) - 2);
};

// EaseFrom (adapted from "Quart.EaseIn")
Effect.Transitions.EaseFrom = function(pos) {
    return Math.pow(pos,4);
};

// EaseTo (adapted from "Quart.EaseOut")
Effect.Transitions.EaseTo = function(pos) {
    return Math.pow(pos,0.25);
};

// CONFIRM PROMPT
/* <a href="http://www.google.com/" onclick="return confirmPrompt(this.href, 'Are you sure you want to?');">Test</a> */
function confirmPrompt(url, msg) {
    if (confirm(msg)) window.location = url;
    return false;
}

// POPUP
/* <a href="http://www.google.com/" onclick="return doPopup(this.href, {location:'yes'});">Test</a> */
function doPopup(url, options) {
    var Popup = {
        open: function(url, options) {
            this.options = {
                width: 600,
                height: 500,
                name: '_blank',
                location: 'no',
                menubar: 'no',
                toolbar: 'no',
                status: 'yes',
                scrollbars: 'yes',
                resizable: 'yes',
                top: '',
                left: '',
                center: true
            }
            Object.extend(this.options, options || {});
            this.options.width = this.options.width < screen.availWidth ? this.options.width : screen.availWidth;
            this.options.height = this.options.height < screen.availHeight ? this.options.height : screen.availHeight;
            if (this.options.center) {
                this.options.top = (screen.height - this.options.height) / 2 ;
                this.options.left = (screen.width - this.options.width) / 2;
            }
            var openoptions = 'width=' +this.options.width+ ',height=' +this.options.height+ ',location=' +this.options.location+ ',menubar=' +this.options.menubar+ ',toolbar=' +this.options.toolbar+ ',scrollbars=' +this.options.scrollbars+ ',resizable=' +this.options.resizable+ ',status=' +this.options.status
            if (this.options.top != '') openoptions += ',top=' +this.options.top;
            if (this.options.left != '') openoptions += ',left=' +this.options.left;
            window.open(url, this.options.name, openoptions);
            return false;
        }
    }
    return Popup.open(url, options);
}

// HANDLE AJAX JSON RESPONSE
function handleResponse(transport) {
    var content = (transport.responseText).evalJSON();
    Object.keys(content.elements).each(function(item) {
        $(item).update(content['elements'][item]);
    });
    Object.keys(content.javascript).each(function(item) {
        eval( content['javascript'][item]);
    });
}

// COOKIES (Cookie.set(), Cookie.get(), Cookie.unset())
var Cookie = {
    build: function() {
        return $A(arguments).compact().join("; ");
    },
    secondsFromNow: function(seconds) {
        var d = new Date();
        d.setTime(d.getTime() + (seconds * 1000));
        return d.toGMTString();
    },
    set: function(name, value, seconds) {
        var expiry = seconds ? 'expires=' + Cookie.secondsFromNow(seconds) : null;
        document.cookie = Cookie.build(name + "=" + value, expiry, "path=/");
    },
    get: function(name) {
        var valueMatch = new RegExp(name + "=([^;]+)").exec(document.cookie);
        return valueMatch ? valueMatch[1] : null;
    },
    unset: function(name) {
        Cookie.set(name, '', -1);
    }
};

// PRELOAD IMAGE
function preloadImage(img) {
    var preload = new Image();
    preload.src = img;
}

var swapLoaded = new Array();

// SWAP IMAGE
function swapImage(el, img_over, img_out) {
    if (img_over) preloadImage(img_over);
    var id = $(el).readAttribute('id');
    if (!id) {
        var id = 'rand_id-' +Math.random();
        $(el).writeAttribute('id', id);
    }
    if (!swapLoaded[id]) {
        swapLoaded[id] = $(el).readAttribute('src');
        $(el).writeAttribute('onload', '');
        Event.observe(el, 'mouseover', function() {
            if (img_over) $(el).writeAttribute('src', img_over);
        });
        Event.observe(el, 'mouseout', function() {
            if (img_out) {
                $(el).writeAttribute('src', img_out);
            } else {
                $(el).writeAttribute('src', swapLoaded[id]);
            }
        });
    }
}

// READ MORE LINK
function readMore(parent, show_sel, hide_sel) {
    if (!show_sel) var show_sel = '.rmt';
    if (!hide_sel) var hide_sel = '.rml';
    $(parent).select(show_sel).each(function(item) {
        item.show();
    });
    $(parent).select(hide_sel).each(function(item) {
        item.hide();
    });
}


function showTip(id) {
    $(id).prototip.show();
}

function hideTip(id) {
    $(id).prototip.hide();
}

var closeWindow_custom;

// CREATE OUTPUT FOR MESSAGE CLASS
function messageClass_output(cssclass, message) {
    if (message) {
        var retval = '';
        retval = '<div class="message-' +cssclass+ '">';
        message.split('|').each(function(item) {
           retval += '<div><b>&middot;</b>&nbsp;' +item+ '</div>';
        });
        retval += '</div>';
        return retval;
    }
}

/* TOP LOGIN */

function topLogin_Show() {
    Effect.Fade('div_top-login-links', {
        duration: .4,
        afterFinish: function() {
            Effect.Appear('div_top-login-form', {duration: .4});
        }
    });
    return false;
}

function topLogin_Hide() {
    Effect.Fade('div_top-login-form', {
        duration: .4,
        afterFinish: function() {
            Effect.Appear('div_top-login-links', {duration: .4});
        }
    });
    return false;
}

function topLogin_usernameChange() {
    if ($F('toplogin_username') == 'username') {
        $('toplogin_username').value = '';
    } else if (!$F('toplogin_username')) {
        $('toplogin_username').value = 'username';
    }
}

function topLogin_passwordChange_focus() {
    $('toplogin_password_temp').hide();
    $('toplogin_password_real').show();
    $('toplogin_password_real').activate();
}

function topLogin_passwordChange_blur() {
    if (!$F('toplogin_password_real')) {
        $('toplogin_password_real').hide();
        $('toplogin_password_temp').show();
    }
}

/* HEADER - ACCOUNT INFO */

function topAccountInfo() {
    new Ajax.Request('/includes/ajax_calls/account/top.php', {
        method: 'post',
        parameters: {login_goto: document.location.href},
        onSuccess: function(transport) {
            var retval = (transport.responseText).evalJSON();
            $('top_login_register').update(retval['data']);
        },
        onFailure: function() {
        },
        onComplete: function() {
        }
    });
}

/* TOP WEATHER */

function getTopWeather(community, toggle) {
    if (($('top_weather').empty()) || (community)) {
        new Ajax.Request('/includes/ajax_calls/weather/top.php', {
            method: 'post',
            parameters: {community: community},
            onSuccess: function(transport) {
                var retval = (transport.responseText).evalJSON();
                $('top_weather').update(retval['data']);
                $('breadcrumb_weather').update(retval['text']);
                if (toggle) toggleTopWeather();
            },
            onFailure: function() {
            },
            onComplete: function() {
            }
        });
    } else if (toggle) {
        toggleTopWeather();
    }
}

function toggleTopWeather() {
    Effect.toggle('top_weather', 'slide', {
        duration: 1,
        transition: Effect.Transitions.Bounce
    });
    if ($('top_weather').visible() == false) {
        trackExpand('header', 'block', '1', 'expand');
    }
}

function toggleTopWeatherLocation() {
    var el = $('top_weather_location_select');
    if (el.visible()) {
        Effect.SlideUp(el, { duration: .2 });
        $('top_weather_change_location_link').removeClassName('on');
    } else {
        Effect.SlideDown(el, { duration: .2 });
        $('top_weather_change_location_link').addClassName('on');
    }
}

/* TRACK TOGGLE */

function trackExpand(area, item, value, action) {
    new Ajax.Request('/includes/ajax_calls/stats/trackExpand.php', {
        method: 'post',
        parameters: {area: area, item: item, value: value, action: action}
    });
}

/* SORT BUSINESSES */

function sortBusinesses(el_id, options) {
    var Sort = {
        get: function(el_id, options) {
            this.options = {
                el_id: el_id,
                category: '',
                level: 1,
                field: 'title',
                direction: 'asc',
                community: '',
                q: '',
                from: 'businessdir'
            }
            Object.extend(this.options, options || {});
            new Ajax.Request('/includes/ajax_calls/directory/sortBusinesses.php', {
                method: 'post',
                parameters: this.options,
                onSuccess: function(transport) {
                    var retval = (transport.responseText).evalJSON();
                    if ((!retval['data']) && (level == 1)) {
                        retval['data'] = 'No matches found.';
                    }
                    $(el_id).update(retval['data']);
                },
                onFailure: function() {
                    alert('Something went wrong. Please try again!');
                },
                onComplete: function() {
                }
            });
        }
    }
    return Sort.get(el_id, options);
}


/* CALENDAR BOX */

var blocks_calendar = new Array();

function blocks_updateCalendar(file, id, event_id, ds, de, direction) {
    if (!file) return false;
    if (!blocks_calendar[id]) blocks_calendar[id] = ds;
    new Ajax.Request(file, {
        method: 'post',
        parameters: {date: blocks_calendar[id], event_id: event_id, ds: ds, de: de, direction: direction},
        onSuccess: function(transport) {
            var retval = (transport.responseText).evalJSON();
            $('div_cb-' +id).update(retval['data']);
            $('link_cb-' +id+ '_prev').update(retval['link_prev']);
            $('link_cb-' +id+ '_next').update(retval['link_next']);
            $('div_cb_container-' +id).show();
            blocks_calendar[id] = retval['newdate'];
        },
        onFailure: function() {
            //alert('Something went wrong. Please try again!');
        },
        onComplete: function() {
        }
    });
    return false;
}

/* REVIEWS */
function getReviews(what, id, div_id, page) {
    if ((what) && (id) && ($(div_id))) {
        new Ajax.Request('/includes/ajax_calls/reviews/reviews.php', {
            method: 'post',
            parameters: {what: what, id: id, div_id: div_id, page: page},
            onSuccess: function(transport) {
                var retval = (transport.responseText).evalJSON();
                $(div_id).update(retval['data']);
            },
            onFailure: function() {
                $(div_id).update('Reviews are not available at this time. Please try again later.');
            },
            onComplete: function() {
            }
        });
    }
}

/* FOOTER FORMS */

var footerForm = Class.create({

    initialize: function() {
        this.ow = '';
        this.opening = false;
    },

    attachClick: function() {
        $$('.page_footer_tab').each(function(item) {
            Event.observe(item, 'click', function() {
                var id = item.readAttribute('id');
                var what = id.substr(4, id.length);
                footerForm.toggle(what);
            });
            item.down('a').writeAttribute('href', 'javascript:void(0);');
            item.down('a').writeAttribute('onclick', 'return false;');
        });
    },

    removeClick: function() {
        $$('.page_footer_tab').each(function(item) {
            Event.stopObserving(item, 'click');
        });
    },

    scrollTo: function(what) {
        this.toggle(what);
        new Effect.ScrollTo('page_footer');
        return false;
    },

    toggle: function(what) {
        this.removeClick();
        if (!this.ow) {
            this.load(what);
        } else {
            if (what == this.ow) {
                this.close(what);
            } else {
                this.close(this.ow, what);
            }
        }
    },

    load: function(what) {
        this.getForm(what, true);
    },

    open: function(what) {
        var thisObj = this;

        this.ow = what;

        new Effect.Morph('pft_' +what, {
            style: 'padding-top: 13px;',
            duration: 0.5
        });

        new Effect.SlideDown('page_footer_form_slider', {
            duration: 1.2,
            transition: Effect.Transitions.Bounce,
            afterFinish: function() {
                new Effect.ScrollTo('page_footer');
                thisObj.attachClick();
            }
        });

    },

    close: function(what, next) {
        var thisObj = this;

        this.ow = '';

        new Effect.Morph('pft_' +what, {
            style: 'padding-top: 0px;',
            duration: 0.5
        });

        new Effect.SlideUp('page_footer_form_slider', {
            duration: 1.2,
            transition: Effect.Transitions.Bounce,
            afterFinish: function() {
                if (next) {
                    thisObj.load(next);
                } else {
                    thisObj.attachClick();
                }
            }
        });

    },

    getForm: function(what, openform) {
        var thisObj = this;

        new Ajax.Request('/includes/ajax_calls/layout/footer_form.php', {
            method: 'post',
            parameters: {form: what},
            onSuccess: function(transport) {
                var retval = (transport.responseText).evalJSON();
                $('page_footer_form_content').update(retval['data']);
                if (openform) thisObj.open(what);
            },
            onFailure: function() {
                alert('Something went wrong. Please try again!');
            },
            onComplete: function() {
            }
        });

    },

    submitForm: function(el) {
        var thisObj = this;

        new Ajax.Request('/includes/ajax_calls/layout/footer_form-process.php', {
            method: 'post',
            parameters: el.serialize()+ '&url=' +window.location.href,
            onSuccess: function(transport) {
                var retval = (transport.responseText).evalJSON();
                if (!retval['err']) {
                    Effect.Fade('page_footer_form_content', {
                        duration: .3,
                        afterFinish: function() {
                            $('page_footer_form_content').update(retval['data']);
                            Effect.Appear('page_footer_form_content', {duration: .3});
                        }
                    });
                } else {
                    alert(retval['data']);
                }
            },
            onFailure: function() {
                alert('Something went wrong. Please try again!');
            },
            onComplete: function() {
            }
        });

        return false;

    }

});

var footerForm = new footerForm();


// LOG ALL EXTERNAL LINK CLICKS TO GOOGLE ANALYTICS
Event.observe(document, 'click', function(event) {
    var element = event.element();
    if ((element.match('img')) && (element.up().match('a'))) {
        element = element.up();
    }
    if (element.match('a')) {
        var href = element.readAttribute('href');
        var host = window.location.host;
        if ((href.match(/^http/)) && (host != href.substring(7, href.indexOf('/', 7)))) {
            //var url = href.replace('http://', '').replace(/[^a-z|A-Z]/g, '_');
            var url = href.replace('http://', '').replace('/', '+');
            if (url.charAt((url.length - 1)) == '/') {
                url = url.substring(0, (url.length - 1));
            }
            var loc = window.location.toString();
            var dir = loc.replace('http://' +host, '');
            var str = dir+ 'exlink/' +url;
            //pageTracker._trackPageview(str);
            _gaq.push(['_trackPageview', str]);
        }
    }
});


// WINDOW LOAD
//document.observe('dom:loaded', function() {
Event.observe(window, 'load', function() {

    // ATTACH CLICK EVENT TO FOOTER TABS
    footerForm.attachClick();

    // HEADER SEARCH AUTOCOMPLETE
    new Autocomplete('header_query', {
        serviceUrl: '/includes/ajax_calls/layout/header_autocomplete.php',
        minChars: 2,
        deferRequestBy: 300,
        width: 234,
        maxHeight: 305,
        onSelect: function(value, data) {
            if (data) window.location.href = data;
        }
    });

    // SHOW ACCOUNT INFO IN HEADER
    topAccountInfo();

    // GET WEATHER FOR HEADER
    getTopWeather(0, false);

});

ypSlideOutMenu.Registry = []
ypSlideOutMenu.aniLen = 250
ypSlideOutMenu.hideDelay = 150
ypSlideOutMenu.minCPUResolution = 10

// constructor
function ypSlideOutMenu(id, dir, left, top, width, height) {
	this.ie  = document.all ? 1 : 0
	this.ns4 = document.layers ? 1 : 0
	this.dom = document.getElementById ? 1 : 0
	this.css = "";
	if (this.ie || this.ns4 || this.dom) {
		this.id			 = id
		this.dir		 = dir
		this.orientation = dir == "left" || dir == "right" ? "h" : "v"
		this.dirType	 = dir == "right" || dir == "down" ? "-" : "+"
		this.dim		 = this.orientation == "h" ? width : height
		this.hideTimer	 = false
		this.aniTimer	 = false
		this.open		 = false
		this.over		 = false
		this.startTime	 = 0
		// global reference to this object
		this.gRef = "ypSlideOutMenu_"+id
		eval(this.gRef+"=this")
		// add this menu object to an internal list of all menus
		ypSlideOutMenu.Registry[id] = this
		var d = document
		var strCSS = "";
		strCSS += '#' + this.id + 'Container { visibility:hidden; '
		strCSS += 'left:' + left + 'px; '
		strCSS += 'top:' + top + 'px; '
		strCSS += 'overflow:hidden; z-index:10000; }'
		strCSS += '#' + this.id + 'Container, #' + this.id + 'Content { position:absolute; '
		strCSS += 'width:' + width + 'px; '
		strCSS += 'height:' + height + 'px; '
		strCSS += 'clip:rect(0 ' + width + ' ' + height + ' 0); '
		strCSS += '}'
		this.css = strCSS;
		this.load();
	}
}

ypSlideOutMenu.writeCSS = function() {
	document.writeln('<style type="text/css">');
	for (var id in ypSlideOutMenu.Registry) {
		if (ypSlideOutMenu.Registry[id].css) document.writeln(ypSlideOutMenu.Registry[id].css);
	}
	document.writeln('</style>');
}

ypSlideOutMenu.prototype.load = function() {
	var d = document
	var lyrId1 = this.id + "Container"
	var lyrId2 = this.id + "Content"
	var obj1 = this.dom ? d.getElementById(lyrId1) : this.ie ? d.all[lyrId1] : d.layers[lyrId1]
	if (obj1) var obj2 = this.ns4 ? obj1.layers[lyrId2] : this.ie ? d.all[lyrId2] : d.getElementById(lyrId2)
	var temp
	if (!obj1 || !obj2) window.setTimeout(this.gRef + ".load()", 100)
	else {
		this.container	= obj1
		this.menu		= obj2
		this.style		= this.ns4 ? this.menu : this.menu.style
		this.homePos	= eval("0" + this.dirType + this.dim)
		this.outPos		= 0
		this.accelConst	= (this.outPos - this.homePos) / ypSlideOutMenu.aniLen / ypSlideOutMenu.aniLen
		// set event handlers.
		if (this.ns4) this.menu.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
		this.menu.onmouseover = new Function("ypSlideOutMenu.showMenu('" + this.id + "')")
		this.menu.onmouseout = new Function("ypSlideOutMenu.hideMenu('" + this.id + "')")
		//set initial state
		this.endSlide();
	}
}

ypSlideOutMenu.showMenu = function(id) {
	var reg = ypSlideOutMenu.Registry
	var obj = ypSlideOutMenu.Registry[id]
	if (obj.container) {
		obj.over = true
		// close other menus.
		for (menu in reg) {
			if (id != menu) {
				ypSlideOutMenu.hide(menu)
			}
		}
		// if this menu is scheduled to close, cancel it.
		if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer) }
		// if this menu is closed, open it.
		if (!obj.open && !obj.aniTimer) {
			obj.opener = window.setTimeout(openMenu, 200);
		}
	}
	function openMenu() {
		reg[id].startSlide(true);
	}
    $(id).addClassName('hover');
}

ypSlideOutMenu.hideMenu = function(id) {
	// schedules the menu to close after <hideDelay> ms, which
	// gives the user time to cancel the action if they accidentally moused out
	var obj = ypSlideOutMenu.Registry[id];
	window.clearTimeout(obj.opener);
	if (obj.container) {
		if (obj.hideTimer) window.clearTimeout(obj.hideTimer)
		obj.hideTimer = window.setTimeout("ypSlideOutMenu.hide('" + id + "')", ypSlideOutMenu.hideDelay);
	}
    if (!$(id).hasClassName('curpage')) $(id).removeClassName('hover');
}

ypSlideOutMenu.hideAll = function() {
	var reg = ypSlideOutMenu.Registry
	for (menu in reg) {
		ypSlideOutMenu.hide(menu);
		if (menu.hideTimer) window.clearTimeout(menu.hideTimer);
	}
}

ypSlideOutMenu.hide = function(id) {
	var obj = ypSlideOutMenu.Registry[id]
	obj.over = false
	if (obj.hideTimer) window.clearTimeout(obj.hideTimer)
	// flag that this scheduled event has occured.
	obj.hideTimer = 0
	// if this menu is open, close it.
	if (obj.open && !obj.aniTimer) obj.startSlide(false)
}

ypSlideOutMenu.prototype.startSlide = function(open) {
	this[open ? "onactivate" : "ondeactivate"]()
	this.open = open
	if (open) this.setVisibility(true)
	this.startTime = (new Date()).getTime()
	this.aniTimer = window.setInterval(this.gRef + ".slide()", ypSlideOutMenu.minCPUResolution)
}

ypSlideOutMenu.prototype.slide = function() {
	var elapsed = (new Date()).getTime() - this.startTime
	if (elapsed > ypSlideOutMenu.aniLen) this.endSlide()
	else {
		var d = Math.round(Math.pow(ypSlideOutMenu.aniLen-elapsed, 2) * this.accelConst)
		if (this.open && this.dirType == "-")		d = -d
		else if (this.open && this.dirType == "+")	d = -d
		else if (!this.open && this.dirType == "-")	d = -this.dim + d
		else										d = this.dim + d
		this.moveTo(d)
	}
}

ypSlideOutMenu.prototype.endSlide = function() {
	this.aniTimer = window.clearTimeout(this.aniTimer)
	this.moveTo(this.open ? this.outPos : this.homePos)
	if (!this.open) this.setVisibility(false)
	if ((this.open && !this.over) || (!this.open && this.over)) {
		this.startSlide(this.over)
	}
}

ypSlideOutMenu.prototype.setVisibility = function(bShow) {
	var s = this.ns4 ? this.container : this.container.style
	s.visibility = bShow ? "visible" : "hidden"
}

ypSlideOutMenu.prototype.moveTo = function(p) {
	this.style[this.orientation == "h" ? "left" : "top"] = this.ns4 ? p : p + "px"
}

ypSlideOutMenu.prototype.getPos = function(c) {
	return parseInt(this.style[c])
}

// events
ypSlideOutMenu.prototype.onactivate		= function() { }
ypSlideOutMenu.prototype.ondeactivate	= function() { }




function keepOpen(id) {
    $(id).setStyle({
        backgroundPosition: '0 0'
    });
}

/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();

/*
 *
 *  Ajax Autocomplete for Prototype, version 1.0.3
 *  (c) 2008 Tomas Kirda
 *
 *  Ajax Autocomplete for Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the web site: http://www.devbridge.com/projects/autocomplete/
 *
 */

var Autocomplete = function(el, options){
  this.el = $(el);
  this.id = this.el.identify();
  this.el.setAttribute('autocomplete','off');
  this.suggestions = [];
  this.data = [];
  this.badQueries = [];
  this.selectedIndex = -1;
  this.currentValue = this.el.value;
  this.intervalId = 0;
  this.cachedResponse = [];
  this.instanceId = null;
  this.onChangeInterval = null;
  this.ignoreValueChange = false;
  this.serviceUrl = options.serviceUrl;
  this.options = {
    autoSubmit:false,
    minChars:1,
    maxHeight:305,
    deferRequestBy:0,
    width:0,
    container:null
  };
  if(options){ Object.extend(this.options, options); }
  if(Autocomplete.isDomLoaded){
    this.initialize();
  }else{
    Event.observe(document, 'dom:loaded', this.initialize.bind(this), false);
  }
};

Autocomplete.instances = [];
Autocomplete.isDomLoaded = false;

Autocomplete.getInstance = function(id){
  var instances = Autocomplete.instances;
  var i = instances.length;
  while(i--){ if(instances[i].id === id){ return instances[i]; }}
};

Autocomplete.highlight = function(value, re){
  return value.replace(re, function(match){ return '<strong>' + match + '<\/strong>' });
};

Autocomplete.prototype = {

  killerFn: null,

  initialize: function() {
    var me = this;
    this.killerFn = function(e) {
      if (!$(Event.element(e)).up('.autocomplete')) {
        me.killSuggestions();
        me.disableKillerFn();
      }
    } .bindAsEventListener(this);

    if (!this.options.width) { this.options.width = this.el.getWidth(); }

    var div = new Element('div', { style: 'position: absolute; z-index: 8850;' });
    div.update('<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_' + this.id + '" style="display:none; width:' + this.options.width + 'px;"></div></div></div>');

    this.options.container = $(this.options.container);
    if (this.options.container) {
      this.options.container.appendChild(div);
      this.fixPosition = function() { };
    } else {
      document.body.appendChild(div);
    }

    this.mainContainerId = div.identify();
    this.container = $('Autocomplete_' + this.id);
    this.fixPosition();

    Event.observe(this.el, window.opera ? 'keypress':'keydown', this.onKeyPress.bind(this));
    Event.observe(this.el, 'keyup', this.onKeyUp.bind(this));
    Event.observe(this.el, 'blur', this.enableKillerFn.bind(this));
    Event.observe(this.el, 'focus', this.fixPosition.bind(this));
    this.container.setStyle({ maxHeight: this.options.maxHeight + 'px' });
    this.instanceId = Autocomplete.instances.push(this) - 1;
  },

  fixPosition: function() {
    var offset = this.el.cumulativeOffset();
    $(this.mainContainerId).setStyle({ top: (offset.top + this.el.getHeight()) + 'px', left: offset.left + 'px' });
  },

  enableKillerFn: function() {
    Event.observe(document.body, 'click', this.killerFn);
  },

  disableKillerFn: function() {
    Event.stopObserving(document.body, 'click', this.killerFn);
  },

  killSuggestions: function() {
    this.stopKillSuggestions();
    this.intervalId = window.setInterval(function() { this.hide(); this.stopKillSuggestions(); } .bind(this), 300);
  },

  stopKillSuggestions: function() {
    window.clearInterval(this.intervalId);
  },

  onKeyPress: function(e) {
    if (!this.enabled) { return; }
    // return will exit the function
    // and event will not fire
    switch (e.keyCode) {
      case Event.KEY_ESC:
        this.el.value = this.currentValue;
        this.hide();
        break;
      case Event.KEY_TAB:
      case Event.KEY_RETURN:
        if (this.selectedIndex === -1) {
          this.hide();
          return;
        }
        this.select(this.selectedIndex);
        if (e.keyCode === Event.KEY_TAB) { return; }
        break;
      case Event.KEY_UP:
        this.moveUp();
        break;
      case Event.KEY_DOWN:
        this.moveDown();
        break;
      default:
        return;
    }
    Event.stop(e);
  },

  onKeyUp: function(e) {
    switch (e.keyCode) {
      case Event.KEY_UP:
      case Event.KEY_DOWN:
        return;
    }
    clearInterval(this.onChangeInterval);
    if (this.currentValue !== this.el.value) {
      if (this.options.deferRequestBy > 0) {
        // Defer lookup in case when value changes very quickly:
        this.onChangeInterval = setInterval((function() {
          this.onValueChange();
        }).bind(this), this.options.deferRequestBy);
      } else {
        this.onValueChange();
      }
    }
  },

  onValueChange: function() {
    clearInterval(this.onChangeInterval);
    this.currentValue = this.el.value;
    this.selectedIndex = -1;
    if (this.ignoreValueChange) {
      this.ignoreValueChange = false;
      return;
    }
    if (this.currentValue === '' || this.currentValue.length < this.options.minChars) {
      this.hide();
    } else {
      this.getSuggestions();
    }
  },

  getSuggestions: function() {
    var cr = this.cachedResponse[this.currentValue];
    if (cr && Object.isArray(cr.suggestions)) {
      this.suggestions = cr.suggestions;
      this.data = cr.data;
      this.suggest();
    } else if (!this.isBadQuery(this.currentValue)) {
      new Ajax.Request(this.serviceUrl, {
        parameters: { query: this.currentValue },
        onComplete: this.processResponse.bind(this),
        method: 'get'
      });
    }
  },

  isBadQuery: function(q) {
    var i = this.badQueries.length;
    while (i--) {
      if (q.indexOf(this.badQueries[i]) === 0) { return true; }
    }
    return false;
  },

  hide: function() {
    this.enabled = false;
    this.selectedIndex = -1;
    this.container.hide();
  },

  suggest: function() {
    if (this.suggestions.length === 0) {
      this.hide();
      return;
    }
    var content = [];
    var re = new RegExp('\\b' + this.currentValue.match(/\w+/g).join('|\\b'), 'gi');
    this.suggestions.each(function(value, i) {
      content.push((this.selectedIndex === i ? '<div class="selected"' : '<div'), ' title="', value, '" onclick="Autocomplete.instances[', this.instanceId, '].select(', i, ');" onmouseover="Autocomplete.instances[', this.instanceId, '].activate(', i, ');">', Autocomplete.highlight(value, re), '</div>');
    } .bind(this));
    this.enabled = true;
    this.container.update(content.join('')).show();
  },

  processResponse: function(xhr) {
    var response;
    try {
      response = xhr.responseText.evalJSON();
      if (!Object.isArray(response.data)) { response.data = []; }
    } catch (err) { return; }
    this.suggestions = response.suggestions;
    this.data = response.data;
    this.cachedResponse[response.query] = response;
    if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
    if (response.query === this.currentValue) { this.suggest(); }
  },

  activate: function(index) {
    var divs = this.container.childNodes;
    var activeItem;
    // Clear previous selection:
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      divs[this.selectedIndex].className = '';
    }
    this.selectedIndex = index;
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      activeItem = divs[this.selectedIndex]
      activeItem.className = 'selected';
    }
    return activeItem;
  },

  deactivate: function(div, index) {
    div.className = '';
    if (this.selectedIndex === index) { this.selectedIndex = -1; }
  },

  select: function(i) {
    var selectedValue = this.suggestions[i];
    if (selectedValue) {
      this.el.value = selectedValue;
      if (this.options.autoSubmit && this.el.form) {
        this.el.form.submit();
      }
      this.ignoreValueChange = true;
      this.hide();
      this.onSelect(i);
    }
  },

  moveUp: function() {
    if (this.selectedIndex === -1) { return; }
    if (this.selectedIndex === 0) {
      this.container.childNodes[0].className = '';
      this.selectedIndex = -1;
      this.el.value = this.currentValue;
      return;
    }
    this.adjustScroll(this.selectedIndex - 1);
  },

  moveDown: function() {
    if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
    this.adjustScroll(this.selectedIndex + 1);
  },

  adjustScroll: function(i) {
    var container = this.container;
    var activeItem = this.activate(i);
    var offsetTop = activeItem.offsetTop;
    var upperBound = container.scrollTop;
    var lowerBound = upperBound + this.options.maxHeight - 25;
    if (offsetTop < upperBound) {
      container.scrollTop = offsetTop;
    } else if (offsetTop > lowerBound) {
      container.scrollTop = offsetTop - this.options.maxHeight + 25;
    }
    this.el.value = this.suggestions[i];
  },

  onSelect: function(i) {
    (this.options.onSelect || Prototype.emptyFunction)(this.suggestions[i], this.data[i]);
  }

};

Event.observe(document, 'dom:loaded', function(){ Autocomplete.isDomLoaded = true; }, false);


eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('A m={11:{9I:\'aw\',ay:\'dA...\',az:\'95 2e dz\',bB:\'95 2e dy 2e dw\',8G:\'dx 2e dB I (f)\',cx:\'dC by <i>a8 a9</i>\',cf:\'dG 2e dF a8 a9 dD\',92:\'a4\',90:\'a5\',9a:\'ac\',9j:\'ab\',9k:\'ab (dv)\',a0:\'du\',ag:\'a7\',ae:\'a7 1p (a2)\',9Z:\'a6\',ao:\'a6 1p (a2)\',93:\'a4 (94 W)\',8X:\'a5 (94 3g)\',91:\'ac\',9T:\'1:1\',3I:\'dl %1 dj %2\',9v:\'95 2e 2d 2L, do al dp 2e 3D. dt 94 dr P 1G al 31.\'},54:\'M/dH/\',8p:\'dI.5g\',5P:\'e2.5g\',6M:5o,be:5o,5j:15,9o:15,5u:15,6v:15,4f:e1,ax:0.75,9t:L,8t:5,3L:2,e0:3,5Z:1f,c0:\'4z 3g\',c1:1,bi:L,cy:\'dW://M.dZ/\',aJ:L,9A:[\'a\',\'4U\'],3j:[],ct:5o,4o:0,8y:50,6O:1f,7X:L,4u:L,3M:\'69\',8F:L,3Z:\'22\',7F:\'22\',9U:H,9Q:H,8P:L,4B:an,5y:an,5W:L,1U:\'e4-e8\',7k:\'M-Q\',96:{2U:\'<O 1Z="M-2U"><68>\'+\'<1K 1Z="M-31">\'+\'<a 21="#" 2k="{m.11.93}">\'+\'<1A>{m.11.92}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-3N">\'+\'<a 21="#" 2k="{m.11.ae}">\'+\'<1A>{m.11.ag}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-3i">\'+\'<a 21="#" 2k="{m.11.ao}">\'+\'<1A>{m.11.9Z}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-1G">\'+\'<a 21="#" 2k="{m.11.8X}">\'+\'<1A>{m.11.90}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-3D">\'+\'<a 21="#" 2k="{m.11.91}">\'+\'<1A>{m.11.9a}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-1c-2H">\'+\'<a 21="#" 2k="{m.11.8G}">\'+\'<1A>{m.11.9T}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-2d">\'+\'<a 21="#" 2k="{m.11.9k}" >\'+\'<1A>{m.11.9j}</1A></a>\'+\'</1K>\'+\'</68></O>\',aZ:\'<O 1Z="M-dU"><68>\'+\'<1K 1Z="M-31">\'+\'<a 21="#" 2k="{m.11.93}" 2n="D m.31(k)">\'+\'<1A>{m.11.92}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-1G">\'+\'<a 21="#" 2k="{m.11.8X}" 2n="D m.1G(k)">\'+\'<1A>{m.11.90}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-3D">\'+\'<a 21="#" 2k="{m.11.91}" 2n="D 1f">\'+\'<1A>{m.11.9a}</1A></a>\'+\'</1K>\'+\'<1K 1Z="M-2d">\'+\'<a 21="#" 2k="{m.11.9k}" 2n="D m.2d(k)">\'+\'<1A>{m.11.9j}</1A></a>\'+\'</1K>\'+\'</68></O>\'+\'<O 1Z="M-1i"></O>\'+\'<O 1Z="M-dK"><O>\'+\'<1A 1Z="M-3R" 2k="{m.11.a0}"><1A></1A></1A>\'+\'</O></O>\'},5O:[],8d:L,18:[],8c:[\'5W\',\'3G\',\'3Z\',\'7F\',\'9U\',\'9Q\',\'1U\',\'3L\',\'di\',\'dT\',\'dS\',\'9S\',\'dR\',\'dQ\',\'e9\',\'9R\',\'8P\',\'4a\',\'5t\',\'3j\',\'4o\',\'K\',\'N\',\'8k\',\'6O\',\'7X\',\'4u\',\'dg\',\'cN\',\'cM\',\'2K\',\'8F\',\'4c\',\'56\',\'3M\',\'85\',\'7k\',\'4B\',\'5y\',\'au\',\'cL\',\'2N\',\'2P\',\'cj\',\'b8\',\'1m\'],1S:[],6r:0,7L:{x:[\'bm\',\'W\',\'4w\',\'3g\',\'bn\'],y:[\'5s\',\'V\',\'8L\',\'4z\',\'7o\']},6Y:{},9R:{},9S:{},85:{af:{},2p:{},a1:{}},48:[],6d:[],4r:{},4g:[],7r:[],4V:[],72:{},9p:{},4m:9i((5i.7A.5H().2q(/.+(?:b7|cO|cP|1x)[\\/: ]([\\d.]+)/)||[0,\'0\'])[1]),1x:(1d.63&&!1T.3S),55:/cs/.1b(5i.7A),5V:/cS.+b7:1\\.[0-8].+cJ/.1b(5i.7A),$:C(1B){q(1B)D 1d.8Z(1B)},2w:C(2a,3p){2a[2a.Y]=3p},16:C(aU,42,44,64,aV){A el=1d.16(aU);q(42)m.3T(el,42);q(aV)m.R(el,{7Z:0,86:\'1s\',8s:0});q(44)m.R(el,44);q(64)64.1X(el);D el},3T:C(el,42){P(A x 3h 42)el[x]=42[x];D el},R:C(el,44){P(A x 3h 44){q(m.1x&&x==\'1v\'){q(44[x]>0.99)el.E.cD(\'5Q\');J el.E.5Q=\'aN(1v=\'+(44[x]*2Q)+\')\'}J el.E[x]=44[x]}},24:C(el,1z,3s){A 4i,4b,4D;q(1I 3s!=\'6P\'||3s===H){A 2J=bA;3s={4d:2J[2],2P:2J[3],7l:2J[4]}}q(1I 3s.4d!=\'3I\')3s.4d=5o;3s.2P=1l[3s.2P]||1l.aL;3s.6T=m.3T({},1z);P(A 35 3h 1z){A e=1L m.28(el,3s,35);4i=9i(m.8n(el,35))||0;4b=9i(1z[35]);4D=35!=\'1v\'?\'F\':\'\';e.3z(4i,4b,4D)}},8n:C(el,1z){q(1d.7J){D 1d.7J.bx(el,H).bz(1z)}J{q(1z==\'1v\')1z=\'5Q\';A 3p=el.6a[1z.29(/\\-(\\w)/g,C(a,b){D b.b1()})];q(1z==\'5Q\')3p=3p.29(/aN\\(1v=([0-9]+)\\)/,C(a,b){D b/2Q});D 3p===\'\'?1:3p}},73:C(){A d=1d,w=1T,46=d.8I&&d.8I!=\'c4\'?d.5h:d.1i;A b=d.1i;A b6=(w.78&&w.ap)?w.78+w.ap:1l.2T(b.aQ,b.1C),b3=(w.77&&1T.aP)?w.77+w.aP:1l.2T(b.aX,b.1M),7m=m.1x?46.aQ:(d.5h.9h||5k.78),7w=m.1x?1l.2T(46.aX,46.9c):(d.5h.9c||5k.77);A K=m.1x?46.9h:(d.5h.9h||5k.78),N=m.1x?46.9c:5k.77;D{7m:1l.2T(7m,b6),7w:1l.2T(7w,b3),K:K,N:N,6z:m.1x?46.6z:da,6l:m.1x?46.6l:d8}},7a:C(el){q(/4U/i.1b(el.3J)){A 6I=1d.2B(\'1O\');P(A i=0;i<6I.Y;i++){A u=6I[i].d7;q(u&&u.29(/^.*?#/,\'\')==el.26.35){el=6I[i];4S}}}A p={x:el.4A,y:el.80};57(el.aY){el=el.aY;p.x+=el.4A;p.y+=el.80;q(el!=1d.1i&&el!=1d.5h){p.x-=el.6z;p.y-=el.6l}}D p},2H:C(a,2p,3z,Z){q(!a)a=m.16(\'a\',H,{1n:\'1s\'},m.2c);q(1I a.5z==\'C\')D 2p;q(Z==\'3w\'){P(A i=0;i<m.4g.Y;i++){q(m.4g[i]&&m.4g[i].a==a){m.4g[i].b9();m.4g[i]=H;D 1f}}m.aD=L}1E{1L m.67(a,2p,3z,Z);D 1f}1D(e){D L}},9z:C(a,2p,3z){D m.2H(a,2p,3z,\'3w\')},8l:C(){D m.16(\'O\',{19:\'M-3w-T\',2h:m.97(m.96.aZ)})},4G:C(el,3J,19){A 1j=el.2B(3J);P(A i=0;i<1j.Y;i++){q((1L 4I(19)).1b(1j[i].19)){D 1j[i]}}D H},97:C(s){s=s.29(/\\s/g,\' \');A 2l=/{m\\.11\\.([^}]+)\\}/g,6b=s.2q(2l),11;q(6b)P(A i=0;i<6b.Y;i++){11=6b[i].29(2l,"$1");q(1I m.11[11]!=\'1W\')s=s.29(6b[i],m.11[11])}D s},7B:C(){A 1j=1d.2B(\'a\');P(A i=0;i<1j.Y;i++){A Z=m.aM(1j[i]);q(Z&&!1j[i].b0){(C(){A t=Z;q(m.1y(m,\'df\',{6q:1j[i],Z:t})){1j[i].2n=(Z==\'2L\')?C(){D m.2H(k)}:C(){D m.9z(k,{2K:t})}}})();1j[i].b0=L}}q(!m.aR)3P(m.7B,50);J q(i)m.79()},aM:C(el){q(el.7s==\'M\')D\'2L\';J q(el.7s==\'M-30\')D\'30\';J q(el.7s==\'M-1g\')D\'1g\';J q(el.7s==\'M-3t\')D\'3t\'},8m:C(a){P(A i=0;i<m.4V.Y;i++){q(m.4V[i][0]==a){A c=m.4V[i][1];m.4V[i][1]=c.58(1);D c}}D H},aK:C(e){A 2a=m.6m();P(A i=0;i<2a.4R.Y;i++){A a=2a.4R[i];q(m.41(a,\'2K\')==\'30\'&&m.41(a,\'8F\'))m.2w(m.7r,a)}m.8B(0)},8B:C(i){q(!m.7r[i])D;A a=m.7r[i];A 5E=m.6c(m.41(a,\'8k\'));q(!5E)5E=m.8l();A 30=1L m.6K(a,5E,1);30.9d=C(){};30.3B=C(){m.2w(m.4V,[a,5E]);m.8B(i+1)};30.9g()},aH:C(){A 8A=0,7x=-1,18=m.18,B,1F;P(A i=0;i<18.Y;i++){B=18[i];q(B){1F=B.Q.E.1F;q(1F&&1F>8A){8A=1F;7x=i}}}q(7x==-1)m.3e=-1;J 18[7x].3V()},41:C(a,5C){a.5z=a.2n;A p=a.5z?a.5z():H;a.5z=H;D(p&&1I p[5C]!=\'1W\')?p[5C]:(1I m[5C]!=\'1W\'?m[5C]:H)},6L:C(a){A 1m=m.41(a,\'1m\');q(1m)D 1m;D a.21},6c:C(1B){A 1N=m.$(1B),4t=m.9p[1B],a={};q(!1N&&!4t)D H;q(!4t){4t=1N.58(L);4t.1B=\'\';m.9p[1B]=4t;D 1N}J{D 4t.58(L)}},51:C(d){m.9E.1X(d);m.9E.2h=\'\'},1H:C(B){q(!m.2D){m.2D=m.16(\'O\',{19:\'M-cZ\',5x:\'\',2n:C(){q(m.1y(m,\'d0\'))m.2d()}},{1k:\'2m\',1o:\'2b\',W:0,1v:0},m.2c,L);m.2z(1T,\'3R\',m.5f)}m.2D.E.1n=\'\';m.5f();m.2D.5x+=\'|\'+B.S;q(m.5V&&m.at)m.R(m.2D,{76:\'6t(\'+m.54+\'d4.aj)\',1v:1});J m.24(m.2D,{1v:B.4o},m.8y)},8V:C(S){q(!m.2D)D;q(1I S!=\'1W\')m.2D.5x=m.2D.5x.29(\'|\'+S,\'\');q((1I S!=\'1W\'&&m.2D.5x!=\'\')||(m.2t&&m.41(m.2t,\'4o\')))D;q(m.5V&&m.at)m.R(m.2D,{76:\'1s\',K:0,N:0});J m.24(m.2D,{1v:0},m.8y,H,C(){m.R(m.2D,{1n:\'1s\',K:0,N:0})})},5f:C(B){q(!m.2D)D;A h=(m.1x&&B&&B.Q)?2r(B.Q.E.V)+2r(B.Q.E.N)+(B.1a?B.1a.1q:0):0;m.R(m.2D,{K:m.3n.7m+\'F\',N:1l.2T(m.3n.7w,h)+\'F\'})},8x:C(5a,B){A 1e=B=B||m.3d();q(m.2t)D 1f;J m.1e=1e;1E{m.2t=5a;5a.2n()}1D(e){m.1e=m.2t=H}1E{q(!5a||B.3j[1]!=\'47\')B.2d()}1D(e){}D 1f},6o:C(el,2o){A B=m.3d(el);q(B){5a=B.89(2o);D m.8x(5a,B)}J D 1f},31:C(el){D m.6o(el,-1)},1G:C(el){D m.6o(el,1)},6F:C(e){q(!e)e=1T.2G;q(!e.2Z)e.2Z=e.9L;q(1I e.2Z.aC!=\'1W\')D L;q(!m.1y(m,\'d2\',e))D L;A B=m.3d();A 2o=H;aS(e.d1){2g 70:q(B)B.6V();D L;2g 32:2o=2;4S;2g 34:2g 39:2g 40:2o=1;4S;2g 8:2g 33:2g 37:2g 38:2o=-1;4S;2g 27:2g 13:2o=0}q(2o!==H){q(2o!=2)m.53(1d,1T.3S?\'9x\':\'9C\',m.6F);q(!m.aJ)D L;q(e.5m)e.5m();J e.bo=1f;q(B){q(2o==0){B.2d()}J q(2o==2){q(B.1p)B.1p.bT()}J{q(B.1p)B.1p.3i();m.6o(B.S,2o)}D 1f}}D L},fe:C(14){m.2w(m.1S,m.3T(14,{23:\'23\'+m.6r++}))},fd:C(1t){A 3a=1t.2N;q(1I 3a==\'6P\'){P(A i=0;i<3a.Y;i++){A o={};P(A x 3h 1t)o[x]=1t[x];o.2N=3a[i];m.2w(m.6d,o)}}J{m.2w(m.6d,1t)}},7I:C(6q,6n){A el,2l=/^M-Q-([0-9]+)$/;el=6q;57(el.26){q(el.6D!==1W)D el.6D;q(el.1B&&2l.1b(el.1B))D el.1B.29(2l,"$1");el=el.26}q(!6n){el=6q;57(el.26){q(el.3J&&m.6x(el)){P(A S=0;S<m.18.Y;S++){A B=m.18[S];q(B&&B.a==el)D S}}el=el.26}}D H},3d:C(el,6n){q(1I el==\'1W\')D m.18[m.3e]||H;q(1I el==\'3I\')D m.18[el]||H;q(1I el==\'9O\')el=m.$(el);D m.18[m.7I(el,6n)]||H},6x:C(a){D(a.2n&&a.2n.cp().29(/\\s/g,\' \').2q(/m.(eW|e)f0/))},cd:C(){P(A i=0;i<m.18.Y;i++)q(m.18[i]&&m.18[i].5B)m.aH()},1y:C(5v,8J,2J){D 5v&&5v[8J]?(5v[8J](5v,2J)!==1f):L},9q:C(e){q(!e)e=1T.2G;q(e.f2>1)D L;q(!e.2Z)e.2Z=e.9L;A el=e.2Z;57(el.26&&!(/M-(2L|3D|3w|3R)/.1b(el.19))){el=el.26}A B=m.3d(el);q(B&&(B.6e||!B.5B))D L;q(B&&e.Z==\'7E\'){q(e.2Z.aC)D L;A 2q=el.19.2q(/M-(2L|3D|3R)/);q(2q){m.2F={B:B,Z:2q[1],W:B.x.G,K:B.x.I,V:B.y.G,N:B.y.I,aO:e.6B,aE:e.7g};m.2z(1d,\'6J\',m.6R);q(e.5m)e.5m();q(/M-(2L|3w)-9D/.1b(B.T.19)){B.3V();m.8N=L}D 1f}J q(/M-3w/.1b(el.19)&&m.3e!=B.S){B.3V();B.4Q(\'1r\')}}J q(e.Z==\'aq\'){m.53(1d,\'6J\',m.6R);q(m.2F){q(m.52&&m.2F.Z==\'2L\')m.2F.B.T.E.4l=m.52;A 3r=m.2F.3r;q(!3r&&!m.8N&&!/(3D|3R)/.1b(m.2F.Z)){q(m.1y(B,\'fu\'))B.2d()}J q(3r||(!3r&&m.aD)){m.2F.B.4Q(\'1r\')}q(m.2F.B.3E)m.2F.B.3E.E.1n=\'1s\';q(3r)m.1y(m.2F.B,\'ft\',m.2F);q(3r)m.5f(B);m.8N=1f;m.2F=H}J q(/M-2L-9D/.1b(el.19)){el.E.4l=m.52}}D 1f},6R:C(e){q(!m.2F)D L;q(!e)e=1T.2G;A a=m.2F,B=a.B;q(B.1g){q(!B.3E)B.3E=m.16(\'O\',H,{1k:\'2m\',K:B.x.I+\'F\',N:B.y.I+\'F\',W:B.x.cb+\'F\',V:B.y.cb+\'F\',1F:4,76:(m.1x?\'fv\':\'1s\'),1v:.fr},B.Q,L);q(B.3E.E.1n==\'1s\')B.3E.E.1n=\'\'}a.dX=e.6B-a.aO;a.dY=e.7g-a.aE;A 9K=1l.fi(1l.aG(a.dX,2)+1l.aG(a.dY,2));q(!a.3r)a.3r=(a.Z!=\'2L\'&&9K>0)||(9K>(m.fn||5));q(a.3r&&e.6B>5&&e.7g>5){q(!m.1y(B,\'fm\',a))D 1f;q(a.Z==\'3R\')B.3R(a);J{B.8C(a.W+a.dX,a.V+a.dY);q(a.Z==\'2L\')B.T.E.4l=\'3D\'}}D 1f},aF:C(e){1E{q(!e)e=1T.2G;A 4Y=/f1/i.1b(e.Z);q(!e.2Z)e.2Z=e.9L;q(m.1x)e.9P=4Y?e.er:e.eV;A B=m.3d(e.2Z);q(!B.5B)D;q(!B||!e.9P||m.3d(e.9P,L)==B||m.2F)D;m.1y(B,4Y?\'et\':\'ew\',e);P(A i=0;i<B.1S.Y;i++)(C(){A o=m.$(\'23\'+B.1S[i]);q(o&&o.7v){q(4Y)m.R(o,{1o:\'2b\'});m.24(o,{1v:4Y?o.1v:0},o.2C,H,4Y?H:C(){m.R(o,{1o:\'1r\'})})}})()}1D(e){}},2z:C(el,2G,49){1E{el.2z(2G,49,1f)}1D(e){1E{el.aA(\'6f\'+2G,49);el.en(\'6f\'+2G,49)}1D(e){el[\'6f\'+2G]=49}}},53:C(el,2G,49){1E{el.53(2G,49,1f)}1D(e){1E{el.aA(\'6f\'+2G,49)}1D(e){el[\'6f\'+2G]=H}}},6y:C(i){q(m.8d&&m.5O[i]&&m.5O[i]!=\'1W\'){A 1O=1d.16(\'1O\');1O.4K=C(){1O=H;m.6y(i+1)};1O.1m=m.5O[i]}},aI:C(3I){q(3I&&1I 3I!=\'6P\')m.8t=3I;A 2a=m.6m();P(A i=0;i<2a.4X.Y&&i<m.8t;i++){m.2w(m.5O,m.6L(2a.4X[i]))}q(m.1U)1L m.5n(m.1U,C(){m.6y(0)});J m.6y(0);q(m.5P)A 5g=m.16(\'1O\',{1m:m.54+m.5P})},74:C(){q(!m.2c){m.3n=m.73();m.4P=m.1x&&m.4m<7;m.c9=m.4P&&87.ek==\'ej:\';P(A x 3h m.6E){q(1I m[x]!=\'1W\')m.11[x]=m[x];J q(1I m.11[x]==\'1W\'&&1I m.6E[x]!=\'1W\')m.11[x]=m.6E[x]}m.2c=m.16(\'O\',{19:\'M-2c\'},{1k:\'2m\',W:0,V:0,K:\'2Q%\',1F:m.4f,9H:\'aw\'},1d.1i,L);m.2y=m.16(\'a\',{19:\'M-2y\',2k:m.11.az,2h:m.11.ay,21:\'bZ:;\'},{1k:\'2m\',V:\'-4e\',1v:m.ax,1F:1},m.2c);m.9E=m.16(\'O\',H,{1n:\'1s\'},m.2c);m.36=m.16(\'O\',{19:\'M-36\'},H,m.2c,1);m.3y=m.16(\'O\',H,{aa:\'ar\',eM:\'eL\'},H,L);1l.eP=C(t,b,c,d){D c*t/d+b};1l.aL=C(t,b,c,d){D c*(t/=d)*t+b};1l.8W=C(t,b,c,d){D-c*(t/=d)*(t-2)+b};m.bq=m.4P;m.br=((1T.3S&&m.4m<9)||5i.ch==\'cm\'||(m.1x&&m.4m<5.5));m.1y(k,\'eT\')}},bs:C(){m.av=L;q(m.8g)m.8g()},79:C(){A el,1j,63=[],4X=[],4R=[],3q={},2l;P(A i=0;i<m.9A.Y;i++){1j=1d.2B(m.9A[i]);P(A j=0;j<1j.Y;j++){el=1j[j];2l=m.6x(el);q(2l){m.2w(63,el);q(2l[0]==\'m.2H\')m.2w(4X,el);J q(2l[0]==\'m.9z\')m.2w(4R,el);A g=m.41(el,\'2N\')||\'1s\';q(!3q[g])3q[g]=[];m.2w(3q[g],el)}}}m.4y={63:63,3q:3q,4X:4X,4R:4R};D m.4y},6m:C(){D m.4y||m.79()},2d:C(el){A B=m.3d(el);q(B)B.2d();D 1f}};m.28=C(3c,1t,1z){k.1t=1t;k.3c=3c;k.1z=1z;q(!1t.b5)1t.b5={}};m.28.4O={9y:C(){(m.28.3F[k.1z]||m.28.3F.am)(k);q(k.1t.3F)k.1t.3F.9X(k.3c,k.4C,k)},3z:C(b4,2e,4D){k.9F=(1L 7W()).83();k.4i=b4;k.4b=2e;k.4D=4D;k.4C=k.4i;k.G=k.9s=0;A 5k=k;C t(7u){D 5k.3F(7u)}t.3c=k.3c;q(t()&&m.48.2w(t)==1){m.ai=ez(C(){A 48=m.48;P(A i=0;i<48.Y;i++)q(!48[i]())48.eD(i--,1);q(!48.Y){eH(m.ai)}},13)}},3F:C(7u){A t=(1L 7W()).83();q(7u||t>=k.1t.4d+k.9F){k.4C=k.4b;k.G=k.9s=1;k.9y();k.1t.6T[k.1z]=L;A 9N=L;P(A i 3h k.1t.6T)q(k.1t.6T[i]!==L)9N=1f;q(9N){q(k.1t.7l)k.1t.7l.9X(k.3c)}D 1f}J{A n=t-k.9F;k.9s=n/k.1t.4d;k.G=k.1t.2P(n,0,1,k.1t.4d);k.4C=k.4i+((k.4b-k.4i)*k.G);k.9y()}D L}};m.3T(m.28,{3F:{1v:C(28){m.R(28.3c,{1v:28.4C})},am:C(28){q(28.3c.E&&28.3c.E[28.1z]!=H)28.3c.E[28.1z]=28.4C+28.4D;J 28.3c[28.1z]=28.4C}}});m.5n=C(1U,3B){k.3B=3B;k.1U=1U;A v=m.4m,3X;k.7G=m.1x&&v>=5.5&&v<7;q(!1U){q(3B)3B();D}m.74();k.2i=m.16(\'2i\',{ey:0},{1o:\'1r\',1k:\'2m\',ex:\'eh\',K:0},m.2c,L);A 4q=m.16(\'4q\',H,H,k.2i,1);k.2I=[];P(A i=0;i<=8;i++){q(i%3==0)3X=m.16(\'3X\',H,{N:\'22\'},4q,L);k.2I[i]=m.16(\'2I\',H,H,3X,L);A E=i!=4?{eb:0,ed:0}:{1k:\'4v\'};m.R(k.2I[i],E)}k.2I[4].19=1U+\' M-1a\';k.ak()};m.5n.4O={ak:C(){A 1m=m.54+(m.es||"ep/")+k.1U+".aj";A 9Y=m.55?m.2c:H;k.3H=m.16(\'1O\',H,{1k:\'2m\',V:\'-4e\'},9Y,L);A 3x=k;k.3H.4K=C(){3x.9W()};k.3H.1m=1m},9W:C(){A o=k.1q=k.3H.K/4,G=[[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]],1H={N:(2*o)+\'F\',K:(2*o)+\'F\'};P(A i=0;i<=8;i++){q(G[i]){q(k.7G){A w=(i==1||i==7)?\'2Q%\':k.3H.K+\'F\';A O=m.16(\'O\',H,{K:\'2Q%\',N:\'2Q%\',1k:\'4v\',2s:\'1r\'},k.2I[i],L);m.16(\'O\',H,{5Q:"fp:fq.cc.fk(ff=f3, 1m=\'"+k.3H.1m+"\')",1k:\'2m\',K:w,N:k.3H.N+\'F\',W:(G[i][0]*o)+\'F\',V:(G[i][1]*o)+\'F\'},O,L)}J{m.R(k.2I[i],{76:\'6t(\'+k.3H.1m+\') \'+(G[i][0]*o)+\'F \'+(G[i][1]*o)+\'F\'})}q(1T.3S&&(i==3||i==5))m.16(\'O\',H,1H,k.2I[i],L);m.R(k.2I[i],1H)}}k.3H=H;q(m.4r[k.1U])m.4r[k.1U].65();m.4r[k.1U]=k;q(k.3B)k.3B()},4x:C(G,1q,9V,2C,2P){A B=k.B,3u=B.Q.E,1q=1q||0,G=G||{x:B.x.G+1q,y:B.y.G+1q,w:B.x.U(\'1V\')-2*1q,h:B.y.U(\'1V\')-2*1q};q(9V)k.2i.E.1o=(G.h>=4*k.1q)?\'2b\':\'1r\';m.R(k.2i,{W:(G.x-k.1q)+\'F\',V:(G.y-k.1q)+\'F\',K:(G.w+2*k.1q)+\'F\'});G.w-=2*k.1q;G.h-=2*k.1q;m.R(k.2I[4],{K:G.w>=0?G.w+\'F\':0,N:G.h>=0?G.h+\'F\':0});q(k.7G)k.2I[3].E.N=k.2I[5].E.N=k.2I[4].E.N},65:C(aT){q(aT)k.2i.E.1o=\'1r\';J m.51(k.2i)}};m.6s=C(B,1H){k.B=B;k.1H=1H;k.3f=1H==\'x\'?\'bL\':\'bM\';k.3k=k.3f.5H();k.62=1H==\'x\'?\'bU\':\'bW\';k.6w=k.62.5H();k.7D=1H==\'x\'?\'bQ\':\'bJ\';k.b2=k.7D.5H();k.1h=k.3v=0};m.6s.4O={U:C(S){aS(S){2g\'8r\':D k.1R+k.3l+(k.t-m.2y[\'1q\'+k.3f])/2;2g\'8o\':D k.G+k.cb+k.1h+(k.I-m.2y[\'1q\'+k.3f])/2;2g\'1V\':D k.I+2*k.cb+k.1h+k.3v;2g\'5L\':D k.4n-k.3m-k.4j;2g\'5G\':D k.G-(k.B.1a?k.B.1a.1q:0);2g\'7H\':D k.U(\'1V\')+(k.B.1a?2*k.B.1a.1q:0);2g\'2j\':D k.1Y?1l.4W((k.I-k.1Y)/2):0}},7S:C(){k.cb=(k.B.T[\'1q\'+k.3f]-k.t)/2;k.4j=m[\'8s\'+k.7D]+2*k.cb},8a:C(){k.t=k.B.el[k.3k]?2r(k.B.el[k.3k]):k.B.el[\'1q\'+k.3f];k.1R=k.B.1R[k.1H];k.3l=(k.B.el[\'1q\'+k.3f]-k.t)/2;q(k.1R==0){k.1R=(m.3n[k.3k]/2)+m.3n[\'2f\'+k.62]}},7Q:C(){A B=k.B;k.2O=\'22\';q(B.7F==\'4w\')k.2O=\'4w\';J q(1L 4I(k.6w).1b(B.3Z))k.2O=H;J q(1L 4I(k.b2).1b(B.3Z))k.2O=\'2T\';k.G=k.1R-k.cb+k.3l;k.I=1l.3C(k.1c,B[\'2T\'+k.3f]||k.1c);k.2W=B.5W?1l.3C(B[\'3C\'+k.3f],k.1c):k.1c;q(B.2Y&&B.3G){k.I=B[k.3k];k.1Y=k.1c}q(k.1H==\'x\'&&m.5Z)k.2W=B.4B;k.2Z=B[\'2Z\'+k.1H.b1()];k.3m=m[\'8s\'+k.62];k.2f=m.3n[\'2f\'+k.62];k.4n=m.3n[k.3k]},7i:C(i){A B=k.B;q(B.2Y&&(B.3G||m.5Z)){k.1Y=i;k.I=1l.2T(k.I,k.1Y);B.T.E[k.6w]=k.U(\'2j\')+\'F\'}J k.I=i;B.T.E[k.3k]=i+\'F\';B.Q.E[k.3k]=k.U(\'1V\')+\'F\';q(B.1a)B.1a.4x();q(B.3E)B.3E.E[k.3k]=i+\'F\';q(B.2E){A d=B.2u;q(k.8f===1W)k.8f=B.1w[\'1q\'+k.3f]-d[\'1q\'+k.3f];d.E[k.3k]=(k.I-k.8f)+\'F\';q(k.1H==\'x\')B.3Y.E.K=\'22\';q(B.1i)B.1i.E[k.3k]=\'22\'}q(k.1H==\'x\'&&B.1u)B.5d(L);q(k.1H==\'x\'&&B.1p&&B.2Y){q(i==k.1c)B.1p.4Z(\'1c-2H\');J B.1p.4E(\'1c-2H\')}},9M:C(i){k.G=i;k.B.Q.E[k.6w]=i+\'F\';q(k.B.1a)k.B.1a.4x()}};m.67=C(a,2p,3z,3o){q(1d.9J&&m.1x&&!m.av){m.8g=C(){1L m.67(a,2p,3z,3o)};D}k.a=a;k.3z=3z;k.3o=3o||\'2L\';k.2E=(3o==\'3w\');k.2Y=!k.2E;m.8d=1f;k.1S=[];k.1e=m.1e;m.1e=H;m.74();A S=k.S=m.18.Y;P(A i=0;i<m.8c.Y;i++){A 35=m.8c[i];k[35]=2p&&1I 2p[35]!=\'1W\'?2p[35]:m[35]}q(!k.1m)k.1m=a.21;A el=(2p&&2p.8U)?m.$(2p.8U):a;el=k.aB=el.2B(\'1O\')[0]||el;k.7p=el.1B||a.1B;q(!m.1y(k,\'eY\'))D L;P(A i=0;i<m.18.Y;i++){q(m.18[i]&&m.18[i].a==a&&!(k.1e&&k.3j[1]==\'47\')){m.18[i].3V();D 1f}}P(A i=0;i<m.18.Y;i++){q(m.18[i]&&m.18[i].aB!=el&&!m.18[i].7z){m.18[i].6A()}}m.18[k.S]=k;q(!m.9t&&!m.2t){q(m.18[S-1])m.18[S-1].2d();q(1I m.3e!=\'1W\'&&m.18[m.3e])m.18[m.3e].2d()}k.el=el;k.1R=m.7a(el);m.3n=m.73();A x=k.x=1L m.6s(k,\'x\');x.8a();A y=k.y=1L m.6s(k,\'y\');y.8a();q(/4U/i.1b(el.3J))k.cn(el);k.Q=m.16(\'O\',{1B:\'M-Q-\'+k.S,19:k.7k},{1o:\'1r\',1k:\'2m\',1F:m.4f++},H,L);k.Q.ev=k.Q.eJ=m.aF;q(k.3o==\'2L\'&&k.3L==2)k.3L=0;q(!k.1U||(k.1e&&k.2Y&&k.3j[1]==\'47\')){k[k.3o+\'8b\']()}J q(m.4r[k.1U]){k.8q();k[k.3o+\'8b\']()}J{k.5M();A B=k;1L m.5n(k.1U,C(){B.8q();B[B.3o+\'8b\']()})}D L};m.67.4O={8D:C(e){1T.87.21=k.1m},8q:C(){A 1a=k.1a=m.4r[k.1U];1a.B=k;1a.2i.E.1F=k.Q.E.1F;m.4r[k.1U]=H},5M:C(){q(k.7z||k.2y)D;k.2y=m.2y;A B=k;k.2y.2n=C(){B.6A()};q(!m.1y(k,\'eS\'))D;A B=k,l=k.x.U(\'8r\')+\'F\',t=k.y.U(\'8r\')+\'F\';q(!2S&&k.1e&&k.3j[1]==\'47\')A 2S=k.1e;q(2S){l=2S.x.U(\'8o\')+\'F\';t=2S.y.U(\'8o\')+\'F\';k.2y.E.1F=m.4f++}3P(C(){q(B.2y)m.R(B.2y,{W:l,V:t,1F:m.4f++})},2Q)},ei:C(){A B=k;A 1O=1d.16(\'1O\');k.T=1O;1O.4K=C(){q(m.18[B.S])B.5I()};q(m.ef)1O.ee=C(){D 1f};1O.19=\'M-2L\';m.R(1O,{1o:\'1r\',1n:\'3A\',1k:\'2m\',au:\'4e\',1F:3});1O.2k=m.11.9v;q(m.55)m.2c.1X(1O);q(m.1x&&m.fl)1O.1m=H;1O.1m=k.1m;k.5M()},fj:C(){q(!m.1y(k,\'fo\'))D;k.T=m.8m(k.a);q(!k.T)k.T=m.6c(k.8k);q(!k.T)k.T=m.8l();k.8K([\'7h\']);q(k.7h){A 1i=m.4G(k.T,\'O\',\'M-1i\');q(1i)1i.1X(k.7h);k.7h.E.1n=\'3A\'}m.1y(k,\'eO\');k.1w=k.T;q(/(3t|1g)/.1b(k.2K))k.7Y(k.1w);m.2c.1X(k.Q);m.R(k.Q,{1k:\'dP\',7Z:\'0 \'+m.9o+\'F 0 \'+m.5j+\'F\'});k.T=m.16(\'O\',{19:\'M-3w\'},{1k:\'4v\',1F:3,2s:\'1r\'},k.Q);k.3Y=m.16(\'O\',H,H,k.T,1);k.3Y.1X(k.1w);m.R(k.1w,{1k:\'4v\',1n:\'3A\',9H:m.11.9I||\'\'});q(k.K)k.1w.E.K=k.K+\'F\';q(k.N)k.1w.E.N=k.N+\'F\';q(k.1w.1C<k.4B)k.1w.E.K=k.4B+\'F\';q(k.2K==\'30\'&&!m.8m(k.a)){k.5M();A 30=1L m.6K(k.a,k.1w);A B=k;30.3B=C(){q(m.18[B.S])B.5I()};30.9d=C(){87.21=B.1m};30.9g()}J q(k.2K==\'1g\'&&k.3M==\'69\'){k.6j()}J k.5I()},5I:C(){1E{q(!k.T)D;k.T.4K=H;q(k.7z)D;J k.7z=L;A x=k.x,y=k.y;q(k.2y){m.R(k.2y,{V:\'-4e\'});k.2y=H;m.1y(k,\'cz\')}q(k.2Y){x.1c=k.T.K;y.1c=k.T.N;m.R(k.T,{K:x.t+\'F\',N:y.t+\'F\'});k.Q.1X(k.T);m.2c.1X(k.Q)}J q(k.81)k.81();x.7S();y.7S();m.R(k.Q,{W:(x.1R+x.3l-x.cb)+\'F\',V:(y.1R+x.3l-y.cb)+\'F\'});k.9w();k.bl();A 2V=x.1c/y.1c;x.7Q();k.2O(x);y.7Q();k.2O(y);q(k.2E)k.cr();q(k.1u)k.5d(0,1);q(k.5W){q(k.2Y)k.ci(2V);J k.7V();A 1Q=k.1p;q(1Q&&k.1e&&1Q.2U&&1Q.aW){A G=1Q.cl.1k||\'\',p;P(A 1H 3h m.7L)P(A i=0;i<5;i++){p=k[1H];q(G.2q(m.7L[1H][i])){p.G=k.1e[1H].G+(k.1e[1H].1h-p.1h)+(k.1e[1H].I-p.I)*[0,0,.5,1,1][i];q(1Q.aW==\'d5\'){q(p.G+p.I+p.1h+p.3v>p.2f+p.4n-p.4j)p.G=p.2f+p.4n-p.I-p.3m-p.4j-p.1h-p.3v;q(p.G<p.2f+p.3m)p.G=p.2f+p.3m}}}}q(k.2Y&&k.x.1c>(k.x.1Y||k.x.I)){k.c2();q(k.1S.Y==1)k.5d()}}k.9G()}1D(e){k.8D(e)}},7Y:C(64,22){A c=m.4G(64,\'6W\',\'M-1i\');q(/(1g|3t)/.1b(k.2K)){q(k.4c)c.E.K=k.4c+\'F\';q(k.56)c.E.N=k.56+\'F\'}},6j:C(){q(k.ad)D;A B=k;k.1i=m.4G(k.1w,\'6W\',\'M-1i\');q(k.2K==\'1g\'){k.5M();A 5D=m.3y.58(1);k.1i.1X(5D);k.d9=k.1w.1C;q(!k.4c)k.4c=5D.1C;A 4T=k.1w.1M-k.1i.1M,h=k.56||m.3n.N-4T-m.5u-m.6v,4K=k.3M==\'69\'?\' 4K="q (m.18[\'+k.S+\']) m.18[\'+k.S+\'].5I()" \':\'\';k.1i.2h+=\'<1g 35="m\'+(1L 7W()).83()+\'" cC="0" S="\'+k.S+\'" \'+\' cR="L" E="K:\'+k.4c+\'F; N:\'+h+\'F" \'+4K+\' 1m="\'+k.1m+\'"></1g>\';k.5D=k.1i.2B(\'O\')[0];k.1g=k.1i.2B(\'1g\')[0];q(k.3M==\'60\')k.82()}q(k.2K==\'3t\'){k.1i.1B=k.1i.1B||\'m-dJ-1B-\'+k.S;A a=k.85;q(1I a.2p.ah==\'1W\')a.2p.ah=\'e6\';q(9r)9r.e3(k.1m,k.1i.1B,k.4c,k.56,a.dq||\'7\',a.ds,a.af,a.2p,a.a1)}k.ad=L},81:C(){q(k.1g&&!k.56){k.1g.E.N=k.1i.E.N=k.7N()+\'F\'}k.1w.1X(m.3y);q(!k.x.1c)k.x.1c=k.1w.1C;k.y.1c=k.1w.1M;k.1w.8v(m.3y);q(m.1x&&k.a3>2r(k.1w.6a.N)){k.a3=2r(k.1w.6a.N)}m.R(k.Q,{1k:\'2m\',7Z:\'0\'});m.R(k.T,{K:k.x.t+\'F\',N:k.y.t+\'F\'})},7N:C(){A h;1E{A 2A=k.1g.9b||k.1g.5T.1d;A 3y=2A.16(\'O\');3y.E.aa=\'ar\';2A.1i.1X(3y);h=3y.80;q(m.1x)h+=2r(2A.1i.6a.5u)+2r(2A.1i.6a.6v)-1}1D(e){h=fh}D h},82:C(){A 4M=k.1w.1C-k.5D.1C;q(4M<0)4M=0;A 4T=k.1w.1M-k.1g.1M;m.R(k.1g,{K:(k.x.I-4M)+\'F\',N:(k.y.I-4T)+\'F\'});m.R(k.1i,{K:k.1g.E.K,N:k.1g.E.N});k.59=k.1g;k.2u=k.59},cr:C(){k.7Y(k.1w);q(k.2K==\'3t\'&&k.3M==\'69\')k.6j();q(k.x.I<k.x.1c&&!k.6O)k.x.I=k.x.1c;q(k.y.I<k.y.1c&&!k.7X)k.y.I=k.y.1c;k.2u=k.1w;m.R(k.3Y,{1k:\'4v\',K:k.x.I+\'F\'});m.R(k.1w,{86:\'1s\',K:\'22\',N:\'22\'});A 1N=m.4G(k.1w,\'6W\',\'M-1i\');q(1N&&!/(1g|3t)/.1b(k.2K)){A 5e=1N;1N=m.16(5e.dn,H,{2s:\'1r\'},H,L);5e.26.dm(1N,5e);1N.1X(m.3y);1N.1X(5e);A 4M=k.1w.1C-1N.1C;A 4T=k.1w.1M-1N.1M;1N.8v(m.3y);A 6S=m.55||5i.ch==\'cm\'?1:0;m.R(1N,{K:(k.x.I-4M-6S)+\'F\',N:(k.y.I-4T)+\'F\',2s:\'22\',1k:\'4v\'});q(6S&&5e.1M>1N.1M){1N.E.K=(2r(1N.E.K)+6S)+\'F\'}k.59=1N;k.2u=k.59}q(k.1g&&k.3M==\'69\')k.82();q(!k.59&&k.y.I<k.3Y.1M)k.2u=k.T;q(k.2u==k.T&&!k.6O&&!/(1g|3t)/.1b(k.2K)){k.x.I+=17}q(k.2u&&k.2u.1M>k.2u.26.1M){3P("1E { m.18["+k.S+"].2u.E.2s = \'22\'; } 1D(e) {}",m.6M)}},cn:C(4U){A c=4U.dk.9e(\',\');P(A i=0;i<c.Y;i++)c[i]=2r(c[i]);q(4U.dV.5H()==\'dL\'){k.x.1R+=c[0]-c[2];k.y.1R+=c[1]-c[2];k.x.t=k.y.t=2*c[2]}J{A 5J,61,5S=5J=c[0],5Y=61=c[1];P(A i=0;i<c.Y;i++){q(i%2==0){5S=1l.3C(5S,c[i]);5J=1l.2T(5J,c[i])}J{5Y=1l.3C(5Y,c[i]);61=1l.2T(61,c[i])}}k.x.1R+=5S;k.x.t=5J-5S;k.y.1R+=5Y;k.y.t=61-5Y}},2O:C(p,5c){A 4h,2S=p.2Z,1H=p==k.x?\'x\':\'y\';q(2S&&2S.2q(/ /)){4h=2S.9e(\' \');2S=4h[0]}q(2S&&m.$(2S)){p.G=m.7a(m.$(2S))[1H];q(4h&&4h[1]&&4h[1].2q(/^[-]?[0-9]+F$/))p.G+=2r(4h[1]);q(p.I<p.2W)p.I=p.2W}J q(p.2O==\'22\'||p.2O==\'4w\'){A 84=1f;A 5b=p.B.5W;q(p.2O==\'4w\')p.G=1l.4W(p.2f+(p.4n+p.3m-p.4j-p.U(\'1V\'))/2);J p.G=1l.4W(p.G-((p.U(\'1V\')-p.t)/2));q(p.G<p.2f+p.3m){p.G=p.2f+p.3m;84=L}q(!5c&&p.I<p.2W){p.I=p.2W;5b=1f}q(p.G+p.U(\'1V\')>p.2f+p.4n-p.4j){q(!5c&&84&&5b){p.I=p.U(\'5L\')}J q(p.U(\'1V\')<p.U(\'5L\')){p.G=p.2f+p.4n-p.4j-p.U(\'1V\')}J{p.G=p.2f+p.3m;q(!5c&&5b)p.I=p.U(\'5L\')}}q(!5c&&p.I<p.2W){p.I=p.2W;5b=1f}}J q(p.2O==\'2T\'){p.G=1l.cH(p.G-p.I+p.t)}q(p.G<p.3m){A cw=p.G;p.G=p.3m;q(5b&&!5c)p.I=p.I-(p.G-cw)}},ci:C(2V){A x=k.x,y=k.y,6X=1f,3b=1l.3C(x.1c,x.I),43=1l.3C(y.1c,y.I),3G=(k.3G||m.5Z);q(3b/43>2V){ 3b=43*2V;q(3b<x.2W){3b=x.2W;43=3b/2V}6X=L}J q(3b/43<2V){ 43=3b/2V;6X=L}q(m.5Z&&x.1c<x.2W){x.1Y=x.1c;y.I=y.1Y=y.1c}J q(k.3G){x.1Y=3b;y.1Y=43}J{x.I=3b;y.I=43}k.7V(3G?H:2V);q(3G&&y.I<y.1Y){y.1Y=y.I;x.1Y=y.I*2V}q(6X||3G){x.G=x.1R-x.cb+x.3l;x.2W=x.I;k.2O(x,L);y.G=y.1R-y.cb+y.3l;y.2W=y.I;k.2O(y,L);q(k.1u)k.5d()}},7V:C(2V){A x=k.x,y=k.y;q(k.1u){57(y.I>k.5y&&x.I>k.4B&&y.U(\'1V\')>y.U(\'5L\')){y.I-=10;q(2V)x.I=y.I*2V;k.5d(0,1)}}},cU:C(){q(k.2u){A h=/1g/i.1b(k.2u.3J)?k.7N()+1+\'F\':\'22\';q(k.1i)k.1i.E.N=h;k.2u.E.N=h;k.y.7i(k.1w.1M);m.5f(k)}},9G:C(){A x=k.x,y=k.y;k.4Q(\'1r\');m.1y(k,\'cX\');q(k.1p&&k.1p.2M)k.1p.2M.5l();k.9B(1,{Q:{K:x.U(\'1V\'),N:y.U(\'1V\'),W:x.G,V:y.G},T:{W:x.1h+x.U(\'2j\'),V:y.1h+y.U(\'2j\'),K:x.1Y||x.I,N:y.1Y||y.I}},m.6M)},9B:C(1J,2e,2C){A 5N=k.3j,7M=1J?(k.1e?k.1e.a:H):m.2t,t=(5N[1]&&7M&&m.41(7M,\'3j\')[1]==5N[1])?5N[1]:5N[0];q(k[t]&&t!=\'2H\'){k[t](1J,2e);D}q(k.1a&&!k.3L){q(1J)k.1a.4x();J k.1a.65((k.2E&&k.4u))}q(!1J)k.8u();A B=k,x=B.x,y=B.y,2P=k.2P;q(!1J)2P=k.cj||2P;A 60=1J?C(){q(B.1a)B.1a.2i.E.1o="2b";3P(C(){B.6i()},50)}:C(){B.5p()};q(1J)m.R(k.Q,{K:x.t+\'F\',N:y.t+\'F\'});q(1J&&k.2E){m.R(k.Q,{W:(x.1R-x.cb+x.3l)+\'F\',V:(y.1R-y.cb+y.3l)+\'F\'})}q(k.b8){m.R(k.Q,{1v:1J?0:1});m.3T(2e.Q,{1v:1J})}m.24(k.Q,2e.Q,{4d:2C,2P:2P,3F:C(3p,2J){q(B.1a&&B.3L&&2J.1z==\'V\'){A 6h=1J?2J.G:1-2J.G;A G={w:x.t+(x.U(\'1V\')-x.t)*6h,h:y.t+(y.U(\'1V\')-y.t)*6h,x:x.1R+(x.G-x.1R)*6h,y:y.1R+(y.G-y.1R)*6h};B.1a.4x(G,0,1)}q(B.2E){q(2J.1z==\'W\')B.3Y.E.W=(x.G-3p)+\'F\';q(2J.1z==\'V\')B.3Y.E.V=(y.G-3p)+\'F\'}}});m.24(k.T,2e.T,2C,2P,60);q(1J){k.Q.E.1o=\'2b\';k.T.E.1o=\'2b\';q(k.2E)k.1w.E.1o=\'2b\';k.a.19+=\' M-4J-3Z\'}},6g:C(1J,2e){k.3L=1f;A B=k,t=1J?m.6M:0;q(1J){m.24(k.Q,2e.Q,0);m.R(k.Q,{1v:0,1o:\'2b\'});m.24(k.T,2e.T,0);k.T.E.1o=\'2b\';m.24(k.Q,{1v:1},t,H,C(){B.6i()})}q(k.1a){k.1a.2i.E.1F=k.Q.E.1F;A 6H=1J||-1,1q=k.1a.1q,7T=1J?3:1q,7U=1J?1q:3;P(A i=7T;6H*i<=6H*7U;i+=6H,t+=25){(C(){A o=1J?7U-i:7T-i;3P(C(){B.1a.4x(0,o,1)},t)})()}}q(1J){}J{3P(C(){q(B.1a)B.1a.65(B.4u);B.8u();m.24(B.Q,{1v:0},H,H,C(){B.5p()})},t)}},47:C(1J,2e){q(!1J)D;A B=k,2C=m.ct,1e=B.1e,x=B.x,y=B.y,2v=1e.x,2x=1e.y,1u=B.1u,Q=k.Q,T=k.T;m.53(1d,\'6J\',m.6R);k.1a=1e.1a;q(k.1a)k.1a.B=B;1e.1a=H;1e.Q.E.2s=\'1r\';m.R(Q,{W:2v.G+\'F\',V:2x.G+\'F\',K:2v.U(\'1V\')+\'F\',N:2x.U(\'1V\')+\'F\'});m.R(T,{1n:\'1s\',K:(x.1Y||x.I)+\'F\',N:(y.1Y||y.I)+\'F\',W:(x.1h+x.U(\'2j\'))+\'F\',V:(y.1h+y.U(\'2j\'))+\'F\'});A 4s=m.16(\'O\',{19:\'M-2L\'},{1k:\'2m\',1F:4,2s:\'1r\',1n:\'1s\',W:(2v.1h+2v.U(\'2j\'))+\'F\',V:(2x.1h+2x.U(\'2j\'))+\'F\',K:(2v.1Y||2v.I)+\'F\',N:(2x.1Y||2x.I)+\'F\'});q(k.2E)m.R(k.3Y,{W:0,V:0});q(1u)m.R(1u,{2s:\'2b\',W:(2v.1h+2v.cb)+\'F\',V:(2x.1h+2x.cb)+\'F\',K:2v.I+\'F\',N:2x.I+\'F\'});A 7R={7K:1e,8j:k};P(A n 3h 7R){k[n]=7R[n].T.58(1);m.R(k[n],{1k:\'2m\',86:0,1o:\'2b\'});4s.1X(k[n])}m.R(k.7K,{W:0,V:0});m.R(k.8j,{1n:\'3A\',1v:0,W:(x.G-2v.G+x.1h-2v.1h+x.U(\'2j\')-2v.U(\'2j\'))+\'F\',V:(y.G-2x.G+y.1h-2x.1h+y.U(\'2j\')-2x.U(\'2j\'))+\'F\'});Q.1X(4s);q(1u){1u.19=\'\';Q.1X(1u)}4s.E.1n=\'\';1e.T.E.1n=\'1s\';q(m.55){A 2q=5i.7A.2q(/cs\\/([0-9]{3})/);q(2q&&2r(2q[1])<d3)Q.E.1o=\'2b\'}C 4b(){Q.E.1o=T.E.1o=\'2b\';T.E.1n=\'3A\';4s.E.1n=\'1s\';B.a.19+=\' M-4J-3Z\';B.6i();1e.5p()}m.24(1e.Q,{W:x.G,V:y.G,K:x.U(\'1V\'),N:y.U(\'1V\')},2C);m.24(4s,{K:x.1Y||x.I,N:y.1Y||y.I,W:x.1h+x.U(\'2j\'),V:y.1h+y.U(\'2j\')},2C);m.24(k.7K,{W:(2v.G-x.G+2v.1h-x.1h+2v.U(\'2j\')-x.U(\'2j\')),V:(2x.G-y.G+2x.1h-y.1h+2x.U(\'2j\')-y.U(\'2j\'))},2C);m.24(k.8j,{1v:1,W:0,V:0},2C);q(1u)m.24(1u,{W:x.1h+x.cb,V:y.1h+y.cb,K:x.I,N:y.I},2C);q(k.1a)A cv=C(3p,2J){q(2J.1z==\'V\'){A 3u=B.Q.E;A G={w:2r(3u.K),h:2r(3u.N),x:2r(3u.W),y:2r(3u.V)};B.1a.4x(G)}};m.24(Q,2e.Q,{4d:2C,7l:4b,3F:cv});4s.E.1o=\'2b\'},bb:C(o,el){q(!k.1e)D 1f;P(A i=0;i<k.1e.1S.Y;i++){A 6Q=m.$(\'23\'+k.1e.1S[i]);q(6Q&&6Q.23==o.23){k.8R();6Q.eG=k.S;m.2w(k.1S,k.1e.1S[i]);D L}}D 1f},6i:C(){k.5B=L;k.3V();q(k.2E&&k.3M==\'60\')k.6j();q(k.1g){1E{A B=k,2A=k.1g.9b||k.1g.5T.1d;m.2z(2A,\'7E\',C(){q(m.3e!=B.S)B.3V()})}1D(e){}q(m.1x&&1I k.6e!=\'eA\')k.1g.E.K=(k.4c-1)+\'F\'}q(k.4o)m.1H(k);q(m.2t&&m.2t==k.a)m.2t=H;k.cu();A p=m.3n,8i=m.6Y.x+p.6z,8h=m.6Y.y+p.6l;k.8w=k.x.G<8i&&8i<k.x.G+k.x.U(\'1V\')&&k.y.G<8h&&8h<k.y.G+k.y.U(\'1V\');q(k.1u)k.c5();m.1y(k,\'eB\')},cu:C(){A S=k.S;A 1U=k.1U;1L m.5n(1U,C(){1E{m.18[S].co()}1D(e){}})},co:C(){A 1G=k.89(1);q(1G&&1G.2n.cp().2q(/m\\.2H/))A 1O=m.16(\'1O\',{1m:m.6L(1G)})},89:C(2o){A 88=k.6G(),as=m.4y.3q[k.2N||\'1s\'];q(!as[88+2o]&&k.1p&&k.1p.bP){q(2o==1)D as[0];J q(2o==-1)D as[as.Y-1]}D as[88+2o]||H},6G:C(){A 2a=m.6m().3q[k.2N||\'1s\'];q(2a)P(A i=0;i<2a.Y;i++){q(2a[i]==k.a)D i}D H},bk:C(){q(k[k.5t]){A 2a=m.4y.3q[k.2N||\'1s\'];q(2a){A s=m.11.3I.29(\'%1\',k.6G()+1).29(\'%2\',2a.Y);k[k.5t].2h=\'<O 1Z="M-3I">\'+s+\'</O>\'+k[k.5t].2h}}},9w:C(){q(!k.1e){P(A i=0;i<m.6d.Y;i++){A 1Q=m.6d[i],3a=1Q.2N;q(1I 3a==\'1W\'||3a===H||3a===k.2N)k.1p=1L m.98(k,1Q)}}J{k.1p=k.1e.1p}A 1Q=k.1p;q(!1Q)D;A B=1Q.B=k;1Q.bK();1Q.4Z(\'1c-2H\');q(1Q.2U){A o=1Q.cl||{};o.4F=1Q.2U;o.23=\'2U\';k.4H(o)}q(1Q.2M)1Q.2M.6p(k);q(!k.1e&&k.4a)1Q.3N(L);q(1Q.4a){1Q.4a=3P(C(){m.1G(B.S)},(1Q.fb||fa))}},6A:C(){m.18[k.S]=H;q(m.2t==k.a)m.2t=H;m.8V(k.S);q(k.2y)m.2y.E.W=\'-4e\';m.1y(k,\'cz\')},bj:C(){q(k.5K)D;k.5K=m.16(\'a\',{21:m.cy,19:\'M-5K\',2h:m.11.cx,2k:m.11.cf});k.4H({4F:k.5K,1k:\'V W\',23:\'5K\'})},8K:C(8e,bu){P(A i=0;i<8e.Y;i++){A Z=8e[i],s=H;q(Z==\'8O\'&&!m.1y(k,\'f9\'))D;J q(Z==\'4L\'&&!m.1y(k,\'f8\'))D;q(!k[Z+\'7b\']&&k.7p)k[Z+\'7b\']=Z+\'-P-\'+k.7p;q(k[Z+\'7b\'])k[Z]=m.6c(k[Z+\'7b\']);q(!k[Z]&&!k[Z+\'7C\']&&k[Z+\'bv\'])1E{s=f7(k[Z+\'bv\'])}1D(e){}q(!k[Z]&&k[Z+\'7C\']){s=k[Z+\'7C\']}q(!k[Z]&&!s){A 1G=k.a.bw;57(1G&&!m.6x(1G)){q((1L 4I(\'M-\'+Z)).1b(1G.19||H)){k[Z]=1G.58(1);4S}1G=1G.bw}}q(!k[Z]&&!s&&k.5t==Z)s=\'\\n\';q(!k[Z]&&s)k[Z]=m.16(\'O\',{19:\'M-\'+Z,2h:s});q(bu&&k[Z]){A o={1k:(Z==\'4L\')?\'5s\':\'7o\'};P(A x 3h k[Z+\'bt\'])o[x]=k[Z+\'bt\'][x];o.4F=k[Z];k.4H(o)}}},4Q:C(1o){q(m.bq)k.6U(\'fc\',1o);q(m.br)k.6U(\'eZ\',1o);q(m.5V)k.6U(\'*\',1o)},6U:C(3J,1o){A 1j=1d.2B(3J);A 1z=3J==\'*\'?\'2s\':\'1o\';P(A i=0;i<1j.Y;i++){q(1z==\'1o\'||(1d.7J.bx(1j[i],"").bz(\'2s\')==\'22\'||1j[i].bE(\'1r-by\')!=H)){A 2X=1j[i].bE(\'1r-by\');q(1o==\'2b\'&&2X){2X=2X.29(\'[\'+k.S+\']\',\'\');1j[i].5w(\'1r-by\',2X);q(!2X)1j[i].E[1z]=1j[i].9u}J q(1o==\'1r\'){A 3O=m.7a(1j[i]);3O.w=1j[i].1C;3O.h=1j[i].1M;q(!k.4o){A bF=(3O.x+3O.w<k.x.U(\'5G\')||3O.x>k.x.U(\'5G\')+k.x.U(\'7H\'));A bD=(3O.y+3O.h<k.y.U(\'5G\')||3O.y>k.y.U(\'5G\')+k.y.U(\'7H\'))}A 7q=m.7I(1j[i]);q(!bF&&!bD&&7q!=k.S){q(!2X){1j[i].5w(\'1r-by\',\'[\'+k.S+\']\');1j[i].9u=1j[i].E[1z];1j[i].E[1z]=\'1r\'}J q(2X.bC(\'[\'+k.S+\']\')==-1){1j[i].5w(\'1r-by\',2X+\'[\'+k.S+\']\')}}J q((2X==\'[\'+k.S+\']\'||m.3e==7q)&&7q!=k.S){1j[i].5w(\'1r-by\',\'\');1j[i].E[1z]=1j[i].9u||\'\'}J q(2X&&2X.bC(\'[\'+k.S+\']\')>-1){1j[i].5w(\'1r-by\',2X.29(\'[\'+k.S+\']\',\'\'))}}}}},3V:C(){k.Q.E.1F=m.4f++;P(A i=0;i<m.18.Y;i++){q(m.18[i]&&i==m.3e){A 4k=m.18[i];4k.T.19+=\' M-\'+4k.3o+\'-9D\';q(4k.2Y){4k.T.E.4l=m.1x?\'bp\':\'7e\';4k.T.2k=m.11.bB}m.1y(4k,\'eE\')}}q(k.1a)k.1a.2i.E.1F=k.Q.E.1F;k.T.19=\'M-\'+k.3o;q(k.2Y){k.T.2k=m.11.9v;q(m.5P){m.52=1T.3S?\'7e\':\'6t(\'+m.54+m.5P+\'), 7e\';q(m.1x&&m.4m<6)m.52=\'bp\';k.T.E.4l=m.52}}m.3e=k.S;m.2z(1d,1T.3S?\'9x\':\'9C\',m.6F);m.1y(k,\'eF\')},8C:C(x,y){k.x.9M(x);k.y.9M(y)},3R:C(e){A w,h,r=e.K/e.N;w=1l.2T(e.K+e.dX,1l.3C(k.4B,k.x.1c));q(k.2Y&&1l.eq(w-k.x.1c)<12)w=k.x.1c;h=k.2E?e.N+e.dY:w/r;q(h<1l.3C(k.5y,k.y.1c)){h=1l.3C(k.5y,k.y.1c);q(k.2Y)w=h*r}k.8E(w,h)},8E:C(w,h){k.y.7i(h);k.x.7i(w)},2d:C(){q(k.6e||!k.5B)D;q(k.3j[1]==\'47\'&&m.2t){m.3d(m.2t).6A();m.2t=H}q(!m.1y(k,\'eK\'))D;k.6e=L;q(k.1p&&!m.2t)k.1p.3i();m.53(1d,1T.3S?\'9x\':\'9C\',m.6F);1E{q(k.2E)k.bf();k.T.E.4l=\'eR\';k.9B(0,{Q:{K:k.x.t,N:k.y.t,W:k.x.1R-k.x.cb+k.x.3l,V:k.y.1R-k.y.cb+k.y.3l},T:{W:0,V:0,K:k.x.t,N:k.y.t}},m.be)}1D(e){k.5p()}},bf:C(){q(m.5V){q(!m.66)m.66=m.16(\'O\',H,{1k:\'2m\'},m.2c);m.R(m.66,{K:k.x.I+\'F\',N:k.y.I+\'F\',W:k.x.G+\'F\',V:k.y.G+\'F\',1n:\'3A\'})}q(k.2K==\'3t\')1E{m.$(k.1i.1B).eN()}1D(e){}q(k.3M==\'60\'&&!k.4u)k.bd();q(k.2u&&k.2u!=k.59)k.2u.E.2s=\'1r\'},bd:C(){q(m.1x&&k.1g)1E{k.1g.5T.1d.1i.2h=\'\'}1D(e){}q(k.2K==\'3t\')9r.eg(k.1i.1B);k.1i.2h=\'\'},c7:C(){q(k.1a)k.1a.2i.E.1n=\'1s\';k.3E=H;k.Q.E.1n=\'1s\';m.2w(m.4g,k)},b9:C(){1E{m.18[k.S]=k;q(!m.9t&&m.3e!=k.S){1E{m.18[m.3e].2d()}1D(e){}}A z=m.4f++,3u={1n:\'\',1F:z};m.R(k.Q,3u);k.6e=1f;A o=k.1a||0;q(o){q(!k.3L)3u.1o=\'1r\';m.R(o.2i,3u)}q(k.1p){k.9w()}k.9G()}1D(e){}},4H:C(o){A el=o.4F,4N=(o.bg==\'36\'&&!/7d$/.1b(o.1k));q(1I el==\'9O\')el=m.6c(el);q(o.3w)el=m.16(\'O\',{2h:o.3w});q(!el||1I el==\'9O\')D;q(!m.1y(k,\'eu\',{14:el}))D;el.E.1n=\'3A\';o.23=o.23||o.4F;q(k.3j[1]==\'47\'&&k.bb(o,el))D;k.8R();A K=o.K&&/^[0-9]+(F|%)$/.1b(o.K)?o.K:\'22\';q(/^(W|3g)7d$/.1b(o.1k)&&!/^[0-9]+F$/.1b(o.K))K=\'eU\';A 14=m.16(\'O\',{1B:\'23\'+m.6r++,23:o.23},{1k:\'2m\',1o:\'1r\',K:K,9H:m.11.9I||\'\',1v:0},4N?m.36:k.1u,L);q(4N)14.6D=k.S;14.1X(el);m.3T(14,{1v:1,cg:0,bh:0,2C:(o.6g===0||o.6g===1f||(o.6g==2&&m.1x))?0:5o});m.3T(14,o);q(k.bG){k.5X(14);q(!14.7v||k.8w)m.24(14,{1v:14.1v},14.2C)}m.2w(k.1S,m.6r-1)},5X:C(14){A p=14.1k||\'8L 4w\',4N=(14.bg==\'36\'),6u=14.cg,6C=14.bh;q(4N){m.36.E.1n=\'3A\';14.6D=k.S;q(14.1C>14.26.1C)14.E.K=\'2Q%\'}J q(14.26!=k.1u)k.1u.1X(14);q(/W$/.1b(p))14.E.W=6u+\'F\';q(/4w$/.1b(p))m.R(14,{W:\'50%\',5j:(6u-1l.4W(14.1C/2))+\'F\'});q(/3g$/.1b(p))14.E.3g=-6u+\'F\';q(/^bm$/.1b(p)){m.R(14,{3g:\'2Q%\',9o:k.x.cb+\'F\',V:-k.y.cb+\'F\',4z:-k.y.cb+\'F\',2s:\'22\'});k.x.1h=14.1C}J q(/^bn$/.1b(p)){m.R(14,{W:\'2Q%\',5j:k.x.cb+\'F\',V:-k.y.cb+\'F\',4z:-k.y.cb+\'F\',2s:\'22\'});k.x.3v=14.1C}A 8M=14.26.1M;14.E.N=\'22\';q(4N&&14.1M>8M)14.E.N=m.4P?8M+\'F\':\'2Q%\';q(/^V/.1b(p))14.E.V=6C+\'F\';q(/^8L/.1b(p))m.R(14,{V:\'50%\',5u:(6C-1l.4W(14.1M/2))+\'F\'});q(/^4z/.1b(p))14.E.4z=-6C+\'F\';q(/^5s$/.1b(p)){m.R(14,{W:(-k.x.1h-k.x.cb)+\'F\',3g:(-k.x.3v-k.x.cb)+\'F\',4z:\'2Q%\',6v:k.y.cb+\'F\',K:\'22\'});k.y.1h=14.1M}J q(/^7o$/.1b(p)){m.R(14,{1k:\'4v\',W:(-k.x.1h-k.x.cb)+\'F\',3g:(-k.x.3v-k.x.cb)+\'F\',V:\'2Q%\',5u:k.y.cb+\'F\',K:\'22\'});k.y.3v=14.1M;14.E.1k=\'2m\'}},bl:C(){k.8K([\'4L\',\'8O\'],L);k.bk();q(k.8O)m.1y(k,\'eX\');q(k.4L)m.1y(k,\'f5\');q(k.4L&&k.8P)k.4L.19+=\' M-3D\';q(m.bi)k.bj();P(A i=0;i<m.1S.Y;i++){A o=m.1S[i],7y=o.8U,3a=o.2N;q((!7y&&!3a)||(7y&&7y==k.7p)||(3a&&3a===k.2N)){q(k.2Y||(k.2E&&o.ea))k.4H(o)}}A 7j=[];P(A i=0;i<k.1S.Y;i++){A o=m.$(\'23\'+k.1S[i]);q(/7d$/.1b(o.1k))k.5X(o);J m.2w(7j,o)}P(A i=0;i<7j.Y;i++)k.5X(7j[i]);k.bG=L},8R:C(){q(!k.1u)k.1u=m.16(\'O\',{19:k.7k},{1k:\'2m\',K:(k.x.I||k.x.1c)+\'F\',N:(k.y.I||k.y.1c)+\'F\',1o:\'1r\',2s:\'1r\',1F:m.1x?4:H},m.2c,L)},5d:C(8z,bH){A 1u=k.1u,x=k.x,y=k.y;m.R(1u,{K:x.I+\'F\',N:y.I+\'F\'});q(8z||bH){P(A i=0;i<k.1S.Y;i++){A o=m.$(\'23\'+k.1S[i]);A 8H=(m.4P||1d.8I==\'c4\');q(o&&/^(5s|7o)$/.1b(o.1k)){q(8H){o.E.K=(1u.1C+2*x.cb+x.1h+x.3v)+\'F\'}y[o.1k==\'5s\'?\'1h\':\'3v\']=o.1M}q(o&&8H&&/^(W|3g)7d$/.1b(o.1k)){o.E.N=(1u.1M+2*y.cb)+\'F\'}}}q(8z){m.R(k.T,{V:y.1h+\'F\'});m.R(1u,{V:(y.1h+y.cb)+\'F\'})}},c5:C(){A b=k.1u;b.19=\'\';m.R(b,{V:(k.y.1h+k.y.cb)+\'F\',W:(k.x.1h+k.x.cb)+\'F\',2s:\'2b\'});q(m.55)b.E.1o=\'2b\';k.Q.1X(b);P(A i=0;i<k.1S.Y;i++){A o=m.$(\'23\'+k.1S[i]);o.E.1F=o.23==\'2U\'?5:4;q(!o.7v||k.8w){o.E.1o=\'2b\';m.24(o,{1v:o.1v},o.2C)}}},8u:C(){q(!k.1S.Y)D;P(A i=0;i<k.1S.Y;i++){A o=m.$(\'23\'+k.1S[i]);q(o.26==m.36)m.51(o)}q(k.1p){A c=k.1p.2U;q(c&&m.3d(c)==k)c.26.8v(c)}q(k.2E&&k.4u){k.1u.E.V=\'-4e\';m.2c.1X(k.1u)}J m.51(k.1u)},c2:C(){q(k.1p&&k.1p.2U){k.1p.4E(\'1c-2H\');D}k.7t=m.16(\'a\',{21:\'bZ:m.18[\'+k.S+\'].6V();\',2k:m.11.8G,19:\'M-1c-2H\'});q(!m.1y(k,\'cW\'))D;k.4H({4F:k.7t,1k:m.c0,7v:L,1v:m.c1})},6V:C(){1E{q(!m.1y(k,\'d6\'))D;q(k.7t)m.51(k.7t);k.3V();A 3b=k.x.I;k.8E(k.x.1c,k.y.1c);A 7c=k.x.G-(k.x.I-3b)/2;q(7c<m.5j)7c=m.5j;k.8C(7c,k.y.G);k.4Q(\'1r\');m.5f(k)}1D(e){k.8D(e)}},5p:C(){k.a.19=k.a.19.29(\'M-4J-3Z\',\'\');k.4Q(\'2b\');q(k.2E&&k.4u&&k.3j[1]!=\'47\'){k.c7()}J{q(k.1a&&k.3L)k.1a.65();m.51(k.Q)}q(m.66)m.66.E.1n=\'1s\';q(!m.36.71.Y)m.36.E.1n=\'1s\';q(k.4o)m.8V(k.S);m.1y(k,\'db\');m.18[k.S]=H;m.cd()}};m.6K=C(a,T,6Z){k.a=a;k.T=T;k.6Z=6Z};m.6K.4O={9g:C(){q(!k.1m)k.1m=m.6L(k.a);q(k.1m.2q(\'#\')){A 2a=k.1m.9e(\'#\');k.1m=2a[0];k.1B=2a[1]}q(m.72[k.1m]){k.bY=m.72[k.1m];q(k.1B)k.9n();J k.5U();D}1E{k.3K=1L c8()}1D(e){1E{k.3K=1L ce("dh.ca")}1D(e){1E{k.3K=1L ce("cc.ca")}1D(e){k.9d()}}}A 3x=k;k.3K.cG=C(){q(3x.3K.9J==4){q(3x.1B)3x.9n();J 3x.5U()}};k.3K.bO("cI",k.1m,L);k.3K.cA(\'X-cE-cF\',\'c8\');k.3K.cB(H)},9n:C(){m.74();A 42=1T.3S||m.c9?{1m:\'cT:cQ\'}:H;k.1g=m.16(\'1g\',42,{1k:\'2m\',V:\'-4e\'},m.2c);k.5U()},5U:C(){A s=k.bY||k.3K.cK;q(k.6Z)m.72[k.1m]=s;q(!m.1x||m.4m>=5.5){s=s.29(/\\s/g,\' \').29(1L 4I(\'<dO[^>]*>\',\'bN\'),\'\').29(1L 4I(\'<bX[^>]*>.*?</bX>\',\'bN\'),\'\');q(k.1g){A 2A=k.1g.9b;q(!2A&&k.1g.5T)2A=k.1g.5T.1d;q(!2A){A 3x=k;3P(C(){3x.5U()},25);D}2A.bO();2A.dM(s);2A.2d();1E{s=2A.8Z(k.1B).2h}1D(e){1E{s=k.1g.1d.8Z(k.1B).2h}1D(e){}}}J{s=s.29(1L 4I(\'^.*?<1i[^>]*>(.*?)</1i>.*?$\',\'i\'),\'$1\')}}m.4G(k.T,\'6W\',\'M-1i\').2h=s;k.3B();P(A x 3h k)k[x]=H}};m.98=C(B,1t){q(m.e5!==1f)m.79();k.B=B;P(A x 3h 1t)k[x]=1t[x];q(k.e7)k.bI();q(k.2M)k.2M=m.bS(k)};m.98.4O={bI:C(){k.2U=m.16(\'O\',{2h:m.97(m.96.2U)},H,m.2c);A 5A=[\'3N\',\'3i\',\'31\',\'1G\',\'3D\',\'1c-2H\',\'2d\'];k.1P={};A 3x=k;P(A i=0;i<5A.Y;i++){k.1P[5A[i]]=m.4G(k.2U,\'1K\',\'M-\'+5A[i]);k.4E(5A[i])}k.1P.3i.E.1n=\'1s\'},bK:C(){q(k.bP||!k.2U)D;A 5g=k.B.6G(),2l=/6k$/;q(5g==0)k.4Z(\'31\');J q(2l.1b(k.1P.31.2B(\'a\')[0].19))k.4E(\'31\');q(5g+1==m.4y.3q[k.B.2N||\'1s\'].Y){k.4Z(\'1G\');k.4Z(\'3N\')}J q(2l.1b(k.1P.1G.2B(\'a\')[0].19)){k.4E(\'1G\');k.4E(\'3N\')}},4E:C(1P){q(!k.1P)D;A bV=k,a=k.1P[1P].2B(\'a\')[0],2l=/6k$/;a.2n=C(){bV[1P]();D 1f};q(2l.1b(a.19))a.19=a.19.29(2l,\'\')},4Z:C(1P){q(!k.1P)D;A a=k.1P[1P].2B(\'a\')[0];a.2n=C(){D 1f};q(!/6k$/.1b(a.19))a.19+=\' 6k\'},bT:C(){q(k.4a)k.3i();J k.3N()},3N:C(bR){q(k.1P){k.1P.3N.E.1n=\'1s\';k.1P.3i.E.1n=\'\'}k.4a=L;q(!bR)m.1G(k.B.S)},3i:C(){q(k.1P){k.1P.3i.E.1n=\'1s\';k.1P.3N.E.1n=\'\'}dE(k.4a);k.4a=H},31:C(){k.3i();m.31(k.1P.31)},1G:C(){k.3i();m.1G(k.1P.1G)},3D:C(){},\'1c-2H\':C(){m.3d().6V()},2d:C(){m.2d(k.1P.2d)}};m.bS=C(1p){C 6p(B){m.3T(1t||{},{4F:4p,23:\'2M\'});q(m.4P)1t.6g=0;B.4H(1t);m.R(4p.26,{2s:\'1r\'})};C 2f(3U){5l(1W,1l.4W(3U*4p[3Q?\'1C\':\'1M\']*0.7))};C 5l(i,8Y){q(i===1W)P(A j=0;j<5r.Y;j++){q(5r[j]==1p.B.a){i=j;4S}}A as=4p.2B(\'a\'),4J=as[i],45=4J.26,W=3Q?\'bU\':\'bW\',3g=3Q?\'bQ\':\'bJ\',K=3Q?\'bL\':\'bM\',4A=\'1q\'+W,1C=\'1q\'+K,6N=O.26.26[1C]-2i[1C],5R=2r(2i.E[3Q?\'W\':\'V\'])||0,2R=5R,dN=20;q(8Y!==1W){2R=5R-8Y;q(2R>0)2R=0;q(2R<6N)2R=6N}J{P(A j=0;j<as.Y;j++)as[j].19=\'\';4J.19=\'M-4J-3Z\';A 9m=i>0?as[i-1].26[4A]:45[4A],9l=45[4A]+45[1C]+(as[i+1]?as[i+1].26[1C]:0);q(9l>O[1C]-5R)2R=O[1C]-9l;J q(9m<-5R)2R=-9m}A 9f=45[4A]+(45[1C]-7f[1C])/2+2R;m.24(2i,3Q?{W:2R}:{V:2R},H,\'8W\');m.24(7f,3Q?{W:9f}:{V:9f},H,\'8W\');8S.E.1n=2R<0?\'3A\':\'1s\';8T.E.1n=(2R>6N)?\'3A\':\'1s\'};A 5r=m.4y.3q[1p.B.2N||\'1s\'],1t=1p.2M,5F=1t.5F||\'c6\',8Q=(5F==\'dc\'),3W=8Q?[\'O\',\'68\',\'1K\',\'1A\']:[\'2i\',\'4q\',\'3X\',\'2I\'],3Q=(5F==\'c6\'),4p=m.16(\'O\',{19:\'M-2M M-2M-\'+5F,2h:\'<O 1Z="M-2M-de">\'+\'<\'+3W[0]+\'><\'+3W[1]+\'></\'+3W[1]+\'></\'+3W[0]+\'></O>\'+\'<O 1Z="M-2f-1J"><O></O></O>\'+\'<O 1Z="M-2f-dd"><O></O></O>\'+\'<O 1Z="M-7f"><O></O></O>\'},{1n:\'1s\'},m.2c),5q=4p.71,O=5q[0],8S=5q[1],8T=5q[2],7f=5q[3],2i=O.cY,4q=4p.2B(3W[1])[0],3X;P(A i=0;i<5r.Y;i++){q(i==0||!3Q)3X=m.16(3W[2],H,H,4q);(C(){A a=5r[i],45=m.16(3W[3],H,H,3X),cV=i;m.16(\'a\',{21:a.21,2n:C(){D m.8x(a)},2h:m.c3?m.c3(a):a.2h},H,45)})()}q(!8Q){8S.2n=C(){2f(-1)};8T.2n=C(){2f(1)};m.2z(4q,1d.f4!==1W?\'fs\':\'em\',C(e){A 3U=0;e=e||1T.2G;q(e.ba){3U=e.ba/ec;q(m.3S)3U=-3U}J q(e.bc){3U=-e.bc/3}q(3U)2f(-3U*0.2);q(e.5m)e.5m();e.bo=1f})}D{6p:6p,5l:5l}};q(1d.9J&&m.1x){(C(){1E{1d.5h.eI(\'W\')}1D(e){3P(bA.eC,50);D}m.bs()})()}m.6E=m.11;A f6=m.67;m.2z(1T,\'7n\',C(){q(m.8p){A 7P=\'.M 1O\',7O=\'4l: 6t(\'+m.54+m.8p+\'), 7e !eQ;\';A E=m.16(\'E\',{Z:\'eo/8n\'},H,1d.2B(\'fw\')[0]);q(!m.1x){E.1X(1d.fg(7P+" {"+7O+"}"))}J{A 1e=1d.cq[1d.cq.Y-1];q(1I(1e.ck)=="6P")1e.ck(7P,7O)}}});m.2z(1T,\'3R\',C(){m.3n=m.73();q(m.36)P(A i=0;i<m.36.71.Y;i++){A 1N=m.36.71[i],B=m.3d(1N);B.5X(1N);q(1N.23==\'2M\')B.1p.2M.5l()}});m.2z(1d,\'6J\',C(e){m.6Y={x:e.6B,y:e.7g}});m.2z(1d,\'7E\',m.9q);m.2z(1d,\'aq\',m.9q);m.2z(1T,\'7n\',m.aI);m.2z(1T,\'7n\',m.aK);m.2z(1T,\'7n\',C(){m.aR=L});m.7B();',62,963,'||||||||||||||||||||this||hs||||if||||||||||var|exp|function|return|style|px|pos|null|size|else|width|true|highslide|height|div|for|wrapper|setStyles|key|content|get|top|left||length|type||lang|||overlay||createElement||expanders|className|outline|test|full|document|last|false|iframe|p1|body|els|position|Math|src|display|visibility|slideshow|offset|hidden|none|options|overlayBox|opacity|innerContent|ie|fireEvent|prop|span|id|offsetWidth|catch|try|zIndex|next|dim|typeof|up|li|new|offsetHeight|node|img|btn|ss|tpos|overlays|window|outlineType|wsize|undefined|appendChild|imgSize|class||href|auto|hsId|animate||parentNode||fx|replace|arr|visible|container|close|to|scroll|case|innerHTML|table|imgPad|title|re|absolute|onclick|op|params|match|parseInt|overflow|upcoming|scrollerDiv|lastX|push|lastY|loading|addEventListener|doc|getElementsByTagName|dur|dimmer|isHtml|dragArgs|event|expand|td|args|objectType|image|thumbstrip|slideshowGroup|justify|easing|100|tblPos|tgt|max|controls|ratio|minSize|hiddenBy|isImage|target|ajax|previous||||name|viewport||||sg|xSize|elem|getExpander|focusKey|ucwh|right|in|pause|transitions|wh|tb|marginMin|page|contentType|val|groups|hasDragged|opt|swf|stl|p2|html|pThis|clearing|custom|block|onLoad|min|move|releaseMask|step|useBox|graphic|number|tagName|xmlHttp|outlineWhileAnimating|objectLoadTime|play|elPos|setTimeout|isX|resize|opera|extend|delta|focus|tree|tr|mediumContent|anchor||getParam|attribs|ySize|styles|cell|iebody|crossfade|timers|func|autoplay|end|objectWidth|duration|9999px|zIndexCounter|sleeping|tgtArr|start|marginMax|blurExp|cursor|uaVersion|clientSize|dimmingOpacity|dom|tbody|pendingOutlines|fadeBox|clone|preserveContent|relative|center|setPosition|anchors|bottom|offsetLeft|minWidth|now|unit|enable|overlayId|getElementByClass|createOverlay|RegExp|active|onload|heading|wDiff|relToVP|prototype|ieLt7|doShowHide|htmls|break|hDiff|area|cacheBindings|round|images|over|disable||discardElement|styleRestoreCursor|removeEventListener|graphicsDir|safari|objectHeight|while|cloneNode|scrollingContent|adj|allowReduce|moveOnly|sizeOverlayBox|cNode|setDimmerSize|cur|documentElement|navigator|marginLeft|self|selectThumb|preventDefault|Outline|250|afterClose|domCh|group|above|numberPosition|marginTop|obj|setAttribute|owner|minHeight|getParams|buttons|isExpanded|param|ruler|cache|mode|opos|toLowerCase|contentLoaded|maxX|credits|fitsize|showLoading|trans|preloadTheseImages|restoreCursor|filter|curTblPos|minX|contentWindow|loadHTML|geckoMac|allowSizeReduction|positionOverlay|minY|padToMinWidth|after|maxY|uclt|all|parent|destroy|mask|Expander|ul|before|currentStyle|matches|getNode|slideshows|isClosing|on|fade|fac|afterExpand|writeExtendedContent|disabled|scrollTop|getAnchors|expOnly|previousOrNext|add|element|idCounter|Dimension|url|offX|marginBottom|lt|isHsAnchor|preloadFullImage|scrollLeft|cancelLoading|clientX|offY|hsKey|langDefaults|keyHandler|getAnchorIndex|dir|imgs|mousemove|Ajax|getSrc|expandDuration|minTblPos|allowWidthReduction|object|oDiv|dragHandler|kdeBugCorr|curAnim|showHideElements|doFullExpand|DIV|changed|mouse|pre||childNodes|cachedGets|getPageSize|init||background|innerHeight|innerWidth|updateAnchors|getPosition|Id|xpos|panel|pointer|marker|clientY|maincontent|setSize|os|wrapperClassName|complete|pageWidth|load|below|thumbsUserSetId|wrapperKey|preloadTheseAjax|rel|fullExpandLabel|gotoEnd|hideOnMouseOut|pageHeight|topmostKey|tId|onLoadStarted|userAgent|setClickEvents|Text|ucrb|mousedown|align|hasAlphaImageLoader|osize|getWrapperKey|defaultView|oldImg|oPos|other|getIframePageHeight|dec|sel|calcExpanded|names|calcBorders|startOff|endOff|fitOverlayBox|Date|allowHeightReduction|setObjContainerSize|padding|offsetTop|htmlGetSize|correctIframeSize|getTime|hasMovedMin|swfOptions|border|location|current|getAdjacentAnchor|calcThumb|Create|overrides|continuePreloading|types|sizeDiff|onDomReady|mY|mX|newImg|contentId|getSelfRendered|getCacheBinding|css|loadingPosXfade|expandCursor|connectOutline|loadingPos|margin|numberOfImagesToPreload|destroyOverlays|removeChild|mouseIsOver|transit|dimmingDuration|doWrapper|topZ|preloadAjaxElement|moveTo|error|resizeTo|cacheAjax|fullExpandTitle|ie6|compatMode|evt|getInline|middle|parOff|hasFocused|caption|dragByHeading|floatMode|genOverlayBox|scrollUp|scrollDown|thumbnailId|undim|easeOutQuad|nextTitle|scrollBy|getElementById|nextText|moveTitle|previousText|previousTitle|arrow|Click|skin|replaceLang|Slideshow||moveText|contentDocument|clientHeight|onError|split|markerPos|run|clientWidth|parseFloat|closeText|closeTitle|activeRight|activeLeft|getElementContent|marginRight|clones|mouseClickHandler|swfobject|state|allowMultipleInstances|origProp|restoreTitle|initSlideshow|keypress|update|htmlExpand|openerTagNames|changeSize|keydown|blur|garbageBin|startTime|show|direction|cssDirection|readyState|distance|srcElement|setPos|done|string|relatedTarget|targetY|headingOverlay|captionOverlay|fullExpandText|targetX|vis|onGraphicLoad|call|appendTo|pauseText|resizeTitle|attributes|spacebar|newHeight|Previous|Next|Pause|Play|Highslide|JS|clear|Close|Move|hasExtendedContent|playTitle|flashvars|playText|wmode|timerId|png|preloadGraphic|and|_default|200|pauseTitle|scrollMaxX|mouseup|both||dimmingGeckoFix|maxWidth|isDomReady|ltr|loadingOpacity|loadingText|loadingTitle|detachEvent|thumb|form|hasHtmlExpanders|clickY|wrapperMouseHandler|pow|focusTopmost|preloadImages|enableKeyListener|preloadAjax|easeInQuad|isUnobtrusiveAnchor|alpha|clickX|scrollMaxY|scrollWidth|pageLoaded|switch|hide|tag|nopad|fixedControls|scrollHeight|offsetParent|contentWrapper|hsHasSetClick|toUpperCase|rb|yScroll|from|orig|xScroll|rv|fadeInOut|awake|wheelDelta|reuseOverlay|detail|destroyObject|restoreDuration|htmlPrepareClose|relativeTo|offsetY|showCredits|writeCredits|getNumber|getOverlays|leftpanel|rightpanel|returnValue|hand|hideSelects|hideIframes|domReady|Overlay|addOverlay|Eval|nextSibling|getComputedStyle||getPropertyValue|arguments|focusTitle|indexOf|clearsY|getAttribute|clearsX|gotOverlays|doPanels|getControls|Bottom|checkFirstAndLast|Width|Height|gi|open|repeat|Right|wait|Thumbstrip|hitSpace|Left|sls|Top|script|cachedGet|javascript|fullExpandPosition|fullExpandOpacity|createFullExpand|stripItemFormatter|BackCompat|showOverlays|horizontal|sleep|XMLHttpRequest|ie6SSL|XMLHTTP||Microsoft|reOrder|ActiveXObject|creditsTitle|offsetX|vendor|correctRatio|easingClose|addRule|overlayOptions|KDE|getImageMapAreaCorrection|preloadNext|toString|styleSheets|htmlSizeOperations|Safari|transitionDuration|prepareNextOutline|wrapStep|tmpMin|creditsText|creditsHref|onHideLoading|setRequestHeader|send|frameborder|removeAttribute|Requested|With|onreadystatechange|floor|GET|Gecko|responseText|maxHeight|maincontentEval|maincontentText|it|ra|blank|allowtransparency|Macintosh|about|reflow|pI|onCreateFullExpand|onBeforeExpand|firstChild|dimming|onDimmerClick|keyCode|onKeyDown|525|geckodimmer|fit|onDoFullExpand|useMap|pageYOffset|newWidth|pageXOffset|onAfterClose|float|down|inner|onSetClickEvent|maincontentId|Msxml2|captionId|of|coords|Image|insertBefore|nodeName|click|drag|version|keys|expressInstallSwfurl|Use|Resize|esc|front|Expand|bring|cancel|Loading|actual|Powered|homepage|clearTimeout|the|Go|graphics|zoomin|flash|footer|circle|write|mgnRight|link|static|headingText|headingId|captionEval|captionText|header|shape|http|||com|outlineStartOffset|1001|zoomout|embedSWF|drop|dynamicallyUpdateAnchors|transparent|useControls|shadow|headingEval|useOnHtml|lineHeight|120|fontSize|oncontextmenu|blockRightClick|removeSWF|collapse|imageCreate|https|protocol||DOMMouseScroll|attachEvent|text|outlines|abs|fromElement|outlinesDir|onMouseOver|onCreateOverlay|onmouseover|onMouseOut|borderCollapse|cellSpacing|setInterval|boolean|onAfterExpand|callee|splice|onBlur|onFocus|reuse|clearInterval|doScroll|onmouseout|onBeforeClose|1px|paddingTop|StopPlay|onAfterGetContent|linearTween|important|default|onShowLoading|onActivate|200px|toElement|htmlE|onAfterGetCaption|onInit|IFRAME|xpand|mouseover|button|scale|onmousewheel|onAfterGetHeading|HsExpander|eval|onBeforeGetHeading|onBeforeGetCaption|500|interval|SELECT|addSlideshow|registerOverlay|sizingMethod|createTextNode|300|sqrt|htmlCreate|AlphaImageLoader|flushImgSize|onDrag|dragSensitivity|onBeforeGetContent|progid|DXImageTransform|01|mousewheel|onDrop|onImageClick|white|HEAD'.split('|'),0,{}))

