/*  Prototype JavaScript framework, version 1.7
 *  (c) 2005-2010 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.7',

  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/.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'),
          form = document.createElement('form'),
          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;
/* Based on Alex Arnell's inheritance implementation. */

var Class = (function() {

  var IS_DONTENUM_BUGGY = (function(){
    for (var p in { toString: 1 }) {
      if (p === 'toString') return false;
    }
    return true;
  })();

  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, length = properties.length; i < 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,
        properties = Object.keys(source);

    if (IS_DONTENUM_BUGGY) {
      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()[0] == "$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,
      NULL_TYPE = 'Null',
      UNDEFINED_TYPE = 'Undefined',
      BOOLEAN_TYPE = 'Boolean',
      NUMBER_TYPE = 'Number',
      STRING_TYPE = 'String',
      OBJECT_TYPE = 'Object',
      FUNCTION_CLASS = '[object Function]',
      BOOLEAN_CLASS = '[object Boolean]',
      NUMBER_CLASS = '[object Number]',
      STRING_CLASS = '[object String]',
      ARRAY_CLASS = '[object Array]',
      DATE_CLASS = '[object Date]',
      NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
        typeof JSON.stringify === 'function' &&
        JSON.stringify(0) === '0' &&
        typeof JSON.stringify(Prototype.K) === 'undefined';

  function Type(o) {
    switch(o) {
      case null: return NULL_TYPE;
      case (void 0): return UNDEFINED_TYPE;
    }
    var type = typeof o;
    switch(type) {
      case 'boolean': return BOOLEAN_TYPE;
      case 'number':  return NUMBER_TYPE;
      case 'string':  return STRING_TYPE;
    }
    return OBJECT_TYPE;
  }

  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(value) {
    return Str('', { '': value }, []);
  }

  function Str(key, holder, stack) {
    var value = holder[key],
        type = typeof value;

    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
      value = value.toJSON(key);
    }

    var _class = _toString.call(value);

    switch (_class) {
      case NUMBER_CLASS:
      case BOOLEAN_CLASS:
      case STRING_CLASS:
        value = value.valueOf();
    }

    switch (value) {
      case null: return 'null';
      case true: return 'true';
      case false: return 'false';
    }

    type = typeof value;
    switch (type) {
      case 'string':
        return value.inspect(true);
      case 'number':
        return isFinite(value) ? String(value) : 'null';
      case 'object':

        for (var i = 0, length = stack.length; i < length; i++) {
          if (stack[i] === value) { throw new TypeError(); }
        }
        stack.push(value);

        var partial = [];
        if (_class === ARRAY_CLASS) {
          for (var i = 0, length = value.length; i < length; i++) {
            var str = Str(i, value, stack);
            partial.push(typeof str === 'undefined' ? 'null' : str);
          }
          partial = '[' + partial.join(',') + ']';
        } else {
          var keys = Object.keys(value);
          for (var i = 0, length = keys.length; i < length; i++) {
            var key = keys[i], str = Str(key, value, stack);
            if (typeof str !== "undefined") {
               partial.push(key.inspect(true)+ ':' + str);
             }
          }
          partial = '{' + partial.join(',') + '}';
        }
        stack.pop();
        return partial;
    }
  }

  function stringify(object) {
    return JSON.stringify(object);
  }

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

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

  function keys(object) {
    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
    var results = [];
    for (var property in object) {
      if (object.hasOwnProperty(property)) {
        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) === ARRAY_CLASS;
  }

  var hasNativeIsArray = (typeof Array.isArray == 'function')
    && Array.isArray([]) && !Array.isArray({});

  if (hasNativeIsArray) {
    isArray = Array.isArray;
  }

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

  function isFunction(object) {
    return _toString.call(object) === FUNCTION_CLASS;
  }

  function isString(object) {
    return _toString.call(object) === STRING_CLASS;
  }

  function isNumber(object) {
    return _toString.call(object) === NUMBER_CLASS;
  }

  function isDate(object) {
    return _toString.call(object) === DATE_CLASS;
  }

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

  extend(Object, {
    extend:        extend,
    inspect:       inspect,
    toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
    toQueryString: toQueryString,
    toHTML:        toHTML,
    keys:          Object.keys || keys,
    values:        values,
    clone:         clone,
    isElement:     isElement,
    isArray:       isArray,
    isHash:        isHash,
    isFunction:    isFunction,
    isString:      isString,
    isNumber:      isNumber,
    isDate:        isDate,
    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
  }
})());



(function(proto) {


  function toISOString() {
    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';
  }


  function toJSON() {
    return this.toISOString();
  }

  if (!proto.toISOString) proto.toISOString = toISOString;
  if (!proto.toJSON) proto.toJSON = toJSON;

})(Date.prototype);


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() {
  var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
    typeof JSON.parse === 'function' &&
    JSON.parse('{"test": true}').test;

  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'),
        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()),
            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() {
    return this.replace(/-+(.)?/g, function(match, chr) {
      return chr ? chr.toUpperCase() : '';
    });
  }

  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 unfilterJSON(filter) {
    return this.replace(filter || Prototype.JSONFilter, '$1');
  }

  function isJSON() {
    var str = this;
    if (str.blank()) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

  function evalJSON(sanitize) {
    var json = this.unfilterJSON(),
        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    if (cx.test(json)) {
      json = json.replace(cx, function (a) {
        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
      });
    }
    try {
      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
    } catch (e) { }
    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
  }

  function parseJSON() {
    var json = this.unfilterJSON();
    return JSON.parse(json);
  }

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

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

  function endsWith(pattern) {
    var d = this.length - pattern.length;
    return d >= 0 && this.indexOf(pattern, d) === 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 || 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,
    unfilterJSON:   unfilterJSON,
    isJSON:         isJSON,
    evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : 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],
          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, context) {
    for (var i = 0, length = this.length >>> 0; i < length; i++) {
      if (i in this) iterator.call(context, this[i], i, this);
    }
  }
  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.toArray() : this)._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 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
  });

  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)) {
          var queryValues = [];
          for (var i = 0, len = values.length, value; i < len; i++) {
            value = values[i];
            queryValues.push(toQueryPair(key, value));
          }
          return results.concat(queryValues);
        }
      } 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 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:                 toObject,
    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 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,
    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 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;
  }
};

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.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.isString(this.options.parameters) ?
          this.options.parameters :
          Object.toQueryString(this.options.parameters);

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

    if (params && this.method === 'get') {
      this.url += (this.url.include('?') ? '&' : '?') + params;
    }

    this.parameters = params.toQueryParams();

    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) || status == 304;
  },

  getStatus: function() {
    try {
      if (this.transport.status === 1223) return 204;
      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 (!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) {
  function shouldUseCache(tagName, attributes) {
    if (tagName === 'select') return false;
    if ('type' in attributes) return false;
    return true;
  }

  var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
    try {
      var el = document.createElement('<input name="x">');
      return el.tagName.toLowerCase() === 'input' && el.name === 'x';
    }
    catch(err) {
      return false;
    }
  })();

  var element = global.Element;

  global.Element = function(tagName, attributes) {
    attributes = attributes || { };
    tagName = tagName.toLowerCase();
    var cache = Element.cache;

    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && 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));

    var node = shouldUseCache(tagName, attributes) ?
     cache[tagName].cloneNode(false) : document.createElement(tagName);

    return Element.writeAttribute(node, attributes);
  };

  Object.extend(global.Element, element || { });
  if (element) global.Element.prototype = element.prototype;

})(this);

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

Element._purgeElement = function(element) {
  var uid = element._prototypeUID;
  if (uid) {
    Element.stopObserving(element);
    element._prototypeUID = void 0;
    delete Element.Storage[uid];
  }
}

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 LINK_ELEMENT_INNERHTML_BUGGY = (function() {
      try {
        var el = document.createElement('div');
        el.innerHTML = "<link>";
        var isBuggy = (el.childNodes.length === 0);
        el = null;
        return isBuggy;
      } catch(e) {
        return true;
      }
    })();

    var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
     TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;

    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);
      var purgeElement = Element._purgeElement;

      var descendants = element.getElementsByTagName('*'),
       i = descendants.length;
      while (i--) purgeElement(descendants[i]);

      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 (ANY_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 if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
          while (element.firstChild) {
            element.removeChild(element.firstChild);
          }
          var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
          nodes.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(),
          value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property, maximumLength) {
    element = $(element);
    maximumLength = maximumLength || -1;
    var elements = [];

    while (element = element[property]) {
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
      if (elements.length == maximumLength)
        break;
    }

    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) {
    var results = [], child = $(element).firstChild;
    while (child) {
      if (child.nodeType === 1) {
        results.push(Element.extend(child));
      }
      child = child.nextSibling;
    }
    return results;
  },

  previousSiblings: function(element, maximumLength) {
    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) {
    element = $(element);
    if (Object.isString(selector))
      return Prototype.Selector.match(element, 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] :
      Prototype.Selector.find(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 (Object.isNumber(expression)) index = expression, expression = false;
    if (!Object.isNumber(index)) index = 0;

    if (expression) {
      return Prototype.Selector.find(element.previousSiblings(), expression, index);
    } else {
      return element.recursivelyCollect("previousSibling", index + 1)[index];
    }
  },

  next: function(element, expression, index) {
    element = $(element);
    if (Object.isNumber(expression)) index = expression, expression = false;
    if (!Object.isNumber(index)) index = 0;

    if (expression) {
      return Prototype.Selector.find(element.nextSiblings(), expression, index);
    } else {
      var maximumLength = Object.isNumber(index) ? index + 1 : 1;
      return element.recursivelyCollect("nextSibling", index + 1)[index];
    }
  },


  select: function(element) {
    element = $(element);
    var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
    return Prototype.Selector.select(expressions, element);
  },

  adjacent: function(element) {
    element = $(element);
    var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
    return Prototype.Selector.select(expressions, element.parentNode).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;
  },

  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;
  },

  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), delta = [0, 0], parent = null;

    element = $(element);

    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 '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.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',
        forProp = 'for',
        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'), f;
            el.onclick = Prototype.emptyFunction;
            var value = el.getAttribute('onclick');

            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;
  };
}

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(),
          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, force) {
  var div = new Element('div'),
      t = Element._insertionTranslations.tags[tagName];

  var workaround = false;
  if (t) workaround = true;
  else if (force) {
    workaround = true;
    t = ['', '', 0];
  }

  if (workaround) {
    div.innerHTML = '&nbsp;' + t[0] + html + t[1];
    div.removeChild(div.firstChild);
    for (var i = t[2]; i--; ) {
      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),
            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;
})();

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

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),
      "BUTTON":   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),
        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;
    }

    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);
  },

  purge: function(element) {
    if (!(element = $(element))) return;
    var purgeElement = Element._purgeElement;

    purgeElement(element);

    var descendants = element.getElementsByTagName('*'),
     i = descendants.length;

    while (i--) purgeElement(descendants[i]);

    return null;
  }
});

(function() {

  function toDecimal(pctString) {
    var match = pctString.match(/^(\d+)%?$/i);
    if (!match) return null;
    return (Number(match[1]) / 100);
  }

  function getPixelValue(value, property, context) {
    var element = null;
    if (Object.isElement(value)) {
      element = value;
      value = element.getStyle(property);
    }

    if (value === null) {
      return null;
    }

    if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
      return window.parseFloat(value);
    }

    var isPercentage = value.include('%'), isViewport = (context === document.viewport);

    if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
      var style = element.style.left, rStyle = element.runtimeStyle.left;
      element.runtimeStyle.left = element.currentStyle.left;
      element.style.left = value || 0;
      value = element.style.pixelLeft;
      element.style.left = style;
      element.runtimeStyle.left = rStyle;

      return value;
    }

    if (element && isPercentage) {
      context = context || element.parentNode;
      var decimal = toDecimal(value);
      var whole = null;
      var position = element.getStyle('position');

      var isHorizontal = property.include('left') || property.include('right') ||
       property.include('width');

      var isVertical =  property.include('top') || property.include('bottom') ||
        property.include('height');

      if (context === document.viewport) {
        if (isHorizontal) {
          whole = document.viewport.getWidth();
        } else if (isVertical) {
          whole = document.viewport.getHeight();
        }
      } else {
        if (isHorizontal) {
          whole = $(context).measure('width');
        } else if (isVertical) {
          whole = $(context).measure('height');
        }
      }

      return (whole === null) ? 0 : whole * decimal;
    }

    return 0;
  }

  function toCSSPixels(number) {
    if (Object.isString(number) && number.endsWith('px')) {
      return number;
    }
    return number + 'px';
  }

  function isDisplayed(element) {
    var originalElement = element;
    while (element && element.parentNode) {
      var display = element.getStyle('display');
      if (display === 'none') {
        return false;
      }
      element = $(element.parentNode);
    }
    return true;
  }

  var hasLayout = Prototype.K;
  if ('currentStyle' in document.documentElement) {
    hasLayout = function(element) {
      if (!element.currentStyle.hasLayout) {
        element.style.zoom = 1;
      }
      return element;
    };
  }

  function cssNameFor(key) {
    if (key.include('border')) key = key + '-width';
    return key.camelize();
  }

  Element.Layout = Class.create(Hash, {
    initialize: function($super, element, preCompute) {
      $super();
      this.element = $(element);

      Element.Layout.PROPERTIES.each( function(property) {
        this._set(property, null);
      }, this);

      if (preCompute) {
        this._preComputing = true;
        this._begin();
        Element.Layout.PROPERTIES.each( this._compute, this );
        this._end();
        this._preComputing = false;
      }
    },

    _set: function(property, value) {
      return Hash.prototype.set.call(this, property, value);
    },

    set: function(property, value) {
      throw "Properties of Element.Layout are read-only.";
    },

    get: function($super, property) {
      var value = $super(property);
      return value === null ? this._compute(property) : value;
    },

    _begin: function() {
      if (this._prepared) return;

      var element = this.element;
      if (isDisplayed(element)) {
        this._prepared = true;
        return;
      }

      var originalStyles = {
        position:   element.style.position   || '',
        width:      element.style.width      || '',
        visibility: element.style.visibility || '',
        display:    element.style.display    || ''
      };

      element.store('prototype_original_styles', originalStyles);

      var position = element.getStyle('position'),
       width = element.getStyle('width');

      if (width === "0px" || width === null) {
        element.style.display = 'block';
        width = element.getStyle('width');
      }

      var context = (position === 'fixed') ? document.viewport :
       element.parentNode;

      element.setStyle({
        position:   'absolute',
        visibility: 'hidden',
        display:    'block'
      });

      var positionedWidth = element.getStyle('width');

      var newWidth;
      if (width && (positionedWidth === width)) {
        newWidth = getPixelValue(element, 'width', context);
      } else if (position === 'absolute' || position === 'fixed') {
        newWidth = getPixelValue(element, 'width', context);
      } else {
        var parent = element.parentNode, pLayout = $(parent).getLayout();

        newWidth = pLayout.get('width') -
         this.get('margin-left') -
         this.get('border-left') -
         this.get('padding-left') -
         this.get('padding-right') -
         this.get('border-right') -
         this.get('margin-right');
      }

      element.setStyle({ width: newWidth + 'px' });

      this._prepared = true;
    },

    _end: function() {
      var element = this.element;
      var originalStyles = element.retrieve('prototype_original_styles');
      element.store('prototype_original_styles', null);
      element.setStyle(originalStyles);
      this._prepared = false;
    },

    _compute: function(property) {
      var COMPUTATIONS = Element.Layout.COMPUTATIONS;
      if (!(property in COMPUTATIONS)) {
        throw "Property not found.";
      }

      return this._set(property, COMPUTATIONS[property].call(this, this.element));
    },

    toObject: function() {
      var args = $A(arguments);
      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
       args.join(' ').split(' ');
      var obj = {};
      keys.each( function(key) {
        if (!Element.Layout.PROPERTIES.include(key)) return;
        var value = this.get(key);
        if (value != null) obj[key] = value;
      }, this);
      return obj;
    },

    toHash: function() {
      var obj = this.toObject.apply(this, arguments);
      return new Hash(obj);
    },

    toCSS: function() {
      var args = $A(arguments);
      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
       args.join(' ').split(' ');
      var css = {};

      keys.each( function(key) {
        if (!Element.Layout.PROPERTIES.include(key)) return;
        if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;

        var value = this.get(key);
        if (value != null) css[cssNameFor(key)] = value + 'px';
      }, this);
      return css;
    },

    inspect: function() {
      return "#<Element.Layout>";
    }
  });

  Object.extend(Element.Layout, {
    PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),

    COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),

    COMPUTATIONS: {
      'height': function(element) {
        if (!this._preComputing) this._begin();

        var bHeight = this.get('border-box-height');
        if (bHeight <= 0) {
          if (!this._preComputing) this._end();
          return 0;
        }

        var bTop = this.get('border-top'),
         bBottom = this.get('border-bottom');

        var pTop = this.get('padding-top'),
         pBottom = this.get('padding-bottom');

        if (!this._preComputing) this._end();

        return bHeight - bTop - bBottom - pTop - pBottom;
      },

      'width': function(element) {
        if (!this._preComputing) this._begin();

        var bWidth = this.get('border-box-width');
        if (bWidth <= 0) {
          if (!this._preComputing) this._end();
          return 0;
        }

        var bLeft = this.get('border-left'),
         bRight = this.get('border-right');

        var pLeft = this.get('padding-left'),
         pRight = this.get('padding-right');

        if (!this._preComputing) this._end();

        return bWidth - bLeft - bRight - pLeft - pRight;
      },

      'padding-box-height': function(element) {
        var height = this.get('height'),
         pTop = this.get('padding-top'),
         pBottom = this.get('padding-bottom');

        return height + pTop + pBottom;
      },

      'padding-box-width': function(element) {
        var width = this.get('width'),
         pLeft = this.get('padding-left'),
         pRight = this.get('padding-right');

        return width + pLeft + pRight;
      },

      'border-box-height': function(element) {
        if (!this._preComputing) this._begin();
        var height = element.offsetHeight;
        if (!this._preComputing) this._end();
        return height;
      },

      'border-box-width': function(element) {
        if (!this._preComputing) this._begin();
        var width = element.offsetWidth;
        if (!this._preComputing) this._end();
        return width;
      },

      'margin-box-height': function(element) {
        var bHeight = this.get('border-box-height'),
         mTop = this.get('margin-top'),
         mBottom = this.get('margin-bottom');

        if (bHeight <= 0) return 0;

        return bHeight + mTop + mBottom;
      },

      'margin-box-width': function(element) {
        var bWidth = this.get('border-box-width'),
         mLeft = this.get('margin-left'),
         mRight = this.get('margin-right');

        if (bWidth <= 0) return 0;

        return bWidth + mLeft + mRight;
      },

      'top': function(element) {
        var offset = element.positionedOffset();
        return offset.top;
      },

      'bottom': function(element) {
        var offset = element.positionedOffset(),
         parent = element.getOffsetParent(),
         pHeight = parent.measure('height');

        var mHeight = this.get('border-box-height');

        return pHeight - mHeight - offset.top;
      },

      'left': function(element) {
        var offset = element.positionedOffset();
        return offset.left;
      },

      'right': function(element) {
        var offset = element.positionedOffset(),
         parent = element.getOffsetParent(),
         pWidth = parent.measure('width');

        var mWidth = this.get('border-box-width');

        return pWidth - mWidth - offset.left;
      },

      'padding-top': function(element) {
        return getPixelValue(element, 'paddingTop');
      },

      'padding-bottom': function(element) {
        return getPixelValue(element, 'paddingBottom');
      },

      'padding-left': function(element) {
        return getPixelValue(element, 'paddingLeft');
      },

      'padding-right': function(element) {
        return getPixelValue(element, 'paddingRight');
      },

      'border-top': function(element) {
        return getPixelValue(element, 'borderTopWidth');
      },

      'border-bottom': function(element) {
        return getPixelValue(element, 'borderBottomWidth');
      },

      'border-left': function(element) {
        return getPixelValue(element, 'borderLeftWidth');
      },

      'border-right': function(element) {
        return getPixelValue(element, 'borderRightWidth');
      },

      'margin-top': function(element) {
        return getPixelValue(element, 'marginTop');
      },

      'margin-bottom': function(element) {
        return getPixelValue(element, 'marginBottom');
      },

      'margin-left': function(element) {
        return getPixelValue(element, 'marginLeft');
      },

      'margin-right': function(element) {
        return getPixelValue(element, 'marginRight');
      }
    }
  });

  if ('getBoundingClientRect' in document.documentElement) {
    Object.extend(Element.Layout.COMPUTATIONS, {
      'right': function(element) {
        var parent = hasLayout(element.getOffsetParent());
        var rect = element.getBoundingClientRect(),
         pRect = parent.getBoundingClientRect();

        return (pRect.right - rect.right).round();
      },

      'bottom': function(element) {
        var parent = hasLayout(element.getOffsetParent());
        var rect = element.getBoundingClientRect(),
         pRect = parent.getBoundingClientRect();

        return (pRect.bottom - rect.bottom).round();
      }
    });
  }

  Element.Offset = Class.create({
    initialize: function(left, top) {
      this.left = left.round();
      this.top  = top.round();

      this[0] = this.left;
      this[1] = this.top;
    },

    relativeTo: function(offset) {
      return new Element.Offset(
        this.left - offset.left,
        this.top  - offset.top
      );
    },

    inspect: function() {
      return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
    },

    toString: function() {
      return "[#{left}, #{top}]".interpolate(this);
    },

    toArray: function() {
      return [this.left, this.top];
    }
  });

  function getLayout(element, preCompute) {
    return new Element.Layout(element, preCompute);
  }

  function measure(element, property) {
    return $(element).getLayout().get(property);
  }

  function getDimensions(element) {
    element = $(element);
    var display = Element.getStyle(element, 'display');

    if (display && display !== 'none') {
      return { width: element.offsetWidth, height: element.offsetHeight };
    }

    var style = element.style;
    var originalStyles = {
      visibility: style.visibility,
      position:   style.position,
      display:    style.display
    };

    var newStyles = {
      visibility: 'hidden',
      display:    'block'
    };

    if (originalStyles.position !== 'fixed')
      newStyles.position = 'absolute';

    Element.setStyle(element, newStyles);

    var dimensions = {
      width:  element.offsetWidth,
      height: element.offsetHeight
    };

    Element.setStyle(element, originalStyles);

    return dimensions;
  }

  function getOffsetParent(element) {
    element = $(element);

    if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
      return $(document.body);

    var isInline = (Element.getStyle(element, 'display') === 'inline');
    if (!isInline && element.offsetParent) return $(element.offsetParent);

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

    return $(document.body);
  }


  function cumulativeOffset(element) {
    element = $(element);
    var valueT = 0, valueL = 0;
    if (element.parentNode) {
      do {
        valueT += element.offsetTop  || 0;
        valueL += element.offsetLeft || 0;
        element = element.offsetParent;
      } while (element);
    }
    return new Element.Offset(valueL, valueT);
  }

  function positionedOffset(element) {
    element = $(element);

    var layout = element.getLayout();

    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (isBody(element)) break;
        var p = Element.getStyle(element, 'position');
        if (p !== 'static') break;
      }
    } while (element);

    valueL -= layout.get('margin-top');
    valueT -= layout.get('margin-left');

    return new Element.Offset(valueL, valueT);
  }

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

  function viewportOffset(forElement) {
    element = $(element);
    var valueT = 0, valueL = 0, docBody = document.body;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == docBody &&
        Element.getStyle(element, 'position') == 'absolute') break;
    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (element != docBody) {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);
    return new Element.Offset(valueL, valueT);
  }

  function absolutize(element) {
    element = $(element);

    if (Element.getStyle(element, 'position') === 'absolute') {
      return element;
    }

    var offsetParent = getOffsetParent(element);
    var eOffset = element.viewportOffset(),
     pOffset = offsetParent.viewportOffset();

    var offset = eOffset.relativeTo(pOffset);
    var layout = element.getLayout();

    element.store('prototype_absolutize_original_styles', {
      left:   element.getStyle('left'),
      top:    element.getStyle('top'),
      width:  element.getStyle('width'),
      height: element.getStyle('height')
    });

    element.setStyle({
      position: 'absolute',
      top:    offset.top + 'px',
      left:   offset.left + 'px',
      width:  layout.get('width') + 'px',
      height: layout.get('height') + 'px'
    });

    return element;
  }

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

    var originalStyles =
     element.retrieve('prototype_absolutize_original_styles');

    if (originalStyles) element.setStyle(originalStyles);
    return element;
  }

  if (Prototype.Browser.IE) {
    getOffsetParent = getOffsetParent.wrap(
      function(proceed, element) {
        element = $(element);

        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
          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;
      }
    );

    positionedOffset = positionedOffset.wrap(function(proceed, element) {
      element = $(element);
      if (!element.parentNode) return new Element.Offset(0, 0);
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);

      var offsetParent = element.getOffsetParent();
      if (offsetParent && offsetParent.getStyle('position') === 'fixed')
        hasLayout(offsetParent);

      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    });
  } else if (Prototype.Browser.Webkit) {
    cumulativeOffset = function(element) {
      element = $(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 new Element.Offset(valueL, valueT);
    };
  }


  Element.addMethods({
    getLayout:              getLayout,
    measure:                measure,
    getDimensions:          getDimensions,
    getOffsetParent:        getOffsetParent,
    cumulativeOffset:       cumulativeOffset,
    positionedOffset:       positionedOffset,
    cumulativeScrollOffset: cumulativeScrollOffset,
    viewportOffset:         viewportOffset,
    absolutize:             absolutize,
    relativize:             relativize
  });

  function isBody(element) {
    return element.nodeName.toUpperCase() === 'BODY';
  }

  function isHtml(element) {
    return element.nodeName.toUpperCase() === 'HTML';
  }

  function isDocument(element) {
    return element.nodeType === Node.DOCUMENT_NODE;
  }

  function isDetached(element) {
    return element !== document.body &&
     !Element.descendantOf(element, document.body);
  }

  if ('getBoundingClientRect' in document.documentElement) {
    Element.addMethods({
      viewportOffset: function(element) {
        element = $(element);
        if (isDetached(element)) return new Element.Offset(0, 0);

        var rect = element.getBoundingClientRect(),
         docEl = document.documentElement;
        return new Element.Offset(rect.left - docEl.clientLeft,
         rect.top - docEl.clientTop);
      }
    });
  }
})();
window.$$ = function() {
  var expression = $A(arguments).join(', ');
  return Prototype.Selector.select(expression, document);
};

Prototype.Selector = (function() {

  function select() {
    throw new Error('Method "Prototype.Selector.select" must be defined.');
  }

  function match() {
    throw new Error('Method "Prototype.Selector.match" must be defined.');
  }

  function find(elements, expression, index) {
    index = index || 0;
    var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;

    for (i = 0; i < length; i++) {
      if (match(elements[i], expression) && index == matchIndex++) {
        return Element.extend(elements[i]);
      }
    }
  }

  function extendElements(elements) {
    for (var i = 0, length = elements.length; i < length; i++) {
      Element.extend(elements[i]);
    }
    return elements;
  }


  var K = Prototype.K;

  return {
    select: select,
    match: match,
    find: find,
    extendElements: (Element.extend === K) ? K : extendElements,
    extendElement: Element.extend
  };
})();
/*!
 * Sizzle CSS Selector Engine - v1.0
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true;

[0, 0].sort(function(){
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function(selector, context, results, seed) {
	results = results || [];
	var origContext = context = context || document;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}

	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
		soFar = selector;

	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
		soFar = m[3];

		parts.push( m[1] );

		if ( m[2] ) {
			extra = m[3];
			break;
		}
	}

	if ( parts.length > 1 && origPOS.exec( selector ) ) {
		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context );
		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] )
					selector += parts.shift();

				set = posProcess( selector, set );
			}
		}
	} else {
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
			var ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
		}

		if ( context ) {
			var ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray(set);
			} else {
				prune = false;
			}

			while ( parts.length ) {
				var cur = parts.pop(), pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}
		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		throw "Syntax error, unrecognized expression: " + (cur || selector);
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );
		} else if ( context && context.nodeType === 1 ) {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}
		} else {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}
	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function(results){
	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort(sortOrder);

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[i-1] ) {
					results.splice(i--, 1);
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function(expr, set){
	return Sizzle(expr, null, null, set);
};

Sizzle.find = function(expr, context, isXML){
	var set, match;

	if ( !expr ) {
		return [];
	}

	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
		var type = Expr.order[i], match;

		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			var left = match[1];
			match.splice(1,1);

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace(/\\/g, "");
				set = Expr.find[ type ]( match, context, isXML );
				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = context.getElementsByTagName("*");
	}

	return {set: set, expr: expr};
};

Sizzle.filter = function(expr, set, inplace, not){
	var old = expr, result = [], curLoop = set, match, anyFound,
		isXMLFilter = set && set[0] && isXML(set[0]);

	while ( expr && set.length ) {
		for ( var type in Expr.filter ) {
			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
				var filter = Expr.filter[ type ], found, item;
				anyFound = false;

				if ( curLoop == result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;
					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							var pass = not ^ !!found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;
								} else {
									curLoop[i] = false;
								}
							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		if ( expr == old ) {
			if ( anyFound == null ) {
				throw "Syntax error, unrecognized expression: " + expr;
			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],
	match: {
		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
	},
	leftMatch: {},
	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},
	attrHandle: {
		href: function(elem){
			return elem.getAttribute("href");
		}
	},
	relative: {
		"+": function(checkSet, part, isXML){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !/\W/.test(part),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag && !isXML ) {
				part = part.toUpperCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},
		">": function(checkSet, part, isXML){
			var isPartStr = typeof part === "string";

			if ( isPartStr && !/\W/.test(part) ) {
				part = isXML ? part : part.toUpperCase();

				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName === part ? parent : false;
					}
				}
			} else {
				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},
		"": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( !/\W/.test(part) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
		},
		"~": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( typeof part === "string" && !/\W/.test(part) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
		}
	},
	find: {
		ID: function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? [m] : [];
			}
		},
		NAME: function(match, context, isXML){
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [], results = context.getElementsByName(match[1]);

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},
		TAG: function(match, context){
			return context.getElementsByTagName(match[1]);
		}
	},
	preFilter: {
		CLASS: function(match, curLoop, inplace, result, not, isXML){
			match = " " + match[1].replace(/\\/g, "") + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
						if ( !inplace )
							result.push( elem );
					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},
		ID: function(match){
			return match[1].replace(/\\/g, "");
		},
		TAG: function(match, curLoop){
			for ( var i = 0; curLoop[i] === false; i++ ){}
			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
		},
		CHILD: function(match){
			if ( match[1] == "nth" ) {
				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}

			match[0] = done++;

			return match;
		},
		ATTR: function(match, curLoop, inplace, result, not, isXML){
			var name = match[1].replace(/\\/g, "");

			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},
		PSEUDO: function(match, curLoop, inplace, result, not){
			if ( match[1] === "not" ) {
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);
				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
					if ( !inplace ) {
						result.push.apply( result, ret );
					}
					return false;
				}
			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}

			return match;
		},
		POS: function(match){
			match.unshift( true );
			return match;
		}
	},
	filters: {
		enabled: function(elem){
			return elem.disabled === false && elem.type !== "hidden";
		},
		disabled: function(elem){
			return elem.disabled === true;
		},
		checked: function(elem){
			return elem.checked === true;
		},
		selected: function(elem){
			elem.parentNode.selectedIndex;
			return elem.selected === true;
		},
		parent: function(elem){
			return !!elem.firstChild;
		},
		empty: function(elem){
			return !elem.firstChild;
		},
		has: function(elem, i, match){
			return !!Sizzle( match[3], elem ).length;
		},
		header: function(elem){
			return /h\d/i.test( elem.nodeName );
		},
		text: function(elem){
			return "text" === elem.type;
		},
		radio: function(elem){
			return "radio" === elem.type;
		},
		checkbox: function(elem){
			return "checkbox" === elem.type;
		},
		file: function(elem){
			return "file" === elem.type;
		},
		password: function(elem){
			return "password" === elem.type;
		},
		submit: function(elem){
			return "submit" === elem.type;
		},
		image: function(elem){
			return "image" === elem.type;
		},
		reset: function(elem){
			return "reset" === elem.type;
		},
		button: function(elem){
			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
		},
		input: function(elem){
			return /input|select|textarea|button/i.test(elem.nodeName);
		}
	},
	setFilters: {
		first: function(elem, i){
			return i === 0;
		},
		last: function(elem, i, match, array){
			return i === array.length - 1;
		},
		even: function(elem, i){
			return i % 2 === 0;
		},
		odd: function(elem, i){
			return i % 2 === 1;
		},
		lt: function(elem, i, match){
			return i < match[3] - 0;
		},
		gt: function(elem, i, match){
			return i > match[3] - 0;
		},
		nth: function(elem, i, match){
			return match[3] - 0 == i;
		},
		eq: function(elem, i, match){
			return match[3] - 0 == i;
		}
	},
	filter: {
		PSEUDO: function(elem, match, i, array){
			var name = match[1], filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
			} else if ( name === "not" ) {
				var not = match[3];

				for ( var i = 0, l = not.length; i < l; i++ ) {
					if ( not[i] === elem ) {
						return false;
					}
				}

				return true;
			}
		},
		CHILD: function(elem, match){
			var type = match[1], node = elem;
			switch (type) {
				case 'only':
				case 'first':
					while ( (node = node.previousSibling) )  {
						if ( node.nodeType === 1 ) return false;
					}
					if ( type == 'first') return true;
					node = elem;
				case 'last':
					while ( (node = node.nextSibling) )  {
						if ( node.nodeType === 1 ) return false;
					}
					return true;
				case 'nth':
					var first = match[2], last = match[3];

					if ( first == 1 && last == 0 ) {
						return true;
					}

					var doneName = match[0],
						parent = elem.parentNode;

					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
						var count = 0;
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						}
						parent.sizcache = doneName;
					}

					var diff = elem.nodeIndex - last;
					if ( first == 0 ) {
						return diff == 0;
					} else {
						return ( diff % first == 0 && diff / first >= 0 );
					}
			}
		},
		ID: function(elem, match){
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},
		TAG: function(elem, match){
			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
		},
		CLASS: function(elem, match){
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},
		ATTR: function(elem, match){
			var name = match[1],
				result = Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value != check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},
		POS: function(elem, match, i, array){
			var name = match[2], filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS;

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
}

var makeArray = function(array, results) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}

	return array;
};

try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 );

} catch(e){
	makeArray = function(array, results) {
		var ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );
		} else {
			if ( typeof array.length === "number" ) {
				for ( var i = 0, l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}
			} else {
				for ( var i = 0; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return 0;
		}

		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( "sourceIndex" in document.documentElement ) {
	sortOrder = function( a, b ) {
		if ( !a.sourceIndex || !b.sourceIndex ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return 0;
		}

		var ret = a.sourceIndex - b.sourceIndex;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( document.createRange ) {
	sortOrder = function( a, b ) {
		if ( !a.ownerDocument || !b.ownerDocument ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return 0;
		}

		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
		aRange.setStart(a, 0);
		aRange.setEnd(a, 0);
		bRange.setStart(b, 0);
		bRange.setEnd(b, 0);
		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
}

(function(){
	var form = document.createElement("div"),
		id = "script" + (new Date).getTime();
	form.innerHTML = "<a name='" + id + "'/>";

	var root = document.documentElement;
	root.insertBefore( form, root.firstChild );

	if ( !!document.getElementById( id ) ) {
		Expr.find.ID = function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
			}
		};

		Expr.filter.ID = function(elem, match){
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );
	root = form = null; // release memory in IE
})();

(function(){

	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function(match, context){
			var results = context.getElementsByTagName(match[1]);

			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	div.innerHTML = "<a href='#'></a>";
	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {
		Expr.attrHandle.href = function(elem){
			return elem.getAttribute("href", 2);
		};
	}

	div = null; // release memory in IE
})();

if ( document.querySelectorAll ) (function(){
	var oldSizzle = Sizzle, div = document.createElement("div");
	div.innerHTML = "<p class='TEST'></p>";

	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
		return;
	}

	Sizzle = function(query, context, extra, seed){
		context = context || document;

		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
			try {
				return makeArray( context.querySelectorAll(query), extra );
			} catch(e){}
		}

		return oldSizzle(query, context, extra, seed);
	};

	for ( var prop in oldSizzle ) {
		Sizzle[ prop ] = oldSizzle[ prop ];
	}

	div = null; // release memory in IE
})();

if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
	var div = document.createElement("div");
	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	if ( div.getElementsByClassName("e").length === 0 )
		return;

	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 )
		return;

	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function(match, context, isXML) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	div = null; // release memory in IE
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	var sibDir = dir == "previousSibling" && !isXML;
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			if ( sibDir && elem.nodeType === 1 ){
				elem.sizcache = doneName;
				elem.sizset = i;
			}
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem.sizcache = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	var sibDir = dir == "previousSibling" && !isXML;
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			if ( sibDir && elem.nodeType === 1 ) {
				elem.sizcache = doneName;
				elem.sizset = i;
			}
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem.sizcache = doneName;
						elem.sizset = i;
					}
					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

var contains = document.compareDocumentPosition ?  function(a, b){
	return a.compareDocumentPosition(b) & 16;
} : function(a, b){
	return a !== b && (a.contains ? a.contains(b) : true);
};

var isXML = function(elem){
	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
		!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
};

var posProcess = function(selector, context){
	var tmpSet = [], later = "", match,
		root = context.nodeType ? [context] : context;

	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet );
	}

	return Sizzle.filter( later, tmpSet );
};


window.Sizzle = Sizzle;

})();

Prototype._original_property = window.Sizzle;

;(function(engine) {
  var extendElements = Prototype.Selector.extendElements;

  function select(selector, scope) {
    return extendElements(engine(selector, scope || document));
  }

  function match(element, selector) {
    return engine.matches(selector, [element]).length == 1;
  }

  Prototype.Selector.engine = engine;
  Prototype.Selector.select = select;
  Prototype.Selector.match = match;
})(Sizzle);

window.Sizzle = Prototype._original_property;
delete Prototype._original_property;

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, accumulator, initial;

    if (options.hash) {
      initial = {};
      accumulator = function(result, key, value) {
        if (key in result) {
          if (!Object.isArray(result[key])) result[key] = [result[key]];
          result[key].push(value);
        } else result[key] = value;
        return result;
      };
    } else {
      initial = '';
      accumulator = function(result, key, value) {
        return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value);
      }
    }

    return elements.inject(initial, 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)))) {
          result = accumulator(result, key, value);
        }
      }
      return result;
    });
  }
};

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);
    var element = form.findFirstElement();
    if (element) element.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 = (function() {
  function input(element, value) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return inputSelector(element, value);
      default:
        return valueSelector(element, value);
    }
  }

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

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

  function select(element, value) {
    if (Object.isUndefined(value))
      return (element.type === 'select-one' ? selectOne : selectMany)(element);

    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);
    }
  }

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

  function selectMany(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(optionValue(opt));
    }
    return values;
  }

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

  return {
    input:         input,
    inputSelector: inputSelector,
    textarea:      valueSelector,
    select:        select,
    selectOne:     selectOne,
    selectMany:    selectMany,
    optionValue:   optionValue,
    button:        valueSelector
  };
})();

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


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 isIELegacyEvent = function(event) { return false; };

  if (window.attachEvent) {
    if (window.addEventListener) {
      isIELegacyEvent = function(event) {
        return !(event instanceof window.Event);
      };
    } else {
      isIELegacyEvent = function(event) { return true; };
    }
  }

  var _isButton;

  function _isButtonForDOMEvents(event, code) {
    return event.which ? (event.which === code + 1) : (event.button === code);
  }

  var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
  function _isButtonForLegacyEvents(event, code) {
    return event.button === legacyButtonMap[code];
  }

  function _isButtonForWebKit(event, code) {
    switch (code) {
      case 0: return event.which == 1 && !event.metaKey;
      case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
      case 2: return event.which == 3;
      default: return false;
    }
  }

  if (window.attachEvent) {
    if (!window.addEventListener) {
      _isButton = _isButtonForLegacyEvents;
    } else {
      _isButton = function(event, code) {
        return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
         _isButtonForDOMEvents(event, code);
      }
    }
  } else if (Prototype.Browser.WebKit) {
    _isButton = _isButtonForWebKit;
  } else {
    _isButton = _isButtonForDOMEvents;
  }

  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;
    while (element) {
      if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
        return Element.extend(element);
      }
      element = element.parentNode;
    }
  }

  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 (window.attachEvent) {
    function _relatedTarget(event) {
      var element;
      switch (event.type) {
        case 'mouseover':
        case 'mouseenter':
          element = event.fromElement;
          break;
        case 'mouseout':
        case 'mouseleave':
          element = event.toElement;
          break;
        default:
          return null;
      }
      return Element.extend(element);
    }

    var additionalMethods = {
      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 (!isIELegacyEvent(event)) return event;

      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
      });

      Object.extend(event, methods);
      Object.extend(event, additionalMethods);

      return event;
    };
  } else {
    Event.extend = Prototype.K;
  }

  if (window.addEventListener) {
    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
    Object.extend(Event.prototype, methods);
  }

  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,
      translations = { mouseenter: "mouseover", mouseleave: "mouseout" };

  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
    _getDOMEventName = function(eventName) {
      return (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("onlosecapture", 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 (!registry) return element;

    if (!eventName) {
      registry.each( function(pair) {
        var eventName = pair.key;
        stopObserving(element, eventName);
      });
      return element;
    }

    var responders = registry.get(eventName);
    if (!responders) return element;

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

    var i = responders.length, responder;
    while (i--) {
      if (responders[i].handler === handler) {
        responder = responders[i];
        break;
      }
    }
    if (!responder) return element;

    if (eventName.include(':')) {
      if (element.removeEventListener)
        element.removeEventListener("dataavailable", responder, false);
      else {
        element.detachEvent("ondataavailable", responder);
        element.detachEvent("onlosecapture", responder);
      }
    } else {
      var actualEventName = _getDOMEventName(eventName);
      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', bubble, true);
    } else {
      event = document.createEventObject();
      event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
    }

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

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

    return Event.extend(event);
  }

  Event.Handler = Class.create({
    initialize: function(element, eventName, selector, callback) {
      this.element   = $(element);
      this.eventName = eventName;
      this.selector  = selector;
      this.callback  = callback;
      this.handler   = this.handleEvent.bind(this);
    },

    start: function() {
      Event.observe(this.element, this.eventName, this.handler);
      return this;
    },

    stop: function() {
      Event.stopObserving(this.element, this.eventName, this.handler);
      return this;
    },

    handleEvent: function(event) {
      var element = Event.findElement(event, this.selector);
      if (element) this.callback.call(this.element, event, element);
    }
  });

  function on(element, eventName, selector, callback) {
    element = $(element);
    if (Object.isFunction(selector) && Object.isUndefined(callback)) {
      callback = selector, selector = null;
    }

    return new Event.Handler(element, eventName, selector, callback).start();
  }

  Object.extend(Event, Event.Methods);

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

  Element.addMethods({
    fire:          fire,

    observe:       observe,

    stopObserving: stopObserving,

    on:            on
  });

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

    observe:       observe.methodize(),

    stopObserving: stopObserving.methodize(),

    on:            on.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);

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

(function() {
  window.Selector = Class.create({
    initialize: function(expression) {
      this.expression = expression.strip();
    },

    findElements: function(rootElement) {
      return Prototype.Selector.select(this.expression, rootElement);
    },

    match: function(element) {
      return Prototype.Selector.match(element, this.expression);
    },

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

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

  Object.extend(Selector, {
    matchElements: function(elements, expression) {
      var match = Prototype.Selector.match,
          results = [];

      for (var i = 0, length = elements.length; i < length; i++) {
        var element = elements[i];
        if (match(element, expression)) {
          results.push(Element.extend(element));
        }
      }
      return results;
    },

    findElement: function(elements, expression, index) {
      index = index || 0;
      var matchIndex = 0, element;
      for (var i = 0, length = elements.length; i < length; i++) {
        element = elements[i];
        if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
          return Element.extend(element);
        }
      }
    },

    findChildElements: function(element, expressions) {
      var selector = expressions.toArray().join(', ');
      return Prototype.Selector.select(selector, element || document);
    }
  });
})();

Ajax.Responders.register({
    onCreate: function(request){
	if(!this.requests){
	    this.requests = {};
	}
	if(request.options.id){
	    if(this.requests[request.options.id]){
		this.requests[request.options.id].transport.abort();
	    }
	    this.requests[request.options.id] = request;
	}
    },
    onComplete: function(request){
	if(request.options.id && this.requests[request.options.id]){
	    this.requests[request.options.id] = false;
	}
    }
});
Form.populate = function(form, values){
    $(form).getElements().each(function(el){
        if(values[el.name] != undefined){
            $(el).setValue(values[el.name]);
        }
    });
};
var moving={};
var kfElements=new Object();

setTimeout(function() {
    //used for future tests and stuff
    
    //alert(1);
    //alert(kfElements.get('country').element.value);
    //alert(2);
    //alert(kfElements.get('country').element.value);
    //alert('dude... there are two country-label elements... hay!');
    
},2500);
//v Durex
kfElements.fElementsList = {};
kfElements.fElements={'dualSlider':'kDualSlider','slider':'kSlider','spinner':'kSpinner','autocomplete':'kAutoComplete','toggleButton':'kToggleButton','datePicker':'kDatePicker'};
kfElements.get = function(el){
    el = $(el);
    var id = el.identify();
    var kElement = kfElements.fElementsList[id];
    if(kfElements.fElementsList[id] == undefined || kfElements.fElementsList[id].element != el){
	
	el.classNames().each(function(c){
	    if(c in kfElements.fElements && typeof(kfElements[kfElements.fElements[c]]) == 'function'){
		kfElements.fElementsList[id] = new kfElements[kfElements.fElements[c]](el);
	    }
	});
    }
    return kfElements.fElementsList[id];
};

kfElements.init=function(settings, el){
    if(el==undefined) el=document.body;
    el = $(el);
    kfElements.settings = {
	'autoCompletePath': '/autocomplete'
    };
    Object.extend(kfElements.settings, settings || {});
    el.select('input[type=text]').each(function(s){
	kfElements.get(s);
    });
};

kfElements.kFormElement=Class.create(
{
    initialize: function(element)
    {
	this.properties={};
        this.element=element;
        this.getProperties();
	this.getKFormElement();
    },
    getKFormElement: function()
    {
//	kfElements.fElementsList[this.element.id]=this;
    },
    getProperties: function()
    {
	$w(this.element.className).each(function(s)
	    {
		if(s.split('-').length==2)
		{
		    var property=s.split('-')[0]; var value=s.split('-')[1];
		    if(this.properties[property]!=undefined)
		    {
			if(!isNaN(parseInt(value)))
			{
			    value=value.replace(/\+/g,"-");
			    if(parseInt(value)==value) value=parseInt(value); else
			    {
				if(parseInt(value)==value) value=parseInt(value);
			    }
			}
			else value=value.replace(/\_/g,' ');
			this.properties[property]=value;
			this.element.removeClassName(s);
		    }
		}
	    }.bind(this));
    },   
    debug: function(test)
    {
        this.element.value=test;
    },
    deFocus: function() //to remove in the next versioun if no use will be found
    {
	setTimeout(function() { $('dummyInput').focus(); },1);
    },
    getElementProperties: function(element)
    {
	var borderWidth=parseInt(element.getStyle('border-left-width').split('px')[0])+parseInt(element.getStyle('border-right-width').split('px')[0]);
	var borderHeight=parseInt(element.getStyle('border-top-width').split('px')[0])+parseInt(element.getStyle('border-bottom-width').split('px')[0]);
	var width=this.element.getWidth();
	var height=this.element.getHeight();
	var color=element.getStyle('color');
	var backgroundColor=element.getStyle('background-color');
	if(backgroundColor=='transparent') backgroundColor='#fff';
	var fontSize=element.getStyle('font-size');
	return {'borderWidth':borderWidth,'borderHeight':borderHeight,'width':width,'height':height,'color':color,'backgroundColor':backgroundColor,'fontSize':fontSize};
    },
    changeCursor: function (element,cursor)
    {
	this.cursor=new Object();
	this.cursor.element=element;
	this.cursor.origZIndex=element.getStyle('z-index');
	this.cursor.cover=new Element('div',{'style':'position:fixed;width:100%;height:100%;top:0;left:0;padding:0;z-index:100;background-color:transparent;cursor:'+cursor+';'});
	document.body.appendChild(this.cursor.cover);
	element.setStyle({'z-index':150});
    },
    restoreCursor: function()
    {
	this.cursor.element.setStyle({'z-index':this.cursor.origZIndex});
	this.cursor.cover.remove();
    }
});

kfElements.kToggleButton = Class.create(kfElements.kFormElement, {
    initialize: function(element)
    {
	this.properties={'labelOn':'on','labelOff':'off'};
        this.element=element;
        this.getProperties();
	this.renderToggleButton();
	this.addEvents();
	this.getValue();
	this.getKFormElement();
    },
    renderToggleButton: function()
    {
	var elementProperties=this.getElementProperties(this.element);
	var toggleButtonWidth=elementProperties.width;
	var toggleButtonHeight=elementProperties.height-elementProperties.borderHeight;;
	this.element.hide();
	this.toggleButton=new Element('div',{'style':'text-align:center;color:'+elementProperties.backgroundColor+';font-weight:bold;background-color:'+elementProperties.color+';font-size:'+elementProperties.fontSize+';line-height:'+toggleButtonHeight+'px;margin-top:0px;display:inline-block;width:'+toggleButtonWidth+'px;'});
        this.element.parentNode.insertBefore(this.toggleButton, this.element.nextSibling);
    },
    addEvents: function()
    {
	this.toggleButton.observe('mousedown', function(event) { event.stop(); this.toggle(); }.bindAsEventListener(this) );
    },
    toggle: function()
    {
	var newValue=null;
	var newLabel=null;
	if(this.element.value==1) { newValue=0; newLabel=this.properties.labelOff; }
	else { newValue=1; newLabel=this.properties.labelOn; }
	this.debug(newValue);
	this.toggleButton.update(newLabel);
    },
    getValue: function()
    {
	if(parseInt(this.element.value)==0) this.element.value=1; else this.element.value=0;
	this.toggle();
    }
});

kfElements.kSpinner = Class.create(kfElements.kFormElement, {
    initialize: function(element)
    {
	this.properties={'min':0,'max':100,'stepping':1,'prefix':'','sufix':''};
        this.element=element;
        this.getProperties();
	this.renderSpinner();
	this.addEvents();
	this.setValue('init');
	this.getKFormElement();
    },
    renderSpinner: function()
    {
	var elementProperties=this.getElementProperties(this.element);
	var spinnerWidth=elementProperties.width;
	var spinnerHeight=elementProperties.height;
	this.element.hide();
	var spinnerDiv=new Element('div',{'style':'text-align:center;margin-top:0px;display:inline-block;width:'+spinnerWidth+'px;'});
	this.spinnerDisplay=new Element('input',{'type':'text','style':'margin:0px;width:'+(spinnerWidth-50)+'px;'});
	this.spinnerDec=new Element('div',{'style':'float:left;display:inline-block;width:20px;height:'+(spinnerHeight)+'px;background-color:'+elementProperties.color+';background-image:url(\'/static/img/arr_left.png\');background-position:center;background-repeat:no-repeat;'});
	this.spinnerInc=new Element('div',{'style':'float:right;display:inline-block;width:20px;height:'+(spinnerHeight)+'px;background-color:'+elementProperties.color+';background-image:url(\'/static/img/arr_right.png\');background-position:center;background-repeat:no-repeat;'});
	spinnerDiv.appendChild(this.spinnerDec);
	spinnerDiv.appendChild(this.spinnerDisplay);
	spinnerDiv.appendChild(this.spinnerInc);
        this.element.parentNode.insertBefore(spinnerDiv, this.element.nextSibling);
    },
    addEvents: function()
    {
	this.spinnerInc.observe('mousedown', function(event) { event.stop(); this.setValue('inc'); }.bindAsEventListener(this) );
	this.spinnerDec.observe('mousedown', function(event) { event.stop(); this.setValue('dec'); }.bindAsEventListener(this) );
	this.spinnerDisplay.observe('change', function(event) { this.setValue(); }.bindAsEventListener(this) );
    },
    setValue: function(modifier)
    {
	if(modifier==undefined)
	{
	    if(this.spinnerDisplay.value.length>0)
	    {
		value=parseInt(this.spinnerDisplay.value.replace(this.properties.prefix.replace(' ','')).replace(this.properties.sufix.replace(' ','')).match(/[\d\.]+/g)[0]);
		if(value>this.properties.max) value=this.properties.max;
		if(value<this.properties.min) value=this.properties.min;
	    }
	    else value=parseInt(this.element.value);
	}
	else
	{
	    if(modifier=='inc' || modifier=='dec')
	    {
		if(modifier=='inc') modifier=this.properties.stepping;
		else if(modifier=='dec') modifier=-this.properties.stepping;
		value=parseInt(this.element.value)+modifier;
		if(value>this.properties.max) value=this.properties.min;
		if(value<this.properties.min) value=this.properties.max;
	    }
	    else if(modifier=='init')
	    {
		value=parseInt(this.element.value);
	    }
	}
	if(isNaN(value)) value=this.properties.min;
	this.spinnerDisplay.value=this.properties.prefix+value+this.properties.sufix;
	this.debug(value);
    }
});

kfElements.kSlider = Class.create(kfElements.kFormElement, {
    initialize: function(element)
    {
	this.properties={'min':0,'max':100,'stepping':1,'prefix':'','sufix':''};
        this.element=element;
        this.getProperties();
	this.renderSlider();
	this.addEvents();
	this.getKFormElement();
    },
    renderSlider: function()
    {
	var elementProperties=this.getElementProperties(this.element);
	var sliderWidth=elementProperties.width;
	this.element.hide();
	var sliderBar=new Element('div',{'style':'margin-top:10px;display:inline-block;height:10px;width:'+sliderWidth+'px;background-image:url(\'/static/img/sliderbgc.gif\');background-position:top;background-repeat:repeat-x;'}); //consider a cursor:url('custom'); option in the future
	var sliderBarLeft=new Element('img',{'src':'/static/img/sliderbgl.gif','style':'float:left;'});
	var sliderBarRight=new Element('img',{'src':'/static/img/sliderbgr.gif','style':'float:right;'});
	sliderBar.appendChild(sliderBarLeft);
	sliderBar.appendChild(sliderBarRight);
	this.widthExtremities=2;
	this.slider=new Element('img',{'src':'/static/img/spin_down.png','style':'margin-top:1px;margin-left:'+(this.widthExtremities)+'px;position:absolute;cursor:ew-resize;'});
	if(navigator.userAgent.search(/opera/i)>=0) { this.slider.setStyle({'cursor':'e-resize'}); }
	sliderBar.appendChild(this.slider);
	this.slider.observe('load', function(event)
	{
	    this.sliderMarginMax=(sliderWidth-this.slider.width-sliderBarRight.width-this.widthExtremities);
	    this.element.parentNode.insertBefore(sliderBar, this.element.nextSibling);
	    this.setValues();
	}.bindAsEventListener(this) );
    },
    addEvents: function()
    {
        this.slider.observe('mousedown', function(event) { this.startMovingSlider(event); }.bindAsEventListener(this) );
    },
    startMovingSlider: function(event)
    {
	this.mouseMoveHandler = function(event){ this.doMove(event); }.bindAsEventListener(this);
	this.mouseUpHandler = function(event){ this.stopMovingSlider(event); }.bindAsEventListener(this);
	moving.element=this.slider;
	moving.marginLeft=parseInt(this.slider.style.marginLeft.split('px')[0]);
	moving.startX=event.pointerX();
	moving.geometry=this.getGeometry(this.slider);
	document.observe('mouseup',this.mouseUpHandler);
	document.observe('mousemove', this.mouseMoveHandler);
	this.changeCursor(this.slider,this.slider.getStyle('cursor'));
	event.stop();
    },
    stopMovingSlider: function(event)
    {
	document.stopObserving('mouseup',this.mouseUpHandler);
	document.stopObserving('mousemove',this.mouseMoveHandler);
	this.restoreCursor();
	this.getValues();
    },
    doMove: function(event)
    {
	element=this.slider;
	var newValue=(event.pointerX()-moving.startX+moving.marginLeft);
	if(moving.geometry.min<=newValue && newValue<=moving.geometry.max) element.style.marginLeft=newValue+'px';
	else if(moving.geometry.min>newValue) element.style.marginLeft=moving.geometry.min+'px';
	else if(moving.geometry.max<newValue) element.style.marginLeft=moving.geometry.max+'px';
	this.getValues();
	event.stop();
    },
    getGeometry: function(element)
    {
	return {'min':parseInt(this.widthExtremities),'max':this.sliderMarginMax};
    },
    getValues: function(element)
    {
	var scaleValues=this.properties.max-this.properties.min;
	var scaleSlider=parseInt(this.sliderMarginMax-this.widthExtremities);
	var min=this.properties.min;
	var max=this.properties.max;
	value=Math.floor(((parseInt(this.slider.style.marginLeft.split('px')[0])-this.widthExtremities)/scaleSlider*scaleValues)+min);
	if(value!=this.properties.min && value!=this.properties.max) value=Math.floor(value/this.properties.stepping)*this.properties.stepping;
	this.value=value;
	this.showValues();
	this.debug(value);
    },
    setValues: function()
    {
	var scaleValues=this.properties.max-this.properties.min;
	var scaleSlider=parseInt(this.sliderMarginMax-this.widthExtremities);
	var slider=this.element.value;
	var sliderMargin=Math.ceil((scaleSlider/scaleValues)*(slider-this.properties.min)+this.widthExtremities);
	if(sliderMargin<this.widthExtremities) sliderMargin=this.widthExtremities;
	if(sliderMargin>parseInt(this.widthExtremities+scaleSlider)) sliderMargin=this.widthExtremities+scaleSlider;
	this.slider.style.marginLeft=sliderMargin+'px';
    },
    showValues: function()
    {
	var offSet=-4;
	var info=new Element('span',{'style':'margin-left:0px;padding:0px;text-align:center;'}).update(this.properties.prefix+this.value+this.properties.sufix);
        this.element.nextSibling.nextSibling.update(info);
	var spacingLeft=this.slider.style.marginLeft.split('px')[0]-(info.getWidth()/2+offSet);
	if(spacingLeft<0) spacingLeft=0;
	if(spacingLeft>info.parentNode.getWidth()-info.getWidth()+offSet) spacingLeft=info.parentNode.getWidth()-info.getWidth()+offSet;
	info.setStyle({marginLeft:spacingLeft+'px'});
    },
});

kfElements.kDualSlider = Class.create(kfElements.kFormElement, {
    initialize: function(element)
    {
	this.properties={'min':0,'max':100,'stepping':1,'prefix':'','sufix':''};
        this.element=element;
        this.getProperties();
	this.renderSlider();
	this.addEvents();
	this.getKFormElement();
    },
    renderSlider: function()
    {
	var elementProperties=this.getElementProperties(this.element);
	var sliderWidth=elementProperties.width;
	this.element.hide();
	var sliderBar=new Element('div',{'style':'margin-top:10px;display:inline-block;height:10px;width:'+sliderWidth+'px;background-image:url(\'/static/img/sliderbgc.gif\');background-position:top;background-repeat:repeat-x;'});
	var sliderBarLeft=new Element('img',{'src':'/static/img/sliderbgl.gif','style':'float:left;'});
	var sliderBarRight=new Element('img',{'src':'/static/img/sliderbgr.gif','style':'float:right;'});
	sliderBar.appendChild(sliderBarLeft);
	sliderBar.appendChild(sliderBarRight);
	this.widthExtremities=2;
	this.sliderMin=new Element('img',{'src':'/static/img/spin_down.png','style':'margin-top:1px;margin-left:'+(this.widthExtremities)+'px;position:absolute;cursor:ew-resize'});
	if(navigator.userAgent.search(/opera/i)>=0) { this.sliderMin.setStyle({'cursor':'e-resize'}); }
	this.sliderMax=new Element('img',{'src':'/static/img/spin_down.png','style':'margin-top:1px;position:absolute;cursor:ew-resize;'});
	if(navigator.userAgent.search(/opera/i)>=0) { this.sliderMin.setStyle({'cursor':'w-resize'}); }
	sliderBar.appendChild(this.sliderMin);
	this.sliderMax.observe('load',function(event)
	{
	    this.sliderMarginMax=(sliderWidth-this.sliderMin.width-sliderBarRight.width-this.widthExtremities);
	    this.sliderMax.setStyle({'marginLeft':this.sliderMarginMax+'px'});
	    sliderBar.appendChild(this.sliderMax);
	    this.element.parentNode.insertBefore(sliderBar, this.element.nextSibling);
	    this.setValues();
	}.bindAsEventListener(this) );
    },
    addEvents: function()
    {
        this.sliderMin.observe('mousedown', function(event) { this.startMovingSlider(event,this.sliderMin); }.bindAsEventListener(this) );
	this.sliderMax.observe('mousedown', function(event) { this.startMovingSlider(event,this.sliderMax); }.bindAsEventListener(this) );
    },
    startMovingSlider: function(event,element)
    {
        this.debug('startObserving');
	this.mouseMoveHandler = function(event){ this.doMove(event); }.bindAsEventListener(this);
	this.mouseUpHandler = function(event){ this.stopMovingSlider(event); }.bindAsEventListener(this);
	moving.element=element;
	moving.marginLeft=parseInt(element.style.marginLeft.split('px')[0]);
	moving.startX=event.pointerX();
	moving.geometry=this.getGeometry(element);
	document.observe('mouseup',this.mouseMoveHandler);
	document.observe('mousemove',this.mouseUpHandler);
	this.changeCursor(element,this.sliderMin.getStyle('cursor'));
	event.stop();
    },
    stopMovingSlider: function(event,element)
    {
	document.stopObserving('mouseup',this.mouseUpHandler);
	document.stopObserving('mousemove',this.mouseMoveHandler);
	this.restoreCursor();
	this.getValues();
    },
    /////to fix this mess
    doMove: function(event,element)
    {
	//this.debug('move - X='+event.pointerX()+'px');
	var newValue=(event.pointerX()-moving.startX+moving.marginLeft);
	if(moving.geometry.min<=newValue && newValue<=moving.geometry.max) element.style.marginLeft=newValue+'px';
	else if(moving.geometry.min>newValue) element.style.marginLeft=moving.geometry.min+'px';
	else if(moving.geometry.max<newValue) element.style.marginLeft=moving.geometry.max+'px';
	this.getValues();
	event.stop();
    },
    getGeometry: function(element)
    {
	if(element===this.sliderMin) return {'min':parseInt(this.widthExtremities),'max':parseInt(parseInt(this.sliderMax.style.marginLeft.split('px')[0])-this.sliderMin.width)};
	if(element===this.sliderMax) return {'min':parseInt(parseInt(this.sliderMin.style.marginLeft.split('px')[0])+this.sliderMin.width),'max':this.sliderMarginMax};
    },
    getValues: function(element)
    {
	var scaleValues=this.properties.max-this.properties.min;
	var scaleSlider=parseInt(this.sliderMarginMax-this.widthExtremities);
	var min=this.properties.min;
	var max=this.properties.max;
	min=Math.floor(((parseInt(this.sliderMin.style.marginLeft.split('px')[0])-this.widthExtremities)/scaleSlider*scaleValues)+min);
	if(min!=this.properties.min) min=Math.floor(min/this.properties.stepping)*this.properties.stepping;
	max=Math.floor(((parseInt(this.sliderMax.style.marginLeft.split('px')[0])-this.widthExtremities)/scaleSlider*scaleValues)+this.properties.min);
	if(max!=this.properties.max) max=Math.floor(max/this.properties.stepping)*this.properties.stepping;
	this.value={'min':min,'max':max};
	this.showValues();
	this.debug(min+'-'+max);
    },
    setValues: function()
    {
	var scaleValues=this.properties.max-this.properties.min;
	var scaleSlider=parseInt(this.sliderMarginMax-this.widthExtremities);
	//var min=this.properties.min;
	//var max=this.properties.max;
	var min=this.element.value.split('-')[0];
	var max=this.element.value.split('-')[1];
	var sliderMinMargin=Math.ceil((scaleSlider/scaleValues)*(min-this.properties.min)+this.widthExtremities);
	var sliderMaxMargin=Math.ceil((scaleSlider/scaleValues)*(max-this.properties.min)+this.widthExtremities);
	if(sliderMinMargin<this.widthExtremities) sliderMinMargin=this.widthExtremities;
	if(sliderMaxMargin>parseInt(this.widthExtremities+scaleSlider)) sliderMaxMargin=this.widthExtremities+scaleSlider;
	this.sliderMin.style.marginLeft=sliderMinMargin+'px';
	this.sliderMax.style.marginLeft=sliderMaxMargin+'px';
	//max=Math.floor(((parseInt(this.sliderMax.style.marginLeft.split('px')[0])-this.widthExtremities)/scaleSlider*scaleValues)+this.properties.min);
	//if(max!=this.properties.max) max=Math.floor(max/this.properties.stepping)*this.properties.stepping;
    },
    showValues: function()
    {
        this.element.nextSibling.nextSibling.update('Min '+this.properties.prefix+this.value.min+this.properties.sufix +'<span style="float:right;padding-right:5px;">Max '+this.properties.prefix+this.value.max+this.properties.sufix+'</span>');
    },
});

kfElements.kAutoComplete = Class.create(kfElements.kFormElement, {
    lastsearch: [],
    lastsearch_options: {},
    suggestionsDiv: null,
    initialize: function(element)
    {
// proposals
//	two search modes - search anywhere in the strings [example, in (cheese, goose, sex, seven, peanuts), if searchAnywhere is true and the searchString is 'se' (cheese,goose,sex,seven) will be matched]
//				if it's false, only (sex,seven) will be matched [this must be implemented also in AutoCompleteRequest]
//	minSearchString - the minimum lenth of this.display.length to trigger a getSuggestions [lower of searchAnywhere false, higher if true]
//
//	opinions?

	this.properties={'length':3,'dynamic':'false','source':'','searchAnywhere':'false','minSearchString':1,'force':'true','noOption':'Select option...','delay':500};
        this.element=element;
        this.getProperties();
	this.renderAutoComplete();
	this.getOptions('init');
	this.addEvents();
	this.selected=null;
	this.getKFormElement();
    },
    renderAutoComplete: function()
    {
	this.element.hide();
	this.display=new Element('input',{'name':this.element.id+'-label','autocomplete':'off','type':'text','style':'margin:0px;','readonly':this.element.readonly || false,'disabled':this.element.disabled || false});
        this.element.parentNode.insertBefore(this.display, this.element.nextSibling);
    },
    addEvents: function()
    {
	this.display.observe('focus', function(event) { if(this.display.value==this.properties.noOption) this.display.value=''; }.bindAsEventListener(this) );
	this.display.observe('keydown', function(event) { this.quickPress(event); }.bindAsEventListener(this) );
	this.display.observe('keyup', function(event) { this.slowPress(event); }.bindAsEventListener(this) );
	this.display.observe('blur', function(event)
	{
	    if(this.OverSuggestions==false)
	    {
		if(this.suggestions.length==1 && this.properties.force=='true') this.setValue(this.suggestions[0]);
		this.clearDivDisplay();
	    }
	    if(this.properties.force=='true' && this.element.value=='invalid') this.display.value=this.properties.noOption;
	}.bindAsEventListener(this) );
    },
    quickPress: function(event)
    {
	this.display.removeClassName('kNoResults');
	var keys={40:'down',38:'up',13:'enter',27:'escape'};
	if(event.keyCode in keys)
	{
	    switch(keys[event.keyCode])
	    {
		case 'enter':
		{
		    if(this.suggestionsDiv!=null)
		    {
			event.stop();
			if(this.selected!=null)
			this.selected.fire('kForm:enter');
		    }
		    break;
		}
		case 'up':
		{
		    event.stop();
		    if(this.suggestionsDiv==null) break;
		    var targets=this.suggestionsDiv.children;
		    if(this.selected==null)
		    {
			targets[targets.length-1].fire('kForm:select');
			this.suggestionsDiv.scrollTop=(targets.length-1)*targets[targets.length-1].getHeight();
		    }
		    else
		    {
			done=false;
			$A(targets).each(function(s,index)
			{
			    if(done==false && this.selected==s)
			    {
				s.fire('kForm:unselect');
				newIndex=index-1;
				if(newIndex<0) newIndex=targets.length-1;
				targets[newIndex].fire('kForm:select');
				this.suggestionsDiv.scrollTop=targets[newIndex].positionedOffset().top-(this.suggestionsDiv.getHeight()/2)+(targets[newIndex].getHeight()/2);
				done=true;
			    }
			}.bind(this));
		    }
		    break;
		}
		case 'down':
		{
		    event.stop();
		    if(this.suggestionsDiv==null) break;
		    var targets=this.suggestionsDiv.children;
		    if(this.selected==null)
		    {
			targets[0].fire('kForm:select');
			this.suggestionsDiv.scrollTop=0;
		    }
		    else
		    {
			done=false;
			$A(targets).each(function(s,index)
			{
			    if(done==false && this.selected==s)
			    {
				s.fire('kForm:unselect');
				newIndex=index+1;
				if(newIndex>targets.length-1) newIndex=0;
				targets[newIndex].fire('kForm:select');
				this.suggestionsDiv.scrollTop=targets[newIndex].positionedOffset().top-(this.suggestionsDiv.getHeight()/2)+(targets[newIndex].getHeight()/2);
				done=true;
			    }
			}.bind(this));
		    }
		    break;
		}
		case 'escape':
		{
		    this.clearDivDisplay();
		    break;
		}
	    }
	}
    },
    slowPress: function(event)
    {
	this.display.removeClassName('kNoResults');
	var keys={40:'down',38:'up',13:'enter',27:'escape'};
	if(event.keyCode in keys) { event.stop(); return; }
	if(event.keyCode!=8 || this.display.value.length>this.properties.minSearchString-1){
	    this.getSuggestions();
	}else{
	    this.clearDivDisplay();
	    if(this.request){
		this.request.transport.abort();
	    }
	    if(this.timer){
		clearTimeout(this.timer);
	    }
	    this.display.removeClassName('kLoading');
	}
    },
    getOptions: function(runAfter)
    {
	var toPostObject={};
	var requestPath=kfElements.settings.autoCompletePath + '/' + this.properties.source.split('%').join('/');
	if(this.element.value=='') { this.display.value=this.properties.noOption; /* return; WHY? */}

	var ss = this.display.value.toLowerCase();
	var lsindex = this.lastsearch.indexOf(ss);
	if(lsindex == -1){ //or not  lastsearch_options
	    for(var i=this.lastsearch.length-1;i>=0;i--){
		if(this.lastsearch[i].substr(0, ss.length) == ss && this.lastsearch_options[i]){
		    var lsindex = lastsearch.length;
		    var options = {};
		    var lsok = this.lastsearch_options[i].keys();
		    for(var j=0;j<lsok.length;j++){
			
		    }
		}
	    }
	}
	if(lsindex > -1 && this.lastsearch_options[lsindex]){
	    this.options = this.lastsearch_options[lsindex];
	    this.checkOptions();
	    if(runAfter != undefined) runAfter();
	    return;
	}
/*	var lsindex = this.lastsearch.indexOf(this.display.value.toLowerCase());
	if(lsindex > -1 && this.lastsearch_options[lsindex]){
	    this.options = this.lastsearch_options[lsindex];
	    this.checkOptions();
	    if(runAfter != undefined) runAfter();
	    return;
	}
*/
	this.lastsearch.push(ss);
	if(this.properties.dynamic=='true' && runAfter!='init')
	{
	    toPostObject={'source':this.properties.source,'search':this.display.value,'searchAnywhere':this.properties.searchAnywhere};
	    this.request = new Ajax.Request(requestPath, {id: 'autocomplete-' + this.element.id, postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport)
	    {
		this.options=transport.responseText.evalJSON();
		this.checkOptions();
		var lsindex = this.lastsearch.length - 1;
		this.lastsearch_options[lsindex] = this.options;
		if(runAfter!=undefined) runAfter();
	    }.bind(this) } );
	    this.display.addClassName('kLoading');
	}
	else
	if(this.properties.dynamic=='false')
	{
	    toPostObject={'source':this.properties.source};
	    this.request = new Ajax.Request(requestPath, {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport)
	    {
		this.options=transport.responseText.evalJSON();
		this.checkOptions();
		if(!(runAfter=='init' && this.element.value=='')) this.getValue();
	    }.bind(this) } );
	}
	else this.getValue();
    },
    checkOptions: function(){
	this.display.removeClassName('kLoading');
	if(Object.isArray(this.options)){
	    console.log('is array');
	    var r = {};
	    for(var i=0;i<this.options.length;i++){
		if(this.options[i] !== undefined){
		    r[i] = this.options[i];
		}
	    }
	    this.options = r;
	}
	if(Object.keys(this.options).length == 0){
	    this.display.addClassName('kNoResults');
	}
    },
    getSuggestions: function()
    {
	this.suggestions=new Array();
	if(this.properties.force=='false') this.element.value=this.display.value; else this.element.value='invalid';
	if(this.display.value.length<this.properties.minSearchString) { this.displaySuggestions(); return; }
	if(this.properties.dynamic=='false')
	{
	    if(this.properties.searchAnywhere=='false')
	    $H(this.options).each(function(s)
	    {
		if(s.value.toLowerCase().search(this.display.value.toLowerCase())==0)
		{
		    this.suggestions.push({key:s.key,value:s.value});
		}
	    }.bind(this));
	    else if(this.properties.searchAnywhere=='true')
	    $H(this.options).each(function(s)
	    {
		if(s.value.toLowerCase().search(this.display.value.toLowerCase())>=0)
		{
		    this.suggestions.push({key:s.key,value:s.value});
		}
	    }.bind(this));
	    this.displaySuggestions();
	}
	else if(this.properties.dynamic=='true')
	{
	    if(this.timer!=undefined) clearTimeout(this.timer);
	    this.timer=setTimeout(function()
	    {
		if(this.display.value.length!=0)
		this.getOptions(function ()
		{ 
		    $H(this.options).each(function(s)
		    {
			this.suggestions.push({key:s.key,value:s.value});
		    }.bind(this));
		    console.log('displaying');
		    this.displaySuggestions();
		    console.log('done');
		}.bind(this) );
	    }.bind(this),this.properties.delay);
	}
    },
    displaySuggestions: function()
    {
	this.clearDivDisplay();
	if(this.suggestions.length>=1)
	{
	    console.log('have suggestions');
	    console.log(this.suggestions);
	    var elementProperties=this.getElementProperties(this.element);
	    var displayWidth=elementProperties.width-elementProperties.borderWidth;
	    var displayHeight=elementProperties.height;
	    this.suggestionsDiv=new Element('div',{'style':'overflow:auto;font-size:'+this.display.getStyle('font-size')+';position:absolute;z-index:50;'+
		'margin-top:'+displayHeight+'px;width:'+displayWidth+'px;height:auto;background-color:#fff;'+
		'border-left:'+this.element.getStyle('border-left-width')+' '+this.element.getStyle('border-left-style')+' '+this.element.getStyle('border-left-color')+
		';border-right:'+this.element.getStyle('border-right-width')+' '+this.element.getStyle('border-right-style')+' '+this.element.getStyle('border-right-color')+
		';border-bottom:'+this.element.getStyle('border-bottom-width')+' '+this.element.getStyle('border-bottom-style')+' '+this.element.getStyle('border-bottom-color')+';'});
	    this.suggestionStyle={'width':'auto','padding':2+'px '+5+'px','borderTop':'1px solid #000','color':elementProperties.color,'backgroundColor':elementProperties.backgroundColor};
	    this.suggestionStyleHover={'width':'auto','padding':2+'px '+5+'px','borderTop':'1px solid #fff','color':elementProperties.backgroundColor,'backgroundColor':elementProperties.color};
	    var i=0;
	    this.suggestions.each(function(s)
	    {
		i++;
		var key=s.key;
		s=s.value;
		var suggestionText='';
		if(this.properties.searchAnywhere=='false')
		suggestionText='<span style="font-weight:bold;">'+s.substr(0,this.display.value.length)+'</span>'+s.substr(this.display.value.length)
		else if(this.properties.searchAnywhere=='true')
		{
//		    var regex = new RegExp(this.display.value, "gi");
//		    matchedValue=s.match(regex)[0];
//		    suggestionText=s.split(regex);
//		    suggestionText=suggestionText.join('<span style="font-weight:bold;">'+matchedValue+'</span>');
		    var regex = new RegExp('(' + this.display.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&").split('\\ ').join('|') + ')', 'gi');
		    suggestionText = s.replace(regex, '<span style="font-weight: bold;">$1</span>');
		}
		var suggestion=new Element('div').setStyle(this.suggestionStyle).update(suggestionText);
		suggestion.observe('mousedown',function(event) { this.fire('kForm:enter'); });
		suggestion.observe('mouseover',function(event) { this.fire('kForm:select');  });
		suggestion.observe('mouseout',function(event) { this.fire('kForm:unselect'); });
		suggestion.observe('kForm:enter',function(event) { this.setValue({key:key,value:s});  }.bind(this));
		suggestion.observe('kForm:select',function(event) { if(this.selected!=null) this.selected.fire('kForm:unselect'); this.selected=suggestion; suggestion.setStyle(this.suggestionStyleHover);  }.bind(this));
		suggestion.observe('kForm:unselect',function(event) { this.selected=null; suggestion.setStyle(this.suggestionStyle);  }.bind(this));
		this.suggestionsDiv.appendChild(suggestion);
	    }.bind(this));
	    this.element.parentNode.insertBefore(this.suggestionsDiv, this.element.nextSibling);
	    if(i>this.properties.length)
	    {
		this.suggestionsDiv.setStyle({'height':(this.properties.length*this.suggestionsDiv.children[0].getHeight())+'px'});
	    }
	    this.OverSuggestions=false;
	    this.suggestionsDiv.observe('mousemove',function(event) { this.OverSuggestions=true; }.bindAsEventListener(this) );
	    this.suggestionsDiv.observe('click',function(event) { this.display.focus(); }.bindAsEventListener(this) );
	    this.suggestionsDiv.observe('mouseout',function(event) { this.OverSuggestions=false; }.bindAsEventListener(this) );
	}
	else
	{
	    console.log('no results');
	    if(this.properties.force=='true') this.element.value='invalid';
	    console.log('did  some stuff');
	}
    },
    clearDivDisplay: function()
    {
	if(this.suggestionsDiv!=null) { this.selected=null; console.log('removing'); this.suggestionsDiv.remove(); console.log('removed'); this.suggestionsDiv=null; }
    },
    setValue: function(value)
    {
	this.clearDivDisplay();
	this.debug(value.key);
	this.display.value=value.value;
	this.element.fire('kForm:changed');
    },
    getValue: function()
    {
	this.display.value=this.element.value;
    },
});


kfElements.kDatePicker = Class.create(kfElements.kFormElement, {
    initialize: function(element)
    {
	this.properties={'position':'right','height':'auto','width':'auto'};
        this.element=element;
        this.getProperties();
	var position=this.properties.position;
	this.properties.position=new Object();
	if(position=='right') { this.properties.position.top=-this.element.getHeight(); this.properties.position.left=this.element.getWidth(); }
	else if(position=='bottom') { this.properties.position.top=0; this.properties.position.left=0; }
	else if(position.split(':').length==2) { this.properties.position.top=position.split(':')[1]; this.properties.position.left=position.split(':')[0]; }
	else { this.properties.position.top=0; this.properties.position.left=this.element.getWidth(); }
	if(Math.floor(this.properties.width)!=this.properties.width) this.properties.width=this.element.getWidth();
	if(Math.floor(this.properties.height)!=this.properties.height) this.properties.height=Math.ceil(0.7*this.properties.width);
	
	this.renderDatePicker();
	this.addEvents();
	this.getValue();
	this.datePicker=new Object();
	this.months=new Array('January','February','March','April','May','June','July','August','September','October','November','December');
	this.days=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
	this.getKFormElement();
    },
    renderDatePicker: function()
    {
	var elementProperties=this.getElementProperties(this.element);
	var dateContainerWidth=elementProperties.width;
	var dateContainerHeight=elementProperties.height-elementProperties.borderHeight;
	this.element.hide();
	this.dateContainer=new Element('div',{'style':'text-align:center;color:'+elementProperties.color+';font-weight:bold;background-color:'+elementProperties.backgroundColor+';font-size:'+elementProperties.fontSize+';line-height:'+dateContainerHeight+'px;margin-top:0px;display:inline-block;width:'+dateContainerWidth+'px;'});
	this.dayField=new Element('input',{'type':'text','maxlength':2,'value':'DD','style':'width:2.3em;margin:0 .2em;text-align:center;'});
	this.monthField=new Element('input',{'type':'text','maxlength':2,'value':'MM','style':'width:2.3em;margin:0 .2em;text-align:center;'});
	this.yearField=new Element('input',{'type':'text','maxlength':4,'value':'YYYY','style':'width:3.5em;margin:0 .2em;text-align:center;'});
	this.datePickerIcon=new Element('img', {'src':'/static/img/datePicker.png','style':'vertical-align:middle;width:20px;'});
	this.dateContainer.appendChild(this.dayField);
	this.dateContainer.appendChild(this.monthField);
	this.dateContainer.appendChild(this.yearField);
	this.dateContainer.appendChild(this.datePickerIcon);
        this.element.parentNode.insertBefore(this.dateContainer, this.element.nextSibling);
    },
    addEvents: function()
    {
	this.dayField.observe('keyup', function(event) { event.stop(); this.updateValue();  }.bindAsEventListener(this) );
	this.monthField.observe('keyup', function(event) { event.stop(); this.updateValue();  }.bindAsEventListener(this) );
	this.yearField.observe('keyup', function(event) { event.stop(); this.updateValue(); }.bindAsEventListener(this) );
	this.datePickerIcon.observe('click', function(event) { event.stop(); this.openDatePicker(); }.bindAsEventListener(this) );
    },
    openDatePicker: function()
    {
	var top=0;
	var left=0;
	this.datePicker.container = new Element('div',{'style':'font-size:10px;line-height:10px;width:'+this.properties.width+'px;height:'+this.properties.height+'px;position:absolute;z-index:150;background-color:white;border:1px solid silver;margin-top:'+this.properties.position.top+'px;margin-left:'+this.properties.position.left+'px;'} );
	this.datePickerIcon.stopObserving('click');
	this.datePickerIcon.observe('click', function(event) { event.stop(); });
	this.datePicker.container.observe('click', function(event) { event.stop(); });
	this.dateContainer.appendChild(this.datePicker.container);
	document.body.observe('click', function(event) { this.closeContainer(); }.bindAsEventListener(this) );
	
	this.today = new Date();
		
	var day=parseInt(this.dayField.value);
	var month=parseInt(this.monthField.value);
	var year=parseInt(this.yearField.value);
	if(isNaN(day) || isNaN(month) || isNaN(year))
	this.date=this.today; else this.date=new Date(this.yearField.value,this.monthField.value-1,this.dayField.value);
	this.updateContainer(this.date);
    },
    alterDate: function(currentDate,year,month,day)
    {
	return new Date(currentDate.getFullYear()+year,currentDate.getMonth()+month,currentDate.getDate()+day);
    },
    getDaysInMonth: function(monthDate)
    {
	firstDayOfMonth = new Date(monthDate.getFullYear(),monthDate.getMonth(),1);
	this.temp=firstDayOfMonth;
	var temp=firstDayOfMonth;
	tempMonth = new Array();
	while(firstDayOfMonth.getMonth()==temp.getMonth())
	{
	    day=temp.getDate();
	    dayOfWeek=temp.getDay();
	    if(dayOfWeek==0 || day==1) tempWeek = new Array();
	    if(day==1) { for(i=0;i<=dayOfWeek;i++) { tempWeek[i]=null; } }
	    if(dayOfWeek<=6) tempWeek[dayOfWeek] = temp;
	    if(dayOfWeek==6) tempMonth[tempMonth.length]=tempWeek;
	    temp=this.alterDate(temp,0,0,1)
	    if(firstDayOfMonth.getMonth()!=temp.getMonth())
	    if(tempMonth[tempMonth.length-1]!=tempWeek) tempMonth[tempMonth.length]=tempWeek;
	}
	return tempMonth;
    },
    viewMonth: function(monthArray)
	{
		this.elementProperties=this.getElementProperties(this.element);
		
		date=monthArray[1][1];
		month=date.getMonth();
		year=date.getFullYear();
		
		monthTable = new Element('table',{'cellpadding':'0','cellspacing':'0','class':'datePickerWindow','style':'border-collapse:separate;color:'+this.elementProperties.color+';background-color:'+this.elementProperties.backgroundColor+';font-size:10px;table-layout:fixed; empty-cells:hide; boder-collapse:collapse; border-spacing:0px;width:100%;height:100%;cursor:default;'});
		tBody = new Element('tbody');
		monthTable.update(tBody);
		titleRow = new Element('tr',{'class':'datePickerTitle','style':'font-weight:bold;color:'+this.elementProperties.backgroundColor+';background-color:'+this.elementProperties.color+';'});
		leftCell = new Element('td').update('&nbsp;'); titleRow.appendChild(leftCell);
		centerBlock= new Element('td',{'colspan':5,'style':'vertical-align:middle'}).update(this.months[month]+', '+year); titleRow.appendChild(centerBlock);
		rightCell = new Element('td',{'style':'vertical-align:middle'}).update('x'); titleRow.appendChild(rightCell);
		rightCell.observe('mousedown',function(event) {this.closeContainer();}.bindAsEventListener(this) );
		tBody.appendChild(titleRow);
		
		
		this.actionCellStyle={'cursor':'pointer','verticalAlign':'middle','color':this.elementProperties.color,'backgroundColor':this.elementProperties.backgroundColor,'borderWidth':'1px','borderStyle':'solid','borderColor':this.elementProperties.backgroundColor};
		this.actionSelectedCellStyle={'verticalAlign':'middle','color':this.elementProperties.backgroundColor,'backgroundColor':this.elementProperties.color};
		this.actionCellStyleHover={'verticalAlign':'middle','cursor':'pointer','color':this.elementProperties.color,'backgroundColor':this.elementProperties.backgroundColor,'borderWidth':'1px','borderStyle':'solid','borderColor':this.elementProperties.color};
		
		menuRow = new Element('tr',{'class':'datePickerMenu','style':'font-weight:bold;cursor:pointer;'});
		prevYear = new Element('td',{'title':'Previous year','style':'vertical-align:middle'}).update('<<'); menuRow.appendChild(prevYear);
		prevYear.observe('mousedown',function(event) { event.stop(); this.updateContainer(this.alterDate(this.temp,-1,0,0)); }.bindAsEventListener(this) );
		
		prevMonth = new Element('td',{'title':'Previous month','style':'vertical-align:middle'}).update('<'); menuRow.appendChild(prevMonth);
		prevMonth.observe('mousedown',function(event) { event.stop(); this.updateContainer(this.alterDate(this.temp,0,-1,0)); }.bindAsEventListener(this) );
		todayCell = new Element('td',{'title':'Show today','colspan':3,'style':'vertical-align:middle'}).update('Today'); menuRow.appendChild(todayCell);
		todayCell.observe('mousedown',function(event)
		{
			event.stop();
			this.date=this.today;
			this.updateContainer(this.today);
		}.bindAsEventListener(this) );
		nextMonth = new Element('td',{'title':'Next month','style':'vertical-align:middle'}).update('>'); menuRow.appendChild(nextMonth);
		nextMonth.observe('mousedown',function(event) { event.stop(); this.updateContainer(this.alterDate(this.temp,0,1,0)); }.bindAsEventListener(this) );
		nextYear = new Element('td',{'title':'Next year','style':'vertical-align:middle'}).update('>>'); menuRow.appendChild(nextYear);
		nextYear.observe('mousedown',function(event) { event.stop(); this.updateContainer(this.alterDate(this.temp,1,0,0)); }.bindAsEventListener(this) );
		
		menuRow.childElements().each(function (s) {
		    s.setStyle(this.actionCellStyle);
		    s.observe('mouseover',function(event) { event.element().setStyle(this.actionCellStyleHover); } );
		    s.observe('mouseout',function(event) { event.element().setStyle(this.actionCellStyle); } );
		});
		tBody.appendChild(menuRow);
		
		daysOfWeekRow = new Element('tr',{'class':'datePickerDaysOfWeek','style':'font-weight:bold;border-bottom:1px solid '+this.elementProperties.color+';color:'+this.elementProperties.backgroundColor+';background-color:'+this.elementProperties.color+';'});
		for(i=0;i<this.days.length;i++)
		{
			day = new Element('td',{'title':this.days[i],'style':'vertical-align:middle'}).update(this.days[i].substr(0,1)); daysOfWeekRow.appendChild(day);
		}
		
		tBody.appendChild(daysOfWeekRow);
		
		for(w=0;w<monthArray.length;w++)
		{
			week = new Element('tr');
			weekDays = monthArray[w];
			for(i=0;i<=6;i++)
			{
				if(weekDays[i]!=null)
				{
					var day = new Element('td',{'class':'datePickerDays','id':weekDays[i].getFullYear()+'-'+weekDays[i].getMonth()+'-'+weekDays[i].getDate()}).update(weekDays[i].getDate());
					day.setStyle(this.actionCellStyle);
					if(this.date.getFullYear()==weekDays[i].getFullYear() && this.date.getMonth()==weekDays[i].getMonth() && this.date.getDate()==weekDays[i].getDate()) this.selectDay(day);
					day.observe('mousedown',function(event) { event.stop(); this.selectDay(event.element()); setTimeout(function() { this.chooseDay(event.element()); }.bind(this),450); }.bindAsEventListener(this) );
					day.observe('mouseover',function(event) { this.hoverDay(event.element()); }.bindAsEventListener(this) );
					day.observe('mouseout',function(event) { this.unHoverDay(); $('datePickerStatus').update('Select date'); }.bindAsEventListener(this) );
					
				} else day = new Element('td');
				week.appendChild(day);
			}
			tBody.appendChild(week);
		}
		
		statusRow = new Element('tr',{'class':'datePickerStatus'});
		statusRow.setStyle(this.actionSelectedCellStyle);
		statusCell= new Element('td',{'colspan':7,'id':'datePickerStatus','style':'vertical-align:middle'}).update('Select date'); statusRow.appendChild(statusCell);
		
		tBody.appendChild(statusRow);
		
		return monthTable;
	},
    unHoverDay: function()
    {
	if($$('.datePickerHoverDay')[0])
	{
	    if($$('.datePickerHoverDay')[0].hasClassName('datePickerSelectedDay')) $$('.datePickerHoverDay')[0].setStyle(this.actionSelectedCellStyle); else $$('.datePickerHoverDay')[0].setStyle(this.actionCellStyle);
	    $$('.datePickerHoverDay')[0].removeClassName('datePickerHoverDay');
	}
    },
    hoverDay: function(day)
    {
	var dateParts=day.id.split('-');
	$('datePickerStatus').update(dateParts[2]+' '+this.months[dateParts[1]]+' '+dateParts[0]);
	this.unHoverDay();
	
	day.addClassName('datePickerHoverDay');
	day.setStyle(this.actionCellStyleHover);
	
    },
    selectDay: function(day)
    {
	if($$('.datePickerSelectedDay').length>0)
	{
	    $$('.datePickerSelectedDay')[0].setStyle(this.actionCellStyle);
	    $$('.datePickerSelectedDay')[0].removeClassName('datePickerSelectedDay');
	}
	day.addClassName('datePickerSelectedDay');
	day.setStyle(this.actionSelectedCellStyle);
    },
    chooseDay: function(day)
    {
	this.closeContainer();
	var dateParts=day.id.split('-');
	if(dateParts[2]>9) this.dayField.value=dateParts[2]; else this.dayField.value='0'+dateParts[2];
	if(dateParts[1]>8) this.monthField.value=(parseInt(dateParts[1])+1); else this.monthField.value='0'+(parseInt(dateParts[1])+1);
	this.yearField.value=dateParts[0];
	this.element.value=this.yearField.value+'-'+this.monthField.value+'-'+this.dayField.value;
    },
    updateValue: function()
    {
	this.element.value=this.yearField.value+'-'+this.monthField.value+'-'+this.dayField.value;
    },
    updateContainer: function(date)
    {
	if(date===undefined) date=this.today;
	var newContainer=this.viewMonth(this.getDaysInMonth(date));
	this.datePicker.container.update(newContainer);
    },
    closeContainer: function()
    {
	document.body.stopObserving('click');
	this.datePickerIcon.stopObserving('click');
	this.datePickerIcon.observe('click', function(event) { event.stop(); this.openDatePicker(); }.bindAsEventListener(this) );
	if(this.datePicker.container.getOpacity()>0.05)
	{ 
	    this.datePicker.container.setOpacity(this.datePicker.container.getOpacity()-0.05);
	    setTimeout(function(event) { this.closeContainer(); }.bindAsEventListener(this),20);
	}
	else this.forceQuit();
    },
    forceQuit: function()
    {
	document.body.stopObserving('click');
	this.datePickerIcon.stopObserving('click');
	this.datePickerIcon.observe('click', function(event) { event.stop(); this.openDatePicker(); }.bindAsEventListener(this) );
	this.datePicker.container.hide();
	this.datePicker.container.remove();
    },
    getValue: function()
    {
	if(this.element.value!='')
	{
	    var date=this.element.value.split('-');
	    this.dayField.value=date[2];
	    this.monthField.value=date[1];
	    this.yearField.value=date[0];
	}
    }
    
    
});
/*
 Highcharts JS v2.1.5 (2011-06-22)
 Prototype adapter

 @author Michael Nelson, Torstein H?nsi.

 Feel free to use and modify this script.
 Highcharts license: www.highcharts.com/license.
*/
var HighchartsAdapter=function(){var f=typeof Effect!="undefined";return{init:function(){if(f)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(a,b,c,d){var e;this.element=a;e=a.attr(b);if(b=="d"){this.paths=Highcharts.pathAnim.init(a,a.d,c);this.toD=c;e=0;c=1}this.start(Object.extend(d||{},{from:e,to:c,attribute:b}))},setup:function(){HighchartsAdapter._extend(this.element);this.element._highchart_animation=this},update:function(a){var b=this.paths;if(b)a=Highcharts.pathAnim.step(b[0],
b[1],a,this.toD);this.element.attr(this.options.attribute,a)},finish:function(){this.element._highchart_animation=null}})},addEvent:function(a,b,c){if(a.addEventListener||a.attachEvent)Event.observe($(a),b,c);else{HighchartsAdapter._extend(a);a._highcharts_observe(b,c)}},animate:function(a,b,c){var d;c=c||{};c.delay=0;c.duration=(c.duration||500)/1E3;if(f)for(d in b)new Effect.HighchartsTransition($(a),d,b[d],c);else for(d in b)a.attr(d,b[d]);if(!a.attr)throw"Todo: implement animate DOM objects";
},stop:function(a){a._highcharts_extended&&a._highchart_animation&&a._highchart_animation.cancel()},each:function(a,b){$A(a).each(b)},fireEvent:function(a,b,c,d){if(b.preventDefault)d=null;if(a.fire)a.fire(b,c);else a._highcharts_extended&&a._highcharts_fire(b,c);d&&d(c)},removeEvent:function(a,b,c){if($(a).stopObserving)$(a).stopObserving(b,c);else{HighchartsAdapter._extend(a);a._highcharts_stop_observing(b,c)}},grep:function(a,b){return a.findAll(b)},hyphenate:function(a){return a.replace(/([A-Z])/g,
function(b,c){return"-"+c.toLowerCase()})},map:function(a,b){return a.map(b)},merge:function(){function a(b,c){var d,e;for(e in c){d=c[e];b[e]=d&&typeof d=="object"&&d.constructor!=Array&&typeof d.nodeType!=="number"?a(b[e]||{},d):c[e]}return b}return function(){for(var b=arguments,c={},d=0;d<b.length;d++)c=a(c,b[d]);return c}.apply(this,arguments)},_extend:function(a){a._highcharts_extended||Object.extend(a,{_highchart_events:{},_highchart_animation:null,_highcharts_extended:true,_highcharts_observe:function(b,
c){this._highchart_events[b]=[this._highchart_events[b],c].compact().flatten()},_highcharts_stop_observing:function(b,c){this._highchart_events[b]=[this._highchart_events[b]].compact().flatten().without(c)},_highcharts_fire:function(b,c){(this._highchart_events[b]||[]).each(function(d){c&&c.stopped||d.bind(this)(c)}.bind(this))}})}}}();

/*
 Highcharts JS v2.1.5 (2011-06-22)

 (c) 2009-2011 Torstein H?nsi

 License: www.highcharts.com/license
*/
(function(){function pa(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function la(a,b){return parseInt(a,b||10)}function Qb(a){return typeof a==="string"}function Kb(a){return typeof a==="object"}function ec(a){return typeof a==="number"}function rc(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function J(a){return a!==Ua&&a!==null}function Ca(a,b,c){var d,e;if(Qb(b))if(J(c))a.setAttribute(b,c);else{if(a&&a.getAttribute)e=a.getAttribute(b)}else if(J(b)&&Kb(b))for(d in b)a.setAttribute(d,
b[d]);return e}function sc(a){if(!a||a.constructor!==Array)a=[a];return a}function B(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++){c=a[b];if(typeof c!=="undefined"&&c!==null)return c}}function Zd(a){var b="",c;for(c in a)b+=c+":"+a[c]+";";return b}function La(a,b){if(Cc)if(b&&b.opacity!==Ua)b.filter="alpha(opacity="+b.opacity*100+")";pa(a.style,b)}function ib(a,b,c,d,e){a=wa.createElement(a);b&&pa(a,b);e&&La(a,{padding:0,border:jb,margin:0});c&&La(a,c);d&&d.appendChild(a);return a}function yb(a,
b){var c=function(){};c.prototype=new a;pa(c.prototype,b);return c}function Bd(a,b,c,d){var e=Va.lang;a=a;var f=isNaN(b=db(b))?2:b;b=c===undefined?e.decimalPoint:c;d=d===undefined?e.thousandsSep:d;e=a<0?"-":"";c=String(la(a=db(+a||0).toFixed(f)));var g=c.length>3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+db(a-c).toFixed(f).slice(2):"")}function fc(a,b){Dc=B(a,b.animation)}function Cd(){var a=Va.global.useUTC;Ec=a?Date.UTC:function(b,c,d,e,f,g){return(new Date(b,
c,B(d,1),B(e,0),B(f,0),B(g,0))).getTime()};dd=a?"getUTCMinutes":"getMinutes";ed=a?"getUTCHours":"getHours";fd=a?"getUTCDay":"getDay";tc=a?"getUTCDate":"getDate";Fc=a?"getUTCMonth":"getMonth";Gc=a?"getUTCFullYear":"getFullYear";Dd=a?"setUTCMinutes":"setMinutes";Ed=a?"setUTCHours":"setHours";gd=a?"setUTCDate":"setDate";Fd=a?"setUTCMonth":"setMonth";Gd=a?"setUTCFullYear":"setFullYear"}function Hc(a){Ic||(Ic=ib(Rb));a&&Ic.appendChild(a);Ic.innerHTML=""}function Jc(){}function Hd(a,b){function c(m,i){function y(k,
o){this.pos=k;this.minor=o;this.isNew=true;o||this.addLabel()}function x(k){if(k){this.options=k;this.id=k.id}return this}function R(k,o,r){this.isNegative=o;this.options=k;this.x=r;this.alignOptions={align:k.align||(qa?o?"left":"right":"center"),verticalAlign:k.verticalAlign||(qa?"middle":o?"bottom":"top"),y:B(k.y,qa?4:o?14:-6),x:B(k.x,qa?o?-6:6:0)};this.textAlign=k.textAlign||(qa?o?"right":"left":"center")}function na(){var k=[],o=[],r;T=ra=null;Da=[];t(Ga,function(q){r=false;t(["xAxis","yAxis"],
function(ma){if(q.isCartesian&&(ma==="xAxis"&&Ea||ma==="yAxis"&&!Ea)&&(q.options[ma]===i.index||q.options[ma]===Ua&&i.index===0)){q[ma]=w;Da.push(q);r=true}});if(!q.visible&&u.ignoreHiddenSeries)r=false;if(r){var A,U,F,V,Aa;if(!Ea){A=q.options.stacking;Kc=A==="percent";if(A){V=q.type+B(q.options.stack,"");Aa="-"+V;q.stackKey=V;U=k[V]||[];k[V]=U;F=o[Aa]||[];o[Aa]=F}if(Kc){T=0;ra=99}}if(q.isCartesian){t(q.data,function(ma){var s=ma.x,W=ma.y,$=W<0,ga=$?F:U,zb=$?Aa:V;if(T===null)T=ra=ma[ha];if(Ea)if(s>
ra)ra=s;else{if(s<T)T=s}else if(J(W)){if(A)ga[s]=J(ga[s])?ga[s]+W:W;W=ga?ga[s]:W;ma=B(ma.low,W);if(!Kc)if(W>ra)ra=W;else if(ma<T)T=ma;if(A){v[zb]||(v[zb]={});v[zb][s]||(v[zb][s]=new R(i.stackLabels,$,s));v[zb][s].setTotal(W)}}});if(/(area|column|bar)/.test(q.type)&&!Ea)if(T>=0){T=0;Id=true}else if(ra<0){ra=0;Jd=true}}}})}function N(k,o){var r,q;Cb=o?1:ta.pow(10,kb(ta.log(k)/ta.LN10));r=k/Cb;if(!o){o=[1,2,2.5,5,10];if(i.allowDecimals===false||D)if(Cb===1)o=[1,2,5,10];else if(Cb<=0.1)o=[1/Cb]}for(q=
0;q<o.length;q++){k=o[q];if(r<=(o[q]+(o[q+1]||o[q]))/2)break}k*=Cb;return k}function ba(k){var o;o=k;Cb=B(Cb,ta.pow(10,kb(ta.log(Qa)/ta.LN10)));if(Cb<1){o=X(1/Cb)*10;o=X(k*o)/o}return o}function Ka(){var k,o,r,q,A=i.tickInterval,U=i.tickPixelInterval;k=i.maxZoom||(Ea&&!J(i.min)&&!J(i.max)?qb(m.smallestInterval*5,ra-T):null);oa=z?Ba:xa;if(Sb){r=m[Ea?"xAxis":"yAxis"][i.linkedTo];q=r.getExtremes();aa=B(q.min,q.dataMin);ca=B(q.max,q.dataMax)}else{aa=B(Ha,i.min,T);ca=B(Ma,i.max,ra)}if(D){aa=ta.log(aa)/
ta.LN10;ca=ta.log(ca)/ta.LN10}if(ca-aa<k){q=(k-ca+aa)/2;aa=Fa(aa-q,B(i.min,aa-q),T);ca=qb(aa+k,B(i.max,aa+k),ra)}if(!Wa&&!Kc&&!Sb&&J(aa)&&J(ca)){k=ca-aa||1;if(!J(i.min)&&!J(Ha)&&Kd&&(T<0||!Id))aa-=k*Kd;if(!J(i.max)&&!J(Ma)&&Ld&&(ra>0||!Jd))ca+=k*Ld}Qa=aa===ca?1:Sb&&!A&&U===r.options.tickPixelInterval?r.tickInterval:B(A,Wa?1:(ca-aa)*U/oa);if(!E&&!J(i.tickInterval))Qa=N(Qa);w.tickInterval=Qa;Lc=i.minorTickInterval==="auto"&&Qa?Qa/5:i.minorTickInterval;if(E){ua=[];A=Va.global.useUTC;var F=1E3/rb,V=6E4/
rb,Aa=36E5/rb;U=864E5/rb;k=6048E5/rb;q=2592E6/rb;var ma=31556952E3/rb,s=[["second",F,[1,2,5,10,15,30]],["minute",V,[1,2,5,10,15,30]],["hour",Aa,[1,2,3,4,6,8,12]],["day",U,[1,2]],["week",k,[1,2]],["month",q,[1,2,3,4,6]],["year",ma,null]],W=s[6],$=W[1],ga=W[2];for(r=0;r<s.length;r++){W=s[r];$=W[1];ga=W[2];if(s[r+1])if(Qa<=($*ga[ga.length-1]+s[r+1][1])/2)break}if($===ma&&Qa<5*$)ga=[1,2,5];s=N(Qa/$,ga);ga=new Date(aa*rb);ga.setMilliseconds(0);if($>=F)ga.setSeconds($>=V?0:s*kb(ga.getSeconds()/s));if($>=
V)ga[Dd]($>=Aa?0:s*kb(ga[dd]()/s));if($>=Aa)ga[Ed]($>=U?0:s*kb(ga[ed]()/s));if($>=U)ga[gd]($>=q?1:s*kb(ga[tc]()/s));if($>=q){ga[Fd]($>=ma?0:s*kb(ga[Fc]()/s));o=ga[Gc]()}if($>=ma){o-=o%s;ga[Gd](o)}$===k&&ga[gd](ga[tc]()-ga[fd]()+i.startOfWeek);r=1;o=ga[Gc]();F=ga.getTime()/rb;V=ga[Fc]();for(Aa=ga[tc]();F<ca&&r<Ba;){ua.push(F);if($===ma)F=Ec(o+r*s,0)/rb;else if($===q)F=Ec(o,V+r*s)/rb;else if(!A&&($===U||$===k))F=Ec(o,V,Aa+r*s*($===U?1:7));else F+=$*s;r++}ua.push(F);Mc=i.dateTimeLabelFormats[W[0]]}else{r=
ba(kb(aa/Qa)*Qa);o=ba(hd(ca/Qa)*Qa);ua=[];for(r=ba(r);r<=o;){ua.push(r);r=ba(r+Qa)}}if(!Sb){if(Wa||Ea&&m.hasColumn){o=(Wa?1:Qa)*0.5;if(Wa||!J(B(i.min,Ha)))aa-=o;if(Wa||!J(B(i.max,Ma)))ca+=o}o=ua[0];r=ua[ua.length-1];if(i.startOnTick)aa=o;else aa>o&&ua.shift();if(i.endOnTick)ca=r;else ca<r&&ua.pop();Lb||(Lb={x:0,y:0});if(!E&&ua.length>Lb[ha])Lb[ha]=ua.length}}function za(){var k,o;Db=aa;Md=ca;na();Ka();fb=va;va=oa/(ca-aa||1);if(!Ea)for(k in v)for(o in v[k])v[k][o].cum=v[k][o].total;if(!w.isDirty)w.isDirty=
aa!==Db||ca!==Md}function Na(k){k=(new x(k)).render();Tb.push(k);return k}function Oa(){var k=i.title,o=i.stackLabels,r=i.alternateGridColor,q=i.lineWidth,A,U,F=m.hasRendered,V=F&&J(Db)&&!isNaN(Db);A=Da.length&&J(aa)&&J(ca);oa=z?Ba:xa;va=oa/(ca-aa||1);eb=z?Z:sb;if(A||Sb){if(Lc&&!Wa)for(A=aa+(ua[0]-aa)%Lc;A<=ca;A+=Lc){ac[A]||(ac[A]=new y(A,true));V&&ac[A].isNew&&ac[A].render(null,true);ac[A].isActive=true;ac[A].render()}t(ua,function(s,W){if(!Sb||s>=aa&&s<=ca){V&&tb[s].isNew&&tb[s].render(W,true);
tb[s].isActive=true;tb[s].render(W)}});r&&t(ua,function(s,W){if(W%2===0&&s<ca){gc[s]||(gc[s]=new x);gc[s].options={from:s,to:ua[W+1]!==Ua?ua[W+1]:ca,color:r};gc[s].render();gc[s].isActive=true}});F||t((i.plotLines||[]).concat(i.plotBands||[]),function(s){Tb.push((new x(s)).render())})}t([tb,ac,gc],function(s){for(var W in s)if(s[W].isActive)s[W].isActive=false;else{s[W].destroy();delete s[W]}});if(q){A=Z+(Ia?Ba:0)+M;U=Ra-sb-(Ia?xa:0)+M;A=da.crispLine([Za,z?Z:A,z?U:ea,Ja,z?Xa-Eb:A,z?U:Ra-sb],q);if(ja)ja.animate({d:A});
else ja=da.path(A).attr({stroke:i.lineColor,"stroke-width":q,zIndex:7}).add()}if(w.axisTitle){A=z?Z:ea;q=la(k.style.fontSize||12);A={low:A+(z?0:oa),middle:A+oa/2,high:A+(z?oa:0)}[k.align];q=(z?ea+xa:Z)+(z?1:-1)*(Ia?-1:1)*id+(Y===2?q:0);w.axisTitle[F?"animate":"attr"]({x:z?A:q+(Ia?Ba:0)+M+(k.x||0),y:z?q-(Ia?xa:0)+M:A+(k.y||0)})}if(o&&o.enabled){var Aa,ma;o=w.stackTotalGroup;if(!o)w.stackTotalGroup=o=da.g("stack-labels").attr({visibility:ub,zIndex:6}).translate(Z,ea).add();for(Aa in v){k=v[Aa];for(ma in k)k[ma].render(o)}}w.isDirty=
false}function Ya(k){for(var o=Tb.length;o--;)Tb[o].id===k&&Tb[o].destroy()}var Ea=i.isX,Ia=i.opposite,z=qa?!Ea:Ea,Y=z?Ia?0:2:Ia?1:3,v={};i=sa(Ea?Nc:jd,[$d,ae,Nd,be][Y],i);var w=this,L=i.type,E=L==="datetime",D=L==="logarithmic",M=i.offset||0,ha=Ea?"x":"y",oa,va,fb,eb=z?Z:sb,Fb,Ub,hc,I,ja,T,ra,Da,Ha,Ma,ca=null,aa=null,Db,Md,Kd=i.minPadding,Ld=i.maxPadding,Sb=J(i.linkedTo),Id,Jd,Kc;L=i.events;var kd,Tb=[],Qa,Lc,Cb,ua,tb={},ac={},gc={},ic,jc,id,Mc,Wa=i.categories,ce=i.labels.formatter||function(){var k=
this.value;return Mc?Oc(Mc,k):Qa%1E6===0?k/1E6+"M":Qa%1E3===0?k/1E3+"k":!Wa&&k>=1E3?Bd(k,0):k},Pc=z&&i.labels.staggerLines,bc=i.reversed,cc=Wa&&i.tickmarkPlacement==="between"?0.5:0;y.prototype={addLabel:function(){var k=this.pos,o=i.labels,r=!(k===aa&&!B(i.showFirstLabel,1)||k===ca&&!B(i.showLastLabel,0)),q=Wa&&z&&Wa.length&&!o.step&&!o.staggerLines&&!o.rotation&&Ba/Wa.length||!z&&Ba/2,A=this.label;k=ce.call({isFirst:k===ua[0],isLast:k===ua[ua.length-1],dateTimeLabelFormat:Mc,value:Wa&&Wa[k]?Wa[k]:
k});q=q&&{width:Fa(1,X(q-2*(o.padding||10)))+$a};q=pa(q,o.style);if(A===Ua)this.label=J(k)&&r&&o.enabled?da.text(k,0,0).attr({align:o.align,rotation:o.rotation}).css(q).add(hc):null;else A&&A.attr({text:k}).css(q)},getLabelSize:function(){var k=this.label;return k?(this.labelBBox=k.getBBox())[z?"height":"width"]:0},render:function(k,o){var r=!this.minor,q=this.label,A=this.pos,U=i.labels,F=this.gridLine,V=r?i.gridLineWidth:i.minorGridLineWidth,Aa=r?i.gridLineColor:i.minorGridLineColor,ma=r?i.gridLineDashStyle:
i.minorGridLineDashStyle,s=this.mark,W=r?i.tickLength:i.minorTickLength,$=r?i.tickWidth:i.minorTickWidth||0,ga=r?i.tickColor:i.minorTickColor,zb=r?i.tickPosition:i.minorTickPosition;r=U.step;var lb=o&&Qc||Ra,Mb;Mb=z?Fb(A+cc,null,null,o)+eb:Z+M+(Ia?(o&&ld||Xa)-Eb-Z:0);lb=z?lb-sb+M-(Ia?xa:0):lb-Fb(A+cc,null,null,o)-eb;if(V){A=Ub(A+cc,V,o);if(F===Ua){F={stroke:Aa,"stroke-width":V};if(ma)F.dashstyle=ma;this.gridLine=F=V?da.path(A).attr(F).add(I):null}F&&A&&F.animate({d:A})}if($){if(zb==="inside")W=-W;
if(Ia)W=-W;V=da.crispLine([Za,Mb,lb,Ja,Mb+(z?0:-W),lb+(z?W:0)],$);if(s)s.animate({d:V});else this.mark=da.path(V).attr({stroke:ga,"stroke-width":$}).add(hc)}if(q&&!isNaN(Mb)){Mb=Mb+U.x-(cc&&z?cc*va*(bc?-1:1):0);lb=lb+U.y-(cc&&!z?cc*va*(bc?1:-1):0);J(U.y)||(lb+=la(q.styles.lineHeight)*0.9-q.getBBox().height/2);if(Pc)lb+=k/(r||1)%Pc*16;if(r)q[k%r?"hide":"show"]();q[this.isNew?"attr":"animate"]({x:Mb,y:lb})}this.isNew=false},destroy:function(){for(var k in this)this[k]&&this[k].destroy&&this[k].destroy()}};
x.prototype={render:function(){var k=this,o=k.options,r=o.label,q=k.label,A=o.width,U=o.to,F,V=o.from,Aa=o.dashStyle,ma=k.svgElem,s=[],W,$,ga=o.color;$=o.zIndex;var zb=o.events;if(A){s=Ub(o.value,A);o={stroke:ga,"stroke-width":A};if(Aa)o.dashstyle=Aa}else if(J(V)&&J(U)){V=Fa(V,aa);U=qb(U,ca);F=Ub(U);if((s=Ub(V))&&F)s.push(F[4],F[5],F[1],F[2]);else s=null;o={fill:ga}}else return;if(J($))o.zIndex=$;if(ma)if(s)ma.animate({d:s},null,ma.onGetPath);else{ma.hide();ma.onGetPath=function(){ma.show()}}else if(s&&
s.length){k.svgElem=ma=da.path(s).attr(o).add();if(zb){Aa=function(lb){ma.on(lb,function(Mb){zb[lb].apply(k,[Mb])})};for(W in zb)Aa(W)}}if(r&&J(r.text)&&s&&s.length&&Ba>0&&xa>0){r=sa({align:z&&F&&"center",x:z?!F&&4:10,verticalAlign:!z&&F&&"middle",y:z?F?16:10:F?6:-4,rotation:z&&!F&&90},r);if(!q)k.label=q=da.text(r.text,0,0).attr({align:r.textAlign||r.align,rotation:r.rotation,zIndex:$}).css(r.style).add();F=[s[1],s[4],B(s[6],s[1])];s=[s[2],s[5],B(s[7],s[2])];W=qb.apply(ta,F);$=qb.apply(ta,s);q.align(r,
false,{x:W,y:$,width:Fa.apply(ta,F)-W,height:Fa.apply(ta,s)-$});q.show()}else q&&q.hide();return k},destroy:function(){for(var k in this){this[k]&&this[k].destroy&&this[k].destroy();delete this[k]}rc(Tb,this)}};R.prototype={setTotal:function(k){this.cum=this.total=k},render:function(k){var o=this.options.formatter.call(this);if(this.label)this.label.attr({text:o,visibility:gb});else this.label=m.renderer.text(o,0,0).css(this.options.style).attr({align:this.textAlign,rotation:this.options.rotation,
visibility:gb}).add(k)},setOffset:function(k,o){var r=this.isNegative,q=w.translate(this.total),A=w.translate(0);A=db(q-A);var U=m.xAxis[0].translate(this.x)+k,F=m.plotHeight;r={x:qa?r?q:q-A:U,y:qa?F-U-o:r?F-q-A:F-q,width:qa?A:o,height:qa?o:A};this.label&&this.label.align(this.alignOptions,null,r).attr({visibility:ub})}};Fb=function(k,o,r,q,A){var U=1,F=0,V=q?fb:va;q=q?Db:aa;V||(V=va);if(r){U*=-1;F=oa}if(bc){U*=-1;F-=U*oa}if(o){if(bc)k=oa-k;k=k/V+q;if(D&&A)k=ta.pow(10,k)}else{if(D&&A)k=ta.log(k)/
ta.LN10;k=U*(k-q)*V+F}return k};Ub=function(k,o,r){var q,A,U;k=Fb(k,null,null,r);var F=r&&Qc||Ra,V=r&&ld||Xa,Aa;r=A=X(k+eb);q=U=X(F-k-eb);if(isNaN(k))Aa=true;else if(z){q=ea;U=F-sb;if(r<Z||r>Z+Ba)Aa=true}else{r=Z;A=V-Eb;if(q<ea||q>ea+xa)Aa=true}return Aa?null:da.crispLine([Za,r,q,Ja,A,U],o||0)};if(qa&&Ea&&bc===Ua)bc=true;pa(w,{addPlotBand:Na,addPlotLine:Na,adjustTickAmount:function(){if(Lb&&!E&&!Wa&&!Sb){var k=ic,o=ua.length;ic=Lb[ha];if(o<ic){for(;ua.length<ic;)ua.push(ba(ua[ua.length-1]+Qa));va*=
(o-1)/(ic-1);ca=ua[ua.length-1]}if(J(k)&&ic!==k)w.isDirty=true}},categories:Wa,getExtremes:function(){return{min:aa,max:ca,dataMin:T,dataMax:ra,userMin:Ha,userMax:Ma}},getPlotLinePath:Ub,getThreshold:function(k){if(aa>k)k=aa;else if(ca<k)k=ca;return Fb(k,0,1)},isXAxis:Ea,options:i,plotLinesAndBands:Tb,getOffset:function(){var k=Da.length&&J(aa)&&J(ca),o=0,r=0,q=i.title,A=i.labels,U=[-1,1,1,-1][Y],F;if(!hc){hc=da.g("axis").attr({zIndex:7}).add();I=da.g("grid").attr({zIndex:1}).add()}jc=0;if(k||Sb){t(ua,
function(V){if(tb[V])tb[V].addLabel();else tb[V]=new y(V);if(Y===0||Y===2||{1:"left",3:"right"}[Y]===A.align)jc=Fa(tb[V].getLabelSize(),jc)});if(Pc)jc+=(Pc-1)*16}else for(F in tb){tb[F].destroy();delete tb[F]}if(q&&q.text){if(!w.axisTitle)w.axisTitle=da.text(q.text,0,0).attr({zIndex:7,rotation:q.rotation||0,align:q.textAlign||{low:"left",middle:"center",high:"right"}[q.align]}).css(q.style).add();o=w.axisTitle.getBBox()[z?"height":"width"];r=B(q.margin,z?5:10)}M=U*(i.offset||Vb[Y]);id=jc+(Y!==2&&
jc&&U*i.labels[z?"y":"x"])+r;Vb[Y]=Fa(Vb[Y],id+o+U*M)},render:Oa,setCategories:function(k,o){w.categories=Wa=k;t(Da,function(r){r.translate();r.setTooltipPoints(true)});w.isDirty=true;B(o,true)&&m.redraw()},setExtremes:function(k,o,r,q){r=B(r,true);Pa(w,"setExtremes",{min:k,max:o},function(){Ha=k;Ma=o;r&&m.redraw(q)})},setScale:za,setTickPositions:Ka,translate:Fb,redraw:function(){kc.resetTracker&&kc.resetTracker();Oa();t(Tb,function(k){k.render()});t(Da,function(k){k.isDirty=true})},removePlotBand:Ya,
removePlotLine:Ya,reversed:bc,stacks:v});for(kd in L)Sa(w,kd,L[kd]);za()}function d(){var m={};return{add:function(i,y,x,R){if(!m[i]){y=da.text(y,0,0).css(a.toolbar.itemStyle).align({align:"right",x:-Eb-20,y:ea+30}).on("click",R).attr({align:"right",zIndex:20}).add();m[i]=y}},remove:function(i){Hc(m[i].element);m[i]=null}}}function e(m){function i(){var E=this.points||sc(this),D=E[0].series.xAxis,M=this.x;D=D&&D.options.type==="datetime";var ha=Qb(M)||D,oa;oa=ha?['<span style="font-size: 10px">'+
(D?Oc("%A, %b %e, %Y",M):M)+"</span>"]:[];t(E,function(va){oa.push(va.point.tooltipFormatter(ha))});return oa.join("<br/>")}function y(E,D){z=Ya?E:(2*z+E)/3;Y=Ya?D:(Y+D)/2;v.translate(z,Y);md=db(E-z)>1||db(D-Y)>1?function(){y(E,D)}:null}function x(){if(!Ya){var E=p.hoverPoints;v.hide();t(ba,function(D){D&&D.hide()});E&&t(E,function(D){D.setState()});p.hoverPoints=null;Ya=true}}var R,na=m.borderWidth,N=m.crosshairs,ba=[],Ka=m.style,za=m.shared,Na=la(Ka.padding),Oa=na+Na,Ya=true,Ea,Ia,z=0,Y=0;Ka.padding=
0;var v=da.g("tooltip").attr({zIndex:8}).add(),w=da.rect(Oa,Oa,0,0,m.borderRadius,na).attr({fill:m.backgroundColor,"stroke-width":na}).add(v).shadow(m.shadow),L=da.text("",Na+Oa,la(Ka.fontSize)+Na+Oa).attr({zIndex:1}).css(Ka).add(v);v.hide();return{shared:za,refresh:function(E){var D,M,ha,oa=0,va={},fb=[];ha=E.tooltipPos;D=m.formatter||i;va=p.hoverPoints;if(za){va&&t(va,function(eb){eb.setState()});p.hoverPoints=E;t(E,function(eb){eb.setState(Ab);oa+=eb.plotY;fb.push(eb.getLabelConfig())});M=E[0].plotX;
oa=X(oa)/E.length;va={x:E[0].category};va.points=fb;E=E[0]}else va=E.getLabelConfig();va=D.call(va);R=E.series;M=za?M:E.plotX;oa=za?oa:E.plotY;D=X(ha?ha[0]:qa?Ba-oa:M);M=X(ha?ha[1]:qa?xa-M:oa);ha=za||!E.series.isCartesian||lc(D,M);if(va===false||!ha)x();else{if(Ya){v.show();Ya=false}L.attr({text:va});ha=L.getBBox();Ea=ha.width+2*Na;Ia=ha.height+2*Na;w.attr({width:Ea,height:Ia,stroke:m.borderColor||E.color||R.color||"#606060"});D=D-Ea+Z-25;M=M-Ia+ea+10;if(D<7){D=7;M-=30}if(M<5)M=5;else if(M+Ia>Ra)M=
Ra-Ia-5;y(X(D-Oa),X(M-Oa))}if(N){N=sc(N);for(D=N.length;D--;){M=E.series[D?"yAxis":"xAxis"];if(N[D]&&M){M=M.getPlotLinePath(E[D?"y":"x"],1);if(ba[D])ba[D].attr({d:M,visibility:ub});else{ha={"stroke-width":N[D].width||1,stroke:N[D].color||"#C0C0C0",zIndex:2};if(N[D].dashStyle)ha.dashstyle=N[D].dashStyle;ba[D]=da.path(M).attr(ha).add()}}}}},hide:x}}function f(m,i){function y(z){var Y,v=Od&&wa.width/wa.documentElement.clientWidth-1,w,L,E;z=z||ab.event;if(!z.target)z.target=z.srcElement;Y=z.touches?z.touches.item(0):
z;if(z.type!=="mousemove"||ab.opera||v){w=ya;L={left:w.offsetLeft,top:w.offsetTop};for(w=w.offsetParent;w;){L.left+=w.offsetLeft;L.top+=w.offsetTop;if(w!==wa.body&&w!==wa.documentElement){L.left-=w.scrollLeft;L.top-=w.scrollTop}w=w.offsetParent}uc=L;w=uc.left;L=uc.top}if(Cc){E=z.x;Y=z.y}else if(Y.layerX===Ua){E=Y.pageX-w;Y=Y.pageY-L}else{E=z.layerX;Y=z.layerY}if(v){E+=X((v+1)*w-w);Y+=X((v+1)*L-L)}return pa(z,{chartX:E,chartY:Y})}function x(z){var Y={xAxis:[],yAxis:[]};t(bb,function(v){var w=v.translate,
L=v.isXAxis;Y[L?"xAxis":"yAxis"].push({axis:v,value:w((qa?!L:L)?z.chartX-Z:xa-z.chartY+ea,true)})});return Y}function R(){var z=m.hoverSeries,Y=m.hoverPoint;Y&&Y.onMouseOut();z&&z.onMouseOut();vc&&vc.hide();nd=null}function na(){if(za){var z={xAxis:[],yAxis:[]},Y=za.getBBox(),v=Y.x-Z,w=Y.y-ea;if(Ka){t(bb,function(L){var E=L.translate,D=L.isXAxis,M=qa?!D:D,ha=E(M?v:xa-w-Y.height,true,0,0,1);E=E(M?v+Y.width:xa-w,true,0,0,1);z[D?"xAxis":"yAxis"].push({axis:L,min:qb(ha,E),max:Fa(ha,E)})});Pa(m,"selection",
z,od)}za=za.destroy()}m.mouseIsDown=pd=Ka=false;Gb(wa,Nb?"touchend":"mouseup",na)}var N,ba,Ka,za,Na=u.zoomType,Oa=/x/.test(Na),Ya=/y/.test(Na),Ea=Oa&&!qa||Ya&&qa,Ia=Ya&&!qa||Oa&&qa;Rc=function(){if(Sc){Sc.translate(Z,ea);qa&&Sc.attr({width:m.plotWidth,height:m.plotHeight}).invert()}else m.trackerGroup=Sc=da.g("tracker").attr({zIndex:9}).add()};Rc();if(i.enabled)m.tooltip=vc=e(i);(function(){var z=true;ya.onmousedown=function(v){v=y(v);m.mouseIsDown=pd=true;N=v.chartX;ba=v.chartY;Sa(wa,Nb?"touchend":
"mouseup",na)};var Y=function(v){if(!(v&&v.touches&&v.touches.length>1)){v=y(v);if(!Nb)v.returnValue=false;var w=v.chartX,L=v.chartY,E=!lc(w-Z,L-ea);if(Nb&&v.type==="touchstart")if(Ca(v.target,"isTracker"))m.runTrackerClick||v.preventDefault();else!de&&!E&&v.preventDefault();if(E){z||R();if(w<Z)w=Z;else if(w>Z+Ba)w=Z+Ba;if(L<ea)L=ea;else if(L>ea+xa)L=ea+xa}if(pd&&v.type!=="touchstart"){Ka=Math.sqrt(Math.pow(N-w,2)+Math.pow(ba-L,2));if(Ka>10){if(mc&&(Oa||Ya)&&lc(N-Z,ba-ea))za||(za=da.rect(Z,ea,Ea?
1:Ba,Ia?1:xa,0).attr({fill:"rgba(69,114,167,0.25)",zIndex:7}).add());if(za&&Ea){w=w-N;za.attr({width:db(w),x:(w>0?0:w)+N})}if(za&&Ia){L=L-ba;za.attr({height:db(L),y:(L>0?0:L)+ba})}}}else if(!E){var D;L=m.hoverPoint;w=m.hoverSeries;var M,ha,oa=Xa,va=qa?v.chartY:v.chartX-Z;if(vc&&i.shared){D=[];M=Ga.length;for(ha=0;ha<M;ha++)if(Ga[ha].visible&&Ga[ha].tooltipPoints.length){v=Ga[ha].tooltipPoints[va];v._dist=db(va-v.plotX);oa=qb(oa,v._dist);D.push(v)}for(M=D.length;M--;)D[M]._dist>oa&&D.splice(M,1);if(D.length&&
D[0].plotX!==nd){vc.refresh(D);nd=D[0].plotX}}if(w&&w.tracker)(v=w.tooltipPoints[va])&&v!==L&&v.onMouseOver()}return(z=E)||!mc}};ya.onmousemove=Y;Sa(ya,"mouseleave",R);ya.ontouchstart=function(v){if(Oa||Ya)ya.onmousedown(v);Y(v)};ya.ontouchmove=Y;ya.ontouchend=function(){Ka&&R()};ya.onclick=function(v){var w=m.hoverPoint;v=y(v);v.cancelBubble=true;if(!Ka)if(w&&Ca(v.target,"isTracker")){var L=w.plotX,E=w.plotY;pa(w,{pageX:uc.left+Z+(qa?Ba-E:L),pageY:uc.top+ea+(qa?xa-L:E)});Pa(w.series,"click",pa(v,
{point:w}));w.firePointEvent("click",v)}else{pa(v,x(v));lc(v.chartX-Z,v.chartY-ea)&&Pa(m,"click",v)}Ka=false}})();Pd=setInterval(function(){md&&md()},32);pa(this,{zoomX:Oa,zoomY:Ya,resetTracker:R})}function g(m){var i=m.type||u.type||u.defaultSeriesType,y=vb[i],x=p.hasRendered;if(x)if(qa&&i==="column")y=vb.bar;else if(!qa&&i==="bar")y=vb.column;i=new y;i.init(p,m);if(!x&&i.inverted)qa=true;if(i.isCartesian)mc=i.isCartesian;Ga.push(i);return i}function h(){u.alignTicks!==false&&t(bb,function(m){m.adjustTickAmount()});
Lb=null}function j(m){var i=p.isDirtyLegend,y,x=p.isDirtyBox,R=Ga.length,na=R,N=p.clipRect;for(fc(m,p);na--;){m=Ga[na];if(m.isDirty&&m.options.stacking){y=true;break}}if(y)for(na=R;na--;){m=Ga[na];if(m.options.stacking)m.isDirty=true}t(Ga,function(ba){if(ba.isDirty){ba.cleanData();ba.getSegments();if(ba.options.legendType==="point")i=true}});if(i&&qd.renderLegend){qd.renderLegend();p.isDirtyLegend=false}if(mc){if(!Tc){Lb=null;t(bb,function(ba){ba.setScale()})}h();wc();t(bb,function(ba){if(ba.isDirty||
x){ba.redraw();x=true}})}if(x){rd();Rc();if(N){Uc(N);N.animate({width:p.plotSizeX,height:p.plotSizeY})}}t(Ga,function(ba){if(ba.isDirty&&ba.visible&&(!ba.isCartesian||ba.xAxis))ba.redraw()});kc&&kc.resetTracker&&kc.resetTracker();Pa(p,"redraw")}function l(){var m=a.xAxis||{},i=a.yAxis||{},y;m=sc(m);t(m,function(x,R){x.index=R;x.isX=true});i=sc(i);t(i,function(x,R){x.index=R});bb=m.concat(i);p.xAxis=[];p.yAxis=[];bb=nc(bb,function(x){y=new c(p,x);p[y.isXAxis?"xAxis":"yAxis"].push(y);return y});h()}
function n(m,i){Hb=sa(a.title,m);xc=sa(a.subtitle,i);t([["title",m,Hb],["subtitle",i,xc]],function(y){var x=y[0],R=p[x],na=y[1];y=y[2];if(R&&na){R.destroy();R=null}if(y&&y.text&&!R)p[x]=da.text(y.text,0,0).attr({align:y.align,"class":"highcharts-"+x,zIndex:1}).css(y.style).add().align(y,false,Ob)})}function C(){mb=u.renderTo;Qd=oc+sd++;if(Qb(mb))mb=wa.getElementById(mb);mb.innerHTML="";if(!mb.offsetWidth){Wb=mb.cloneNode(0);La(Wb,{position:pc,top:"-9999px",display:""});wa.body.appendChild(Wb)}Vc=
(Wb||mb).offsetWidth;yc=(Wb||mb).offsetHeight;p.chartWidth=Xa=u.width||Vc||600;p.chartHeight=Ra=u.height||(yc>19?yc:400);p.container=ya=ib(Rb,{className:"highcharts-container"+(u.className?" "+u.className:""),id:Qd},pa({position:Rd,overflow:gb,width:Xa+$a,height:Ra+$a,textAlign:"left"},u.style),Wb||mb);p.renderer=da=u.forExport?new Wc(ya,Xa,Ra,true):new Xc(ya,Xa,Ra);var m,i;if(Sd&&ya.getBoundingClientRect){m=function(){La(ya,{left:0,top:0});i=ya.getBoundingClientRect();La(ya,{left:-(i.left-la(i.left))+
$a,top:-(i.top-la(i.top))+$a})};m();Sa(ab,"resize",m);Sa(p,"destroy",function(){Gb(ab,"resize",m)})}}function G(){function m(){var y=u.width||mb.offsetWidth,x=u.height||mb.offsetHeight;if(y&&x){if(y!==Vc||x!==yc){clearTimeout(i);i=setTimeout(function(){td(y,x,false)},100)}Vc=y;yc=x}}var i;Sa(ab,"resize",m);Sa(p,"destroy",function(){Gb(ab,"resize",m)})}function fa(){var m=a.labels,i=a.credits,y;n();qd=p.legend=new ee(p);wc();t(bb,function(x){x.setTickPositions(true)});h();wc();rd();mc&&t(bb,function(x){x.render()});
if(!p.seriesGroup)p.seriesGroup=da.g("series-group").attr({zIndex:3}).add();t(Ga,function(x){x.translate();x.setTooltipPoints();x.render()});m.items&&t(m.items,function(){var x=pa(m.style,this.style),R=la(x.left)+Z,na=la(x.top)+ea+12;delete x.left;delete x.top;da.text(this.html,R,na).attr({zIndex:2}).css(x).add()});if(!p.toolbar)p.toolbar=d(p);if(i.enabled&&!p.credits){y=i.href;da.text(i.text,0,0).on("click",function(){if(y)location.href=y}).attr({align:i.position.align,zIndex:8}).css(i.style).add().align(i.position)}Rc();
p.hasRendered=true;if(Wb){mb.appendChild(ya);Hc(Wb)}}function K(){var m=Ga.length,i=ya&&ya.parentNode;Pa(p,"destroy");Gb(ab,"unload",K);Gb(p);for(t(bb,function(y){Gb(y)});m--;)Ga[m].destroy();if(ya){ya.innerHTML="";Gb(ya);i&&i.removeChild(ya);ya=null}if(da)da.alignedObjects=null;clearInterval(Pd);for(m in p)delete p[m]}function ia(){if(!zc&&ab==ab.top&&wa.readyState!=="complete")wa.attachEvent("onreadystatechange",function(){wa.detachEvent("onreadystatechange",ia);wa.readyState==="complete"&&ia()});
else{Yc=Pb=0;C();ud();vd();t(a.series||[],function(m){g(m)});p.inverted=qa=B(qa,a.chart.inverted);l();p.render=fa;p.tracker=kc=new f(p,a.tooltip);fa();Pa(p,"load");b&&b.apply(p,[p]);t(p.callbacks,function(m){m.apply(p,[p])})}}Nc=sa(Nc,Va.xAxis);jd=sa(jd,Va.yAxis);Va.xAxis=Va.yAxis=null;a=sa(Va,a);var u=a.chart,P=u.margin;P=Kb(P)?P:[P,P,P,P];var O=B(u.marginTop,P[0]),Q=B(u.marginRight,P[1]),H=B(u.marginBottom,P[2]),S=B(u.marginLeft,P[3]),Ta=u.spacingTop,cb=u.spacingRight,Ib=u.spacingBottom,Jb=u.spacingLeft,
Ob,Hb,xc,ea,Eb,sb,Z,Vb,mb,Wb,ya,Qd,Vc,yc,Xa,Ra,ld,Qc,Zc,wd,xd,$c,p=this,de=(P=u.events)&&!!P.click,yd,lc,vc,pd,dc,Td,zd,xa,Ba,kc,Sc,Rc,qd,Xb,Yb,uc,mc=u.showAxes,Tc=0,bb=[],Lb,Ga=[],qa,da,md,Pd,nd,rd,wc,ud,vd,td,od,Ud,ee=function(m){function i(I,ja){var T=I.legendItem,ra=I.legendLine,Da=I.legendSymbol,Ha=Ia.color,Ma=ja?N.itemStyle.color:Ha,ca=ja?I.color:Ha;Ha=ja?I.pointAttr[hb]:{stroke:Ha,fill:Ha};T&&T.css({fill:Ma});ra&&ra.attr({stroke:ca});Da&&Da.attr(Ha)}function y(I,ja,T){var ra=I.legendItem,Da=
I.legendLine,Ha=I.legendSymbol;I=I.checkbox;ra&&ra.attr({x:ja,y:T});Da&&Da.translate(ja,T-4);Ha&&Ha.attr({x:ja+Ha.xOff,y:T+Ha.yOff});if(I){I.x=ja;I.y=T}}function x(){t(Na,function(I){var ja=I.checkbox,T=fb.alignAttr;ja&&La(ja,{left:T.translateX+I.legendItemWidth+ja.x-40+$a,top:T.translateY+ja.y-11+$a})})}function R(I){var ja,T,ra,Da,Ha=I.legendItem;Da=I.series||I;var Ma=Da.options,ca=Ma&&Ma.borderWidth||0;if(!Ha){Da=/^(bar|pie|area|column)$/.test(Da.type);I.legendItem=Ha=da.text(N.labelFormatter.call(I),
0,0).css(I.visible?Ya:Ia).on("mouseover",function(){I.setState(Ab);Ha.css(Ea)}).on("mouseout",function(){Ha.css(I.visible?Ya:Ia);I.setState()}).on("click",function(){var Db=function(){I.setVisible()};I.firePointEvent?I.firePointEvent("legendItemClick",null,Db):Pa(I,"legendItemClick",null,Db)}).attr({zIndex:2}).add(fb);if(!Da&&Ma&&Ma.lineWidth){var aa={"stroke-width":Ma.lineWidth,zIndex:2};if(Ma.dashStyle)aa.dashstyle=Ma.dashStyle;I.legendLine=da.path([Za,-Ka-za,0,Ja,-za,0]).attr(aa).add(fb)}if(Da)ja=
da.rect(T=-Ka-za,ra=-11,Ka,12,2).attr({zIndex:3}).add(fb);else if(Ma&&Ma.marker&&Ma.marker.enabled)ja=da.symbol(I.symbol,T=-Ka/2-za,ra=-4,Ma.marker.radius).attr({zIndex:3}).add(fb);if(ja){ja.xOff=T+ca%2/2;ja.yOff=ra+ca%2/2}I.legendSymbol=ja;i(I,I.visible);if(Ma&&Ma.showCheckbox){I.checkbox=ib("input",{type:"checkbox",checked:I.selected,defaultChecked:I.selected},N.itemCheckboxStyle,ya);Sa(I.checkbox,"click",function(Db){Pa(I,"checkboxClick",{checked:Db.target.checked},function(){I.select()})})}}ja=
Ha.getBBox();T=I.legendItemWidth=N.itemWidth||Ka+za+ja.width+Y;M=ja.height;if(ba&&L-w+T>(Fb||Xa-2*z-w)){L=w;E+=M}D=E;y(I,L,E);if(ba)L+=T;else E+=M;eb=Fb||Fa(ba?L-w:T,eb)}function na(){L=w;E=v;D=eb=0;fb||(fb=da.g("legend").attr({zIndex:7}).add());Na=[];t(Ub,function(ra){var Da=ra.options;if(Da.showInLegend)Na=Na.concat(Da.legendType==="point"?ra.data:ra)});Na.sort(function(ra,Da){return(ra.options.legendIndex||0)-(Da.options.legendIndex||0)});hc&&Na.reverse();t(Na,R);Xb=Fb||eb;Yb=D-v+M;if(oa||va){Xb+=
2*z;Yb+=2*z;if(ha)Xb>0&&Yb>0&&ha.animate(ha.crisp(null,null,null,Xb,Yb));else ha=da.rect(0,0,Xb,Yb,N.borderRadius,oa||0).attr({stroke:N.borderColor,"stroke-width":oa||0,fill:va||jb}).add(fb).shadow(N.shadow);ha[Na.length?"show":"hide"]()}for(var I=["left","right","top","bottom"],ja,T=4;T--;){ja=I[T];if(Oa[ja]&&Oa[ja]!=="auto"){N[T<2?"align":"verticalAlign"]=ja;N[T<2?"x":"y"]=la(Oa[ja])*(T%2?-1:1)}}fb.align(pa(N,{width:Xb,height:Yb}),true,Ob);Tc||x()}var N=m.options.legend;if(N.enabled){var ba=N.layout===
"horizontal",Ka=N.symbolWidth,za=N.symbolPadding,Na,Oa=N.style,Ya=N.itemStyle,Ea=N.itemHoverStyle,Ia=N.itemHiddenStyle,z=la(Oa.padding),Y=20,v=18,w=4+z+Ka+za,L,E,D,M=0,ha,oa=N.borderWidth,va=N.backgroundColor,fb,eb,Fb=N.width,Ub=m.series,hc=N.reversed;na();Sa(m,"endResize",x);return{colorizeItem:i,destroyItem:function(I){var ja=I.checkbox;t(["legendItem","legendLine","legendSymbol"],function(T){I[T]&&I[T].destroy()});ja&&Hc(I.checkbox)},renderLegend:na}}};lc=function(m,i){return m>=0&&m<=Ba&&i>=0&&
i<=xa};Ud=function(){Pa(p,"selection",{resetSelection:true},od);p.toolbar.remove("zoom")};od=function(m){var i=Va.lang,y=p.pointCount<100;p.toolbar.add("zoom",i.resetZoom,i.resetZoomTitle,Ud);!m||m.resetSelection?t(bb,function(x){x.setExtremes(null,null,false,y)}):t(m.xAxis.concat(m.yAxis),function(x){var R=x.axis;if(p.tracker[R.isXAxis?"zoomX":"zoomY"])R.setExtremes(x.min,x.max,false,y)});j()};wc=function(){var m=a.legend,i=B(m.margin,10),y=m.x,x=m.y,R=m.align,na=m.verticalAlign,N;ud();if((p.title||
p.subtitle)&&!J(O))if(N=Fa(p.title&&!Hb.floating&&!Hb.verticalAlign&&Hb.y||0,p.subtitle&&!xc.floating&&!xc.verticalAlign&&xc.y||0))ea=Fa(ea,N+B(Hb.margin,15)+Ta);if(m.enabled&&!m.floating)if(R==="right")J(Q)||(Eb=Fa(Eb,Xb-y+i+cb));else if(R==="left")J(S)||(Z=Fa(Z,Xb+y+i+Jb));else if(na==="top")J(O)||(ea=Fa(ea,Yb+x+i+Ta));else if(na==="bottom")J(H)||(sb=Fa(sb,Yb-x+i+Ib));mc&&t(bb,function(ba){ba.getOffset()});J(S)||(Z+=Vb[3]);J(O)||(ea+=Vb[0]);J(H)||(sb+=Vb[2]);J(Q)||(Eb+=Vb[1]);vd()};td=function(m,
i,y){var x=p.title,R=p.subtitle;Tc+=1;fc(y,p);Qc=Ra;ld=Xa;p.chartWidth=Xa=X(m);p.chartHeight=Ra=X(i);La(ya,{width:Xa+$a,height:Ra+$a});da.setSize(Xa,Ra,y);Ba=Xa-Z-Eb;xa=Ra-ea-sb;Lb=null;t(bb,function(na){na.isDirty=true;na.setScale()});t(Ga,function(na){na.isDirty=true});p.isDirtyLegend=true;p.isDirtyBox=true;wc();x&&x.align(null,null,Ob);R&&R.align(null,null,Ob);j(y);Qc=null;Pa(p,"resize");setTimeout(function(){Pa(p,"endResize",null,function(){Tc-=1})},Dc&&Dc.duration||500)};vd=function(){p.plotLeft=
Z=X(Z);p.plotTop=ea=X(ea);p.plotWidth=Ba=X(Xa-Z-Eb);p.plotHeight=xa=X(Ra-ea-sb);p.plotSizeX=qa?xa:Ba;p.plotSizeY=qa?Ba:xa;Ob={x:Jb,y:Ta,width:Xa-Jb-cb,height:Ra-Ta-Ib}};ud=function(){ea=B(O,Ta);Eb=B(Q,cb);sb=B(H,Ib);Z=B(S,Jb);Vb=[0,0,0,0]};rd=function(){var m=u.borderWidth||0,i=u.backgroundColor,y=u.plotBackgroundColor,x=u.plotBackgroundImage,R,na={x:Z,y:ea,width:Ba,height:xa};R=m+(u.shadow?8:0);if(m||i)if(Zc)Zc.animate(Zc.crisp(null,null,null,Xa-R,Ra-R));else Zc=da.rect(R/2,R/2,Xa-R,Ra-R,u.borderRadius,
m).attr({stroke:u.borderColor,"stroke-width":m,fill:i||jb}).add().shadow(u.shadow);if(y)if(wd)wd.animate(na);else wd=da.rect(Z,ea,Ba,xa,0).attr({fill:y}).add().shadow(u.plotShadow);if(x)if(xd)xd.animate(na);else xd=da.image(x,Z,ea,Ba,xa).add();if(u.plotBorderWidth)if($c)$c.animate($c.crisp(null,Z,ea,Ba,xa));else $c=da.rect(Z,ea,Ba,xa,0,u.plotBorderWidth).attr({stroke:u.plotBorderColor,"stroke-width":u.plotBorderWidth,zIndex:4}).add();p.isDirtyBox=false};Sa(ab,"unload",K);u.reflow!==false&&Sa(p,"load",
G);if(P)for(yd in P)Sa(p,yd,P[yd]);p.options=a;p.series=Ga;p.addSeries=function(m,i,y){var x;if(m){fc(y,p);i=B(i,true);Pa(p,"addSeries",{options:m},function(){x=g(m);x.isDirty=true;p.isDirtyLegend=true;i&&p.redraw()})}return x};p.animation=B(u.animation,true);p.destroy=K;p.get=function(m){var i,y,x;for(i=0;i<bb.length;i++)if(bb[i].options.id===m)return bb[i];for(i=0;i<Ga.length;i++)if(Ga[i].options.id===m)return Ga[i];for(i=0;i<Ga.length;i++){x=Ga[i].data;for(y=0;y<x.length;y++)if(x[y].id===m)return x[y]}return null};
p.getSelectedPoints=function(){var m=[];t(Ga,function(i){m=m.concat(Ad(i.data,function(y){return y.selected}))});return m};p.getSelectedSeries=function(){return Ad(Ga,function(m){return m.selected})};p.hideLoading=function(){ad(dc,{opacity:0},{duration:a.loading.hideDuration,complete:function(){La(dc,{display:jb})}});zd=false};p.isInsidePlot=lc;p.redraw=j;p.setSize=td;p.setTitle=n;p.showLoading=function(m){var i=a.loading;if(!dc){dc=ib(Rb,{className:"highcharts-loading"},pa(i.style,{left:Z+$a,top:ea+
$a,width:Ba+$a,height:xa+$a,zIndex:10,display:jb}),ya);Td=ib("span",null,i.labelStyle,dc)}Td.innerHTML=m||a.lang.loading;if(!zd){La(dc,{opacity:0,display:""});ad(dc,{opacity:i.style.opacity},{duration:i.showDuration});zd=true}};p.pointCount=0;ia()}var wa=document,ab=window,ta=Math,X=ta.round,kb=ta.floor,hd=ta.ceil,Fa=ta.max,qb=ta.min,db=ta.abs,nb=ta.cos,Bb=ta.sin,Zb=ta.PI,Vd=Zb*2/360,qc=navigator.userAgent,Cc=/msie/i.test(qc)&&!ab.opera,Ac=wa.documentMode===8,Od=/AppleWebKit/.test(qc),Sd=/Firefox/.test(qc),
zc=!!wa.createElementNS&&!!wa.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,Xc,Nb=wa.documentElement.ontouchstart!==undefined,Pb,Yc,Wd={},sd=0,rb=1,Ic,Va,Oc,Dc,bd,Ua,Rb="div",pc="absolute",Rd="relative",gb="hidden",oc="highcharts-",ub="visible",$a="px",jb="none",Za="M",Ja="L",Xd="rgba(192,192,192,"+(zc?1.0E-6:0.0020)+")",hb="",Ab="hover",Ec,dd,ed,fd,tc,Fc,Gc,Dd,Ed,gd,Fd,Gd,ka=ab.HighchartsAdapter,wb=ka||{},t=wb.each,Ad=wb.grep,nc=wb.map,sa=wb.merge,Yd=wb.hyphenate,Sa=wb.addEvent,
Gb=wb.removeEvent,Pa=wb.fireEvent,ad=wb.animate,Uc=wb.stop,vb={};Oc=function(a,b,c){function d(G){return G.toString().replace(/^([0-9])$/,"0$1")}if(!J(b)||isNaN(b))return"Invalid date";a=B(a,"%Y-%m-%d %H:%M:%S");b=new Date(b*rb);var e,f=b[ed](),g=b[fd](),h=b[tc](),j=b[Fc](),l=b[Gc](),n=Va.lang,C=n.weekdays;n=n.months;b={a:C[g].substr(0,3),A:C[g],d:d(h),e:h,b:n[j].substr(0,3),B:n[j],m:d(j+1),y:l.toString().substr(2,2),Y:l,H:d(f),I:d(f%12||12),l:f%12||12,M:d(b[dd]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",
S:d(b.getSeconds())};for(e in b)a=a.replace("%"+e,b[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};ka&&ka.init&&ka.init();if(!ka&&ab.jQuery){var ob=jQuery;t=function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===false)return c};Ad=ob.grep;nc=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=b.call(a[d],a[d],d,a);return c};sa=function(){var a=arguments;return ob.extend(true,null,a[0],a[1],a[2],a[3])};Yd=function(a){return a.replace(/([A-Z])/g,function(b,c){return"-"+
c.toLowerCase()})};Sa=function(a,b,c){ob(a).bind(b,c)};Gb=function(a,b,c){var d=wa.removeEventListener?"removeEventListener":"detachEvent";if(wa[d]&&!a[d])a[d]=function(){};ob(a).unbind(b,c)};Pa=function(a,b,c,d){var e=ob.Event(b),f="detached"+b;pa(e,c);if(a[b]){a[f]=a[b];a[b]=null}ob(a).trigger(e);if(a[f]){a[b]=a[f];a[f]=null}d&&!e.isDefaultPrevented()&&d(e)};ad=function(a,b,c){var d=ob(a);if(b.d){a.toD=b.d;b.d=1}d.stop();d.animate(b,c)};Uc=function(a){ob(a).stop()};ob.extend(ob.easing,{easeOutQuad:function(a,
b,c,d,e){return-d*(b/=e)*(b-2)+c}});var fe=jQuery.fx.step._default,ge=jQuery.fx.prototype.cur;ob.fx.step._default=function(a){var b=a.elem;b.attr?b.attr(a.prop,a.now):fe.apply(this,arguments)};ob.fx.step.d=function(a){var b=a.elem;if(!a.started){var c=bd.init(b,b.d,b.toD);a.start=c[0];a.end=c[1];a.started=true}b.attr("d",bd.step(a.start,a.end,a.pos,b.toD))};ob.fx.prototype.cur=function(){var a=this.elem;return a.attr?a.attr(this.prop):ge.apply(this,arguments)}}bd={init:function(a,b,c){b=b||"";var d=
a.shift,e=b.indexOf("C")>-1,f=e?7:3,g;b=b.split(" ");c=[].concat(c);var h,j,l=function(n){for(g=n.length;g--;)n[g]===Za&&n.splice(g+1,0,n[g+1],n[g+2],n[g+1],n[g+2])};if(e){l(b);l(c)}if(a.isArea){h=b.splice(b.length-6,6);j=c.splice(c.length-6,6)}if(d){c=[].concat(c).splice(0,f).concat(c);a.shift=false}if(b.length)for(a=c.length;b.length<a;){d=[].concat(b).splice(b.length-f,f);if(e){d[f-6]=d[f-2];d[f-5]=d[f-1]}b=b.concat(d)}if(h){b=b.concat(h);c=c.concat(j)}return[b,c]},step:function(a,b,c,d){var e=
[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;){d=parseFloat(a[f]);e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d}else e=b;return e}};ka={enabled:true,align:"center",x:0,y:15,style:{color:"#666",fontSize:"11px",lineHeight:"14px"}};Va={colors:["#4572A7","#AA4643","#89A54E","#80699B","#3D96AE","#DB843D","#92A8CD","#A47D7C","#B5CA92"],symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:["January","February","March","April","May","June","July",
"August","September","October","November","December"],weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],decimalPoint:".",resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:true},chart:{borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:true,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0"},title:{text:"Chart title",align:"center",y:15,style:{color:"#3E576F",fontSize:"16px"}},subtitle:{text:"",align:"center",y:30,style:{color:"#6D869F"}},plotOptions:{line:{allowPointSelect:false,showCheckbox:false,animation:{duration:1E3},events:{},lineWidth:2,shadow:true,marker:{enabled:true,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:sa(ka,
{enabled:false,y:-6,formatter:function(){return this.y}}),showInLegend:true,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:true}},labels:{style:{position:pc,color:"#3E576F"}},legend:{enabled:true,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderWidth:1,borderColor:"#909090",borderRadius:5,shadow:false,style:{padding:"5px"},itemStyle:{cursor:"pointer",color:"#3E576F"},itemHoverStyle:{cursor:"pointer",color:"#000000"},itemHiddenStyle:{color:"#C0C0C0"},
itemCheckboxStyle:{position:pc,width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0},loading:{hideDuration:100,labelStyle:{fontWeight:"bold",position:Rd,top:"1em"},showDuration:100,style:{position:pc,backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:true,backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,shadow:true,snap:Nb?25:10,style:{color:"#333333",fontSize:"12px",padding:"5px",whiteSpace:"nowrap"}},toolbar:{itemStyle:{color:"#4572A7",
cursor:"pointer"}},credits:{enabled:true,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"10px"}}};var Nc={dateTimeLabelFormats:{second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:false,gridLineColor:"#C0C0C0",labels:ka,lineColor:"#C0D0E0",lineWidth:1,max:null,min:null,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",
minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:false,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#6D869F",fontWeight:"bold"}},type:"linear"},jd=sa(Nc,{endOnTick:true,gridLineWidth:1,tickPixelInterval:72,showLastLabel:true,labels:{align:"right",x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:true,tickWidth:0,
title:{rotation:270,text:"Y-values"},stackLabels:{enabled:false,formatter:function(){return this.total},style:ka.style}}),be={labels:{align:"right",x:-8,y:null},title:{rotation:270}},ae={labels:{align:"left",x:8,y:null},title:{rotation:90}},Nd={labels:{align:"center",x:0,y:14},title:{rotation:0}},$d=sa(Nd,{labels:{y:-5}}),xb=Va.plotOptions;ka=xb.line;xb.spline=sa(ka);xb.scatter=sa(ka,{lineWidth:0,states:{hover:{lineWidth:0}}});xb.area=sa(ka,{});xb.areaspline=sa(xb.area);xb.column=sa(ka,{borderColor:"#FFFFFF",
borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,states:{hover:{brightness:0.1,shadow:false},select:{color:"#C0C0C0",borderColor:"#000000",shadow:false}},dataLabels:{y:null,verticalAlign:null}});xb.bar=sa(xb.column,{dataLabels:{align:"left",x:5,y:0}});xb.pie=sa(ka,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],colorByPoint:true,dataLabels:{distance:30,enabled:true,formatter:function(){return this.point.name},y:5},legendType:"point",marker:null,
size:"75%",showInLegend:false,slicedOffset:10,states:{hover:{brightness:0.1,shadow:false}}});Cd();var $b=function(a){var b=[],c;(function(d){if(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(d))b=[la(c[1]),la(c[2]),la(c[3]),parseFloat(c[4],10)];else if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(d))b=[la(c[1],16),la(c[2],16),la(c[3],16),1]})(a);return{get:function(d){return b&&!isNaN(b[0])?d==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+
")":d==="a"?b[3]:"rgba("+b.join(",")+")":a},brighten:function(d){if(ec(d)&&d!==0){var e;for(e=0;e<3;e++){b[e]+=la(d*255);if(b[e]<0)b[e]=0;if(b[e]>255)b[e]=255}}return this},setOpacity:function(d){b[3]=d;return this}}};Jc.prototype={init:function(a,b){this.element=wa.createElementNS("http://www.w3.org/2000/svg",b);this.renderer=a},animate:function(a,b,c){if(b=B(b,Dc,true)){b=sa(b);if(c)b.complete=c;ad(this,a,b)}else{this.attr(a);c&&c()}},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName,j=
this.renderer,l,n=this.shadows,C,G=this;if(Qb(a)&&J(b)){c=a;a={};a[c]=b}if(Qb(a)){c=a;if(h==="circle")c={x:"cx",y:"cy"}[c]||c;else if(c==="strokeWidth")c="stroke-width";G=Ca(g,c)||this[c]||0;if(c!=="d"&&c!=="visibility")G=parseFloat(G)}else for(c in a){l=false;d=a[c];if(c==="d"){if(d&&d.join)d=d.join(" ");if(/(NaN| {2}|^$)/.test(d))d="M 0 0";this.d=d}else if(c==="x"&&h==="text"){for(e=0;e<g.childNodes.length;e++){f=g.childNodes[e];Ca(f,"x")===Ca(g,"x")&&Ca(f,"x",d)}if(this.rotation)Ca(g,"transform",
"rotate("+this.rotation+" "+d+" "+la(a.y||Ca(g,"y"))+")")}else if(c==="fill")d=j.color(d,g,c);else if(h==="circle"&&(c==="x"||c==="y"))c={x:"cx",y:"cy"}[c]||c;else if(c==="translateX"||c==="translateY"||c==="rotation"||c==="verticalAlign"){this[c]=d;this.updateTransform();l=true}else if(c==="stroke")d=j.color(d,g,c);else if(c==="dashstyle"){c="stroke-dasharray";d=d&&d.toLowerCase();if(d==="solid")d=jb;else if(d){d=d.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot",
"1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(e=d.length;e--;)d[e]=la(d[e])*a["stroke-width"];d=d.join(",")}}else if(c==="isTracker")this[c]=d;else if(c==="width")d=la(d);else if(c==="align"){c="text-anchor";d={left:"start",center:"middle",right:"end"}[d]}if(c==="strokeWidth")c="stroke-width";if(Od&&c==="stroke-width"&&d===0)d=1.0E-6;if(this.symbolName&&/^(x|y|r|start|end|innerR)/.test(c)){if(!C){this.symbolAttr(a);
C=true}l=true}if(n&&/^(width|height|visibility|x|y|d)$/.test(c))for(e=n.length;e--;)Ca(n[e],c,d);if((c==="width"||c==="height")&&h==="rect"&&d<0)d=0;if(c==="text"){this.textStr=d;this.added&&j.buildText(this)}else l||Ca(g,c,d)}return G},symbolAttr:function(a){var b=this;t(["x","y","r","start","end","width","height","innerR"],function(c){b[c]=B(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](X(b.x*2)/2,X(b.y*2)/2,b.r,{start:b.start,end:b.end,width:b.width,height:b.height,innerR:b.innerR})})},
clip:function(a){return this.attr("clip-path","url("+this.renderer.url+"#"+a.id+")")},crisp:function(a,b,c,d,e){var f,g={},h={},j;a=a||this.strokeWidth||0;j=a%2/2;h.x=kb(b||this.x||0)+j;h.y=kb(c||this.y||0)+j;h.width=kb((d||this.width||0)-2*j);h.height=kb((e||this.height||0)-2*j);h.strokeWidth=a;for(f in h)if(this[f]!==h[f])this[f]=g[f]=h[f];return g},css:function(a){var b=this.element;b=a&&a.width&&b.nodeName==="text";var c=a,d;if(a&&a.color)a.fill=a.color;this.styles=a=pa(this.styles,a);if(J(a)){a=
{};for(d in c)a[Yd(d)]=c[d]}if(Cc&&!zc){b&&delete a.width;La(this.element,a)}else this.attr({style:Zd(a)});b&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=b;if(Nb&&a==="click"){a="touchstart";c=function(d){d.preventDefault();b()}}this.element["on"+a]=c;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=true;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||
0,c=this.inverted,d=this.rotation,e=[];if(c){a+=this.attr("width");b+=this.attr("height")}if(a||b)e.push("translate("+a+","+b+")");if(c)e.push("rotate(90) scale(-1,1)");else d&&e.push("rotate("+d+" "+this.x+" "+this.y+")");e.length&&Ca(this.element,"transform",e.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){if(a){this.alignOptions=a;this.alignByTranslate=b;c||this.renderer.alignedObjects.push(this)}else{a=this.alignOptions;b=this.alignByTranslate}c=
B(c,this.renderer);var d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),h={};if(/^(right|center)$/.test(d))f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=X(f);if(/^(bottom|middle)$/.test(e))g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=X(g);this[this.placed?"animate":"attr"](h);this.placed=true;this.alignAttr=h;return this},getBBox:function(){var a,b,c,d=this.rotation,e=d*Vd;try{a=pa({},this.element.getBBox())}catch(f){a={width:0,
height:0}}b=a.width;c=a.height;if(d){a.width=db(c*Bb(e))+db(b*nb(e));a.height=db(c*nb(e))+db(b*Bb(e))}return a},show:function(){return this.attr({visibility:ub})},hide:function(){return this.attr({visibility:gb})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=Ca(f,"zIndex");this.parentInverted=a&&a.inverted;this.textStr!==undefined&&b.buildText(this);if(g){c.handleZ=true;g=la(g)}if(c.handleZ)for(c=0;c<e.length;c++){a=e[c];b=Ca(a,"zIndex");if(a!==f&&
(la(b)>g||!J(g)&&J(b))){d.insertBefore(f,a);return this}}d.appendChild(f);this.added=true;return this},destroy:function(){var a=this.element||{},b=this.shadows,c=a.parentNode,d;a.onclick=a.onmouseout=a.onmouseover=a.onmousemove=null;Uc(this);c&&c.removeChild(a);b&&t(b,function(e){(c=e.parentNode)&&c.removeChild(e)});rc(this.renderer.alignedObjects,this);for(d in this)delete this[d];return null},empty:function(){for(var a=this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a,
b){var c=[],d,e,f=this.element,g=this.parentInverted?"(-1,-1)":"(1,1)";if(a){for(d=1;d<=3;d++){e=f.cloneNode(0);Ca(e,{isShadow:"true",stroke:"rgb(0, 0, 0)","stroke-opacity":0.05*d,"stroke-width":7-2*d,transform:"translate"+g,fill:jb});b?b.element.appendChild(e):f.parentNode.insertBefore(e,f);c.push(e)}this.shadows=c}return this}};var Wc=function(){this.init.apply(this,arguments)};Wc.prototype={Element:Jc,init:function(a,b,c,d){var e=location,f;f=this.createElement("svg").attr({xmlns:"http://www.w3.org/2000/svg",
version:"1.1"});a.appendChild(f.element);this.box=f.element;this.boxWrapper=f;this.alignedObjects=[];this.url=Cc?"":e.href.replace(/#.*?$/,"");this.defs=this.createElement("defs").add();this.forExport=d;this.setSize(b,c,false)},createElement:function(a){var b=new this.Element;b.init(this,a);return b},buildText:function(a){for(var b=a.element,c=B(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,
"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=Ca(b,"x"),h=a.styles,j=Sd&&h&&h["-hc-direction"]==="rtl"&&!this.forExport&&la(qc.split("Firefox/")[1])<4,l,n=h&&la(h.width),C=h&&h["line-height"],G,fa=d.length;fa--;)b.removeChild(d[fa]);n&&!a.added&&this.box.appendChild(b);t(c,function(K,ia){var u,P=0,O;K=K.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");u=K.split("|||");t(u,function(Q){if(Q!==""||u.length===
1){var H={},S=wa.createElementNS("http://www.w3.org/2000/svg","tspan");e.test(Q)&&Ca(S,"style",Q.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"));if(f.test(Q)){Ca(S,"onclick",'location.href="'+Q.match(f)[1]+'"');La(S,{cursor:"pointer"})}Q=(Q.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">");if(j){l=[];for(fa=Q.length;fa--;)l.push(Q.charAt(fa));Q=l.join("")}S.appendChild(wa.createTextNode(Q));if(P)H.dx=3;else H.x=g;if(!P){if(ia){!zc&&a.renderer.forExport&&La(S,{display:"block"});
O=ab.getComputedStyle&&ab.getComputedStyle(G,null).getPropertyValue("line-height");if(!O||isNaN(O))O=C||G.offsetHeight||18;Ca(S,"dy",O)}G=S}Ca(S,H);b.appendChild(S);P++;if(n){Q=Q.replace(/-/g,"- ").split(" ");for(var Ta,cb=[];Q.length||cb.length;){Ta=b.getBBox().width;H=Ta>n;if(!H||Q.length===1){Q=cb;cb=[];if(Q.length){S=wa.createElementNS("http://www.w3.org/2000/svg","tspan");Ca(S,{dy:C||16,x:g});b.appendChild(S);if(Ta>n)n=Ta}}else{S.removeChild(S.firstChild);cb.unshift(Q.pop())}Q.length&&S.appendChild(wa.createTextNode(Q.join(" ").replace(/- /g,
"-")))}}}})})},crispLine:function(a,b){if(a[1]===a[4])a[1]=a[4]=X(a[1])+b%2/2;if(a[2]===a[5])a[2]=a[5]=X(a[2])+b%2/2;return a},path:function(a){return this.createElement("path").attr({d:a,fill:jb})},circle:function(a,b,c){a=Kb(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(Kb(a)){b=a.y;c=a.r;d=a.innerR;e=a.start;f=a.end;a=a.x}return this.symbol("arc",a||0,b||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){if(Kb(a)){b=a.y;c=a.width;
d=a.height;e=a.r;f=a.strokeWidth;a=a.x}e=this.createElement("rect").attr({rx:e,ry:e,fill:jb});return e.attr(e.crisp(f,a,b,Fa(c,0),Fa(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[B(c,true)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){return this.createElement("g").attr(J(a)&&{"class":oc+a})},image:function(a,b,c,d,e){var f={preserveAspectRatio:jb};arguments.length>1&&pa(f,{x:b,y:c,width:d,height:e});f=
this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e){var f,g=this.symbols[a];g=g&&g(X(b),X(c),d,e);var h=/^url\((.*?)\)$/,j;if(g){f=this.path(g);pa(f,{symbolName:a,x:b,y:c,r:d});e&&pa(f,e)}else if(h.test(a)){var l=function(n,C){n.attr({width:C[0],height:C[1]}).translate(-X(C[0]/2),-X(C[1]/2))};j=a.match(h)[1];a=Wd[j];f=this.image(j).attr({x:b,y:c});
if(a)l(f,a);else{f.attr({width:0,height:0});ib("img",{onload:function(){l(f,Wd[j]=[this.width,this.height])},src:j})}}else f=this.circle(b,c,d);return f},symbols:{square:function(a,b,c){c=0.707*c;return[Za,a-c,b-c,Ja,a+c,b-c,a+c,b+c,a-c,b+c,"Z"]},triangle:function(a,b,c){return[Za,a,b-1.33*c,Ja,a+c,b+0.67*c,a-c,b+0.67*c,"Z"]},"triangle-down":function(a,b,c){return[Za,a,b+1.33*c,Ja,a-c,b-0.67*c,a+c,b-0.67*c,"Z"]},diamond:function(a,b,c){return[Za,a,b-c,Ja,a+c,b,a,b+c,a-c,b,"Z"]},arc:function(a,b,c,
d){var e=d.start,f=d.end-1.0E-6,g=d.innerR,h=nb(e),j=Bb(e),l=nb(f);f=Bb(f);d=d.end-e<Zb?0:1;return[Za,a+c*h,b+c*j,"A",c,c,0,d,1,a+c*l,b+c*f,Ja,a+g*l,b+g*f,"A",g,g,0,d,0,a+g*h,b+g*j,"Z"]}},clipRect:function(a,b,c,d){var e=oc+sd++,f=this.createElement("clipPath").attr({id:e}).add(this.defs);a=this.rect(a,b,c,d,0).add(f);a.id=e;return a},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f=this;b=a.linearGradient;c=oc+sd++;var g,h,j;g=f.createElement("linearGradient").attr({id:c,gradientUnits:"userSpaceOnUse",
x1:b[0],y1:b[1],x2:b[2],y2:b[3]}).add(f.defs);t(a.stops,function(l){if(e.test(l[1])){d=$b(l[1]);h=d.get("rgb");j=d.get("a")}else{h=l[1];j=1}f.createElement("stop").attr({offset:l[0],"stop-color":h,"stop-opacity":j}).add(g)});return"url("+this.url+"#"+c+")"}else if(e.test(a)){d=$b(a);Ca(b,c+"-opacity",d.get("a"));return d.get("rgb")}else return a},text:function(a,b,c){var d=Va.chart.style;b=X(B(b,0));c=X(B(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({"font-family":d.fontFamily,"font-size":d.fontSize});
a.x=b;a.y=c;return a}};Xc=Wc;if(!zc){wb=yb(Jc,{init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ",pc,";"];if(b==="shape"||b===Rb)d.push("left:0;top:0;width:10px;height:10px;");if(Ac)d.push("visibility: ",b===Rb?gb:ub);c.push(' style="',d.join(""),'"/>');if(b){c=b===Rb||b==="span"||b==="img"?c.join(""):a.prepVML(c);this.element=ib(c)}this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box;d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);Ac&&d.gVis===
gb&&La(c,{visibility:gb});d.appendChild(c);this.added=true;this.alignOnAdd&&this.updateTransform();return this},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,j=this.renderer,l=this.symbolName,n,C,G=this.shadows,fa=this;if(Qb(a)&&J(b)){c=a;a={};a[c]=b}if(Qb(a)){c=a;fa=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c]}else for(c in a){d=a[c];n=false;if(l&&/^(x|y|r|start|end|width|height|innerR)/.test(c)){if(!C){this.symbolAttr(a);C=true}n=true}else if(c==="d"){d=
d||[];this.d=d.join(" ");e=d.length;for(n=[];e--;)n[e]=ec(d[e])?X(d[e]*10)-5:d[e]==="Z"?"x":d[e];d=n.join(" ")||"x";f.path=d;if(G)for(e=G.length;e--;)G[e].path=d;n=true}else if(c==="zIndex"||c==="visibility"){if(Ac&&c==="visibility"&&h==="DIV"){f.gVis=d;n=f.childNodes;for(e=n.length;e--;)La(n[e],{visibility:d});if(d===ub)d=null}if(d)g[c]=d;n=true}else if(/^(width|height)$/.test(c)){if(this.updateClipping){this[c]=d;this.updateClipping()}else g[c]=d;n=true}else if(/^(x|y)$/.test(c)){this[c]=d;if(f.tagName===
"SPAN")this.updateTransform();else g[{x:"left",y:"top"}[c]]=d}else if(c==="class")f.className=d;else if(c==="stroke"){d=j.color(d,f,c);c="strokecolor"}else if(c==="stroke-width"||c==="strokeWidth"){f.stroked=d?true:false;c="strokeweight";this[c]=d;if(ec(d))d+=$a}else if(c==="dashstyle"){(f.getElementsByTagName("stroke")[0]||ib(j.prepVML(["<stroke/>"]),null,null,f))[c]=d||"solid";this.dashstyle=d;n=true}else if(c==="fill")if(h==="SPAN")g.color=d;else{f.filled=d!==jb?true:false;d=j.color(d,f,c);c="fillcolor"}else if(c===
"translateX"||c==="translateY"||c==="rotation"||c==="align"){if(c==="align")c="textAlign";this[c]=d;this.updateTransform();n=true}else if(c==="text"){this.bBox=null;f.innerHTML=d;n=true}if(G&&c==="visibility")for(e=G.length;e--;)G[e].style[c]=d;if(!n)if(Ac)f[c]=d;else Ca(f,c,d)}return fa},clip:function(a){var b=this,c=a.members;c.push(b);b.destroyClip=function(){rc(c,b)};return b.css(a.getCSS(b.inverted))},css:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width){delete a.width;this.textWidth=
b;this.updateTransform()}this.styles=pa(this.styles,a);La(this.element,a);return this},destroy:function(){this.destroyClip&&this.destroyClip();Jc.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;){c=a[b];c.parentNode.removeChild(c)}},getBBox:function(){var a=this.element,b=this.bBox;if(!b){if(a.nodeName==="text")a.style.position=pc;b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},on:function(a,b){this.element["on"+
a]=function(){var c=ab.event;c.target=c.srcElement;b(c)};return this},updateTransform:function(){if(this.added){var a=this,b=a.element,c=a.translateX||0,d=a.translateY||0,e=a.x||0,f=a.y||0,g=a.textAlign||"left",h={left:0,center:0.5,right:1}[g],j=g&&g!=="left";if(c||d)a.css({marginLeft:c,marginTop:d});a.inverted&&t(b.childNodes,function(P){a.renderer.invertChild(P,b)});if(b.tagName==="SPAN"){var l,n;c=a.rotation;var C;l=0;d=1;var G=0,fa;C=la(a.textWidth);var K=a.xCorr||0,ia=a.yCorr||0,u=[c,g,b.innerHTML,
a.textWidth].join(",");if(u!==a.cTT){if(J(c)){l=c*Vd;d=nb(l);G=Bb(l);La(b,{filter:c?["progid:DXImageTransform.Microsoft.Matrix(M11=",d,", M12=",-G,", M21=",G,", M22=",d,", sizingMethod='auto expand')"].join(""):jb})}l=b.offsetWidth;n=b.offsetHeight;if(l>C){La(b,{width:C+$a,display:"block",whiteSpace:"normal"});l=C}C=X((la(b.style.fontSize)||12)*1.2);K=d<0&&-l;ia=G<0&&-n;fa=d*G<0;K+=G*C*(fa?1-h:h);ia-=d*C*(c?fa?h:1-h:1);if(j){K-=l*h*(d<0?-1:1);if(c)ia-=n*h*(G<0?-1:1);La(b,{textAlign:g})}a.xCorr=K;
a.yCorr=ia}La(b,{left:e+K,top:f+ia});a.cTT=u}}else this.alignOnAdd=true},shadow:function(a,b){var c=[],d,e=this.element,f=this.renderer,g,h=e.style,j,l=e.path;if(l&&typeof l.value!=="string")l="x";if(a){for(d=1;d<=3;d++){j=['<shape isShadow="true" strokeweight="',7-2*d,'" filled="false" path="',l,'" coordsize="100,100" style="',e.style.cssText,'" />'];g=ib(f.prepVML(j),null,{left:la(h.left)+1,top:la(h.top)+1});j=['<stroke color="black" opacity="',0.05*d,'"/>'];ib(f.prepVML(j),null,null,g);b?b.element.appendChild(g):
e.parentNode.insertBefore(g,e);c.push(g)}this.shadows=c}return this}});ka=function(){this.init.apply(this,arguments)};ka.prototype=sa(Wc.prototype,{Element:wb,isIE8:qc.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d;this.alignedObjects=[];d=this.createElement(Rb);a.appendChild(d.element);this.box=d.element;this.boxWrapper=d;this.setSize(b,c,false);if(!wa.namespaces.hcv){wa.namespaces.add("hcv","urn:schemas-microsoft-com:vml");wa.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}},
clipRect:function(a,b,c,d){var e=this.createElement();return pa(e,{members:[],left:a,top:b,width:c,height:d,getCSS:function(f){var g=this.top,h=this.left,j=h+this.width,l=g+this.height;g={clip:"rect("+X(f?h:g)+"px,"+X(f?l:j)+"px,"+X(f?j:l)+"px,"+X(f?g:h)+"px)"};!f&&Ac&&pa(g,{width:j+$a,height:l+$a});return g},updateClipping:function(){t(e.members,function(f){f.css(e.getCSS(f.inverted))})}})},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f,g,h=a.linearGradient,j,l,n,C;t(a.stops,
function(G,fa){if(e.test(G[1])){d=$b(G[1]);f=d.get("rgb");g=d.get("a")}else{f=G[1];g=1}if(fa){n=f;C=g}else{j=f;l=g}});a=90-ta.atan((h[3]-h[1])/(h[2]-h[0]))*180/Zb;c=["<",c,' colors="0% ',j,",100% ",n,'" angle="',a,'" opacity="',C,'" o:opacity2="',l,'" type="gradient" focus="100%" />'];ib(this.prepVML(c),null,null,b)}else if(e.test(a)&&b.tagName!=="IMG"){d=$b(a);c=["<",c,' opacity="',d.get("a"),'"/>'];ib(this.prepVML(c),null,null,b);return d.get("rgb")}else return a},prepVML:function(a){var b=this.isIE8;
a=a.join("");if(b){a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />');a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')}else a=a.replace("<","<hcv:");return a},text:function(a,b,c){var d=Va.chart.style;return this.createElement("span").attr({text:a,x:X(b),y:X(c)}).css({whiteSpace:"nowrap",fontFamily:d.fontFamily,fontSize:d.fontSize})},path:function(a){return this.createElement("shape").attr({coordsize:"100 100",
d:a})},circle:function(a,b,c){return this.symbol("circle").attr({x:a,y:b,r:c})},g:function(a){var b;if(a)b={className:oc+a,"class":oc+a};return this.createElement(Rb).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.css({left:b,top:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(Kb(a)){b=a.y;c=a.width;d=a.height;e=a.r;f=a.strokeWidth;a=a.x}var g=this.symbol("rect");g.r=e;return g.attr(g.crisp(f,a,b,Fa(c,0),Fa(d,0)))},invertChild:function(a,
b){var c=b.style;La(a,{flip:"x",left:la(c.width)-10,top:la(c.height)-10,rotation:-90})},symbols:{arc:function(a,b,c,d){var e=d.start,f=d.end,g=nb(e),h=Bb(e),j=nb(f),l=Bb(f);d=d.innerR;var n=0.07/c,C=d&&0.1/d||0;if(f-e===0)return["x"];else if(2*Zb-f+e<n)j=-n;else if(f-e<C)j=nb(e+C);return["wa",a-c,b-c,a+c,b+c,a+c*g,b+c*h,a+c*j,b+c*l,"at",a-d,b-d,a+d,b+d,a+d*j,b+d*l,a+d*g,b+d*h,"x","e"]},circle:function(a,b,c){return["wa",a-c,b-c,a+c,b+c,a+c,b,a+c,b,"e"]},rect:function(a,b,c,d){if(!J(d))return[];var e=
d.width;d=d.height;var f=a+e,g=b+d;c=qb(c,e,d);return[Za,a+c,b,Ja,f-c,b,"wa",f-2*c,b,f,b+2*c,f-c,b,f,b+c,Ja,f,g-c,"wa",f-2*c,g-2*c,f,g,f,g-c,f-c,g,Ja,a+c,g,"wa",a,g-2*c,a+2*c,g,a+c,g,a,g-c,Ja,a,b+c,"wa",a,b,a+2*c,b+2*c,a,b+c,a+c,b,"x","e"]}}});Xc=ka}Hd.prototype.callbacks=[];var Bc=function(){};Bc.prototype={init:function(a,b){var c;this.series=a;this.applyOptions(b);this.pointAttr={};if(a.options.colorByPoint){c=a.chart.options.colors;if(!this.options)this.options={};this.color=this.options.color=
this.color||c[Pb++];if(Pb>=c.length)Pb=0}a.chart.pointCount++;return this},applyOptions:function(a){var b=this.series;this.config=a;if(ec(a)||a===null)this.y=a;else if(Kb(a)&&!ec(a.length)){pa(this,a);this.options=a}else if(Qb(a[0])){this.name=a[0];this.y=a[1]}else if(ec(a[0])){this.x=a[0];this.y=a[1]}if(this.x===Ua)this.x=b.autoIncrement()},destroy:function(){var a=this,b=a.series,c;b.chart.pointCount--;a===b.chart.hoverPoint&&a.onMouseOut();b.chart.hoverPoints=null;Gb(a);t(["graphic","tracker",
"group","dataLabel","connector"],function(d){a[d]&&a[d].destroy()});a.legendItem&&a.series.chart.legend.destroyItem(a);for(c in a)a[c]=null},getLabelConfig:function(){return{x:this.category,y:this.y,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},select:function(a,b){var c=this,d=c.series.chart;c.selected=a=B(a,!c.selected);c.firePointEvent(a?"select":"unselect");c.setState(a&&"select");b||t(d.getSelectedPoints(),function(e){if(e.selected&&e!==c){e.selected=
false;e.setState(hb);e.firePointEvent("unselect")}})},onMouseOver:function(){var a=this.series.chart,b=a.tooltip,c=a.hoverPoint;c&&c!==this&&c.onMouseOut();this.firePointEvent("mouseOver");b&&!b.shared&&b.refresh(this);this.setState(Ab);a.hoverPoint=this},onMouseOut:function(){this.firePointEvent("mouseOut");this.setState();this.series.chart.hoverPoint=null},tooltipFormatter:function(a){var b=this.series;return['<span style="color:'+b.color+'">',this.name||b.name,"</span>: ",!a?"<b>x = "+(this.name||
this.x)+",</b> ":"","<b>",!a?"y = ":"",this.y,"</b>"].join("")},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g=e.chart;b=B(b,true);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);if(Kb(a)){e.getAttribs();f&&f.attr(d.pointAttr[e.state])}e.isDirty=true;b&&g.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f=d.data;fc(b,e);a=B(a,true);c.firePointEvent("remove",null,function(){rc(f,c);c.destroy();d.isDirty=true;a&&e.redraw()})},firePointEvent:function(a,
b,c){var d=this,e=this.series.options;if(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])this.importEvents();if(a==="click"&&e.allowPointSelect)c=function(f){d.select(null,f.ctrlKey||f.metaKey||f.shiftKey)};Pa(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=sa(this.series.options.point,this.options).events,b;this.events=a;for(b in a)Sa(this,b,a[b]);this.hasImportedEvents=true}},setState:function(a){var b=this.series,c=b.options.states,d=xb[b.type].marker&&
b.options.marker,e=d&&!d.enabled,f=(d=d&&d.states[a])&&d.enabled===false,g=b.stateMarkerGraphic,h=b.chart,j=this.pointAttr;a=a||hb;if(!(a===this.state||this.selected&&a!=="select"||c[a]&&c[a].enabled===false||a&&(f||e&&!d.enabled))){if(this.graphic)this.graphic.attr(j[a]);else{if(a){if(!g)b.stateMarkerGraphic=g=h.renderer.circle(0,0,j[a].r).attr(j[a]).add(b.group);g.translate(this.plotX,this.plotY)}if(g)g[a?"show":"hide"]()}this.state=a}}};var pb=function(){};pb.prototype={isCartesian:true,type:"line",
pointClass:Bc,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;d=a.series.length;this.chart=a;b=this.setOptions(b);pa(this,{index:d,options:b,name:b.name||"Series "+(d+1),state:hb,pointAttr:{},visible:b.visible!==false,selected:b.selected===true});d=b.events;for(c in d)Sa(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=true;this.getColor();this.getSymbol();this.setData(b.data,
false)},autoIncrement:function(){var a=this.options,b=this.xIncrement;b=B(b,a.pointStart,0);this.pointInterval=B(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},cleanData:function(){var a=this.chart,b=this.data,c,d,e=a.smallestInterval,f,g;b.sort(function(h,j){return h.x-j.x});if(this.options.connectNulls)for(g=b.length-1;g>=0;g--)b[g].y===null&&b[g-1]&&b[g+1]&&b.splice(g,1);for(g=b.length-1;g>=0;g--)if(b[g-1]){f=b[g].x-b[g-1].x;if(f>0&&(d===Ua||f<d)){d=f;c=g}}if(e===
Ua||d<e)a.smallestInterval=d;this.closestPoints=c},getSegments:function(){var a=-1,b=[],c=this.data;t(c,function(d,e){if(d.y===null){e>a+1&&b.push(c.slice(a+1,e));a=e}else e===c.length-1&&b.push(c.slice(a+1,e+1))});this.segments=b},setOptions:function(a){var b=this.chart.options.plotOptions;return sa(b[this.type],b.series,a)},getColor:function(){var a=this.chart.options.colors;this.color=this.options.color||a[Pb++]||"#0000ff";if(Pb>=a.length)Pb=0},getSymbol:function(){var a=this.chart.options.symbols;
this.symbol=this.options.marker.symbol||a[Yc++];if(Yc>=a.length)Yc=0},addPoint:function(a,b,c,d){var e=this.data,f=this.graph,g=this.area,h=this.chart;a=(new this.pointClass).init(this,a);fc(d,h);if(f&&c)f.shift=c;if(g){g.shift=c;g.isArea=true}b=B(b,true);e.push(a);c&&e[0].remove(false);this.getAttribs();this.isDirty=true;b&&h.redraw()},setData:function(a,b){var c=this,d=c.data,e=c.initialColor,f=c.chart,g=d&&d.length||0;c.xIncrement=null;if(J(e))Pb=e;for(a=nc(sc(a||[]),function(h){return(new c.pointClass).init(c,
h)});g--;)d[g].destroy();c.data=a;c.cleanData();c.getSegments();c.getAttribs();c.isDirty=true;f.isDirtyBox=true;B(b,true)&&f.redraw(false)},remove:function(a,b){var c=this,d=c.chart;a=B(a,true);if(!c.isRemoving){c.isRemoving=true;Pa(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=true;a&&d.redraw(b)})}c.isRemoving=false},translate:function(){for(var a=this.chart,b=this.options.stacking,c=this.xAxis.categories,d=this.yAxis,e=this.data,f=e.length;f--;){var g=e[f],h=g.x,j=g.y,l=g.low,
n=d.stacks[(j<0?"-":"")+this.stackKey];g.plotX=this.xAxis.translate(h);if(b&&this.visible&&n&&n[h]){l=n[h];h=l.total;l.cum=l=l.cum-j;j=l+j;if(b==="percent"){l=h?l*100/h:0;j=h?j*100/h:0}g.percentage=h?g.y*100/h:0;g.stackTotal=h}if(J(l))g.yBottom=d.translate(l,0,1,0,1);if(j!==null)g.plotY=d.translate(j,0,1,0,1);g.clientX=a.inverted?a.plotHeight-g.plotX:g.plotX;g.category=c&&c[g.x]!==Ua?c[g.x]:g.x}},setTooltipPoints:function(a){var b=this.chart,c=b.inverted,d=[],e=X((c?b.plotTop:b.plotLeft)+b.plotSizeX),
f,g,h=[];if(a)this.tooltipPoints=null;t(this.segments,function(j){d=d.concat(j)});if(this.xAxis&&this.xAxis.reversed)d=d.reverse();t(d,function(j,l){f=d[l-1]?d[l-1]._high+1:0;for(g=j._high=d[l+1]?kb((j.plotX+(d[l+1]?d[l+1].plotX:e))/2):e;f<=g;)h[c?e-f++:f++]=j});this.tooltipPoints=h},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(!(!Nb&&a.mouseIsDown)){b&&b!==this&&b.onMouseOut();this.options.events.mouseOver&&Pa(this,"mouseOver");this.tracker&&this.tracker.toFront();this.setState(Ab);
a.hoverSeries=this}},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut();this&&a.events.mouseOut&&Pa(this,"mouseOut");c&&!a.stickyTracking&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this.chart,c=this.clipRect,d=this.options.animation;if(d&&!Kb(d))d={};if(a){if(!c.isAnimating){c.attr("width",0);c.isAnimating=true}}else{c.animate({width:b.plotSizeX},d);this.animate=null}},drawPoints:function(){var a,b=this.data,c=this.chart,
d,e,f,g,h,j;if(this.options.marker.enabled)for(f=b.length;f--;){g=b[f];d=g.plotX;e=g.plotY;j=g.graphic;if(e!==Ua&&!isNaN(e)){a=g.pointAttr[g.selected?"select":hb];h=a.r;if(j)j.animate({x:d,y:e,r:h});else g.graphic=c.renderer.symbol(B(g.marker&&g.marker.symbol,this.symbol),d,e,h).attr(a).add(this.group)}}},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={};a=a||{};b=b||{};c=c||{};d=d||{};for(f in e){g=e[f];h[f]=B(a[g],b[f],c[f],d[f])}return h},getAttribs:function(){var a=this,
b=xb[a.type].marker?a.options.marker:a.options,c=b.states,d=c[Ab],e,f=a.color,g={stroke:f,fill:f},h=a.data,j=[],l,n=a.pointAttrToOptions,C;if(a.options.marker){d.radius=d.radius||b.radius+2;d.lineWidth=d.lineWidth||b.lineWidth+1}else d.color=d.color||$b(d.color||f).brighten(d.brightness).get();j[hb]=a.convertAttribs(b,g);t([Ab,"select"],function(G){j[G]=a.convertAttribs(c[G],j[hb])});a.pointAttr=j;for(f=h.length;f--;){g=h[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===false)b.radius=
0;e=false;if(g.options)for(C in n)if(J(b[n[C]]))e=true;if(e){l=[];c=b.states||{};e=c[Ab]=c[Ab]||{};if(!a.options.marker)e.color=$b(e.color||g.options.color).brighten(e.brightness||d.brightness).get();l[hb]=a.convertAttribs(b,j[hb]);l[Ab]=a.convertAttribs(c[Ab],j[Ab],l[hb]);l.select=a.convertAttribs(c.select,j.select,l[hb])}else l=j;g.pointAttr=l}},destroy:function(){var a=this,b=a.chart,c=/\/5[0-9\.]+ (Safari|Mobile)\//.test(qc),d,e;Gb(a);a.legendItem&&a.chart.legend.destroyItem(a);t(a.data,function(f){f.destroy()});
t(["area","graph","dataLabelsGroup","group","tracker"],function(f){if(a[f]){d=c&&f==="group"?"hide":"destroy";a[f][d]()}});if(b.hoverSeries===a)b.hoverSeries=null;rc(b.series,a);for(e in a)delete a[e]},drawDataLabels:function(){if(this.options.dataLabels.enabled){var a=this,b,c,d=a.data,e=a.options.dataLabels,f,g=a.dataLabelsGroup,h=a.chart,j=h.inverted,l=a.type,n;n=a.options.stacking;var C=l==="column"||l==="bar",G=e.verticalAlign===null,fa=e.y===null;if(C)if(n){if(G)e=sa(e,{verticalAlign:"middle"});
if(fa)e=sa(e,{y:{top:14,middle:4,bottom:-6}[e.verticalAlign]})}else{if(G)e=sa(e,{verticalAlign:"top"});if(fa)e=sa(e,{y:-6})}if(!g)g=a.dataLabelsGroup=h.renderer.g("data-labels").attr({visibility:a.visible?ub:gb,zIndex:6}).translate(h.plotLeft,h.plotTop).add();n=e.color;if(n==="auto")n=null;e.style.color=B(n,a.color);t(d,function(K){var ia=K.barX,u=ia&&ia+K.barW/2||K.plotX||-999,P=B(K.plotY,-999),O=K.dataLabel,Q=e.align;f=e.formatter.call(K.getLabelConfig());b=(j?h.plotWidth-P:u)+e.x;c=(j?h.plotHeight-
u:P)+e.y;if(l==="column")b+={left:-1,right:1}[Q]*K.barW/2||0;if(O){if(j&&!e.y)c=c+la(O.styles.lineHeight)*0.9-O.getBBox().height/2;O.attr({text:f}).animate({x:b,y:c})}else if(J(f)){O=K.dataLabel=h.renderer.text(f,b,c).attr({align:Q,rotation:e.rotation,zIndex:1}).css(e.style).add(g);j&&!e.y&&O.attr({y:c+la(O.styles.lineHeight)*0.9-O.getBBox().height/2})}if(C&&a.options.stacking){u=K.barY;P=K.barW;K=K.barH;O.align(e,null,{x:j?h.plotWidth-u-K:ia,y:j?h.plotHeight-ia-P:u,width:j?K:P,height:j?P:K})}})}},
drawGraph:function(){var a=this,b=a.options,c=a.graph,d=[],e,f=a.area,g=a.group,h=b.lineColor||a.color,j=b.lineWidth,l=b.dashStyle,n,C=a.chart.renderer,G=a.yAxis.getThreshold(b.threshold||0),fa=/^area/.test(a.type),K=[],ia=[];t(a.segments,function(u){n=[];t(u,function(H,S){if(a.getPointSpline)n.push.apply(n,a.getPointSpline(u,H,S));else{n.push(S?Ja:Za);S&&b.step&&n.push(H.plotX,u[S-1].plotY);n.push(H.plotX,H.plotY)}});if(u.length>1)d=d.concat(n);else K.push(u[0]);if(fa){var P=[],O,Q=n.length;for(O=
0;O<Q;O++)P.push(n[O]);Q===3&&P.push(Ja,n[1],n[2]);if(b.stacking&&a.type!=="areaspline")for(O=u.length-1;O>=0;O--)P.push(u[O].plotX,u[O].yBottom);else P.push(Ja,u[u.length-1].plotX,G,Ja,u[0].plotX,G);ia=ia.concat(P)}});a.graphPath=d;a.singlePoints=K;if(fa){e=B(b.fillColor,$b(a.color).setOpacity(b.fillOpacity||0.75).get());if(f)f.animate({d:ia});else a.area=a.chart.renderer.path(ia).attr({fill:e}).add(g)}if(c)c.animate({d:d});else if(j){c={stroke:h,"stroke-width":j};if(l)c.dashstyle=l;a.graph=C.path(d).attr(c).add(g).shadow(b.shadow)}},
render:function(){var a=this,b=a.chart,c,d,e=a.options,f=e.animation,g=f&&a.animate;f=g?f&&f.duration||500:0;var h=a.clipRect;d=b.renderer;if(!h){h=a.clipRect=!b.hasRendered&&b.clipRect?b.clipRect:d.clipRect(0,0,b.plotSizeX,b.plotSizeY);if(!b.clipRect)b.clipRect=h}if(!a.group){c=a.group=d.g("series");if(b.inverted){d=function(){c.attr({width:b.plotWidth,height:b.plotHeight}).invert()};d();Sa(b,"resize",d)}c.clip(a.clipRect).attr({visibility:a.visible?ub:gb,zIndex:e.zIndex}).translate(b.plotLeft,b.plotTop).add(b.seriesGroup)}a.drawDataLabels();
g&&a.animate(true);a.drawGraph&&a.drawGraph();a.drawPoints();a.options.enableMouseTracking!==false&&a.drawTracker();g&&a.animate();setTimeout(function(){h.isAnimating=false;if((c=a.group)&&h!==b.clipRect&&h.renderer){c.clip(a.clipRect=b.clipRect);h.destroy()}},f);a.isDirty=false},redraw:function(){var a=this.chart,b=this.group;if(b){a.inverted&&b.attr({width:a.plotWidth,height:a.plotHeight});b.animate({translateX:a.plotLeft,translateY:a.plotTop})}this.translate();this.setTooltipPoints(true);this.render()},
setState:function(a){var b=this.options,c=this.graph,d=b.states;b=b.lineWidth;a=a||hb;if(this.state!==a){this.state=a;if(!(d[a]&&d[a].enabled===false)){if(a)b=d[a].lineWidth||b+1;if(c&&!c.dashstyle)c.attr({"stroke-width":b},a?0:500)}}},setVisible:function(a,b){var c=this.chart,d=this.legendItem,e=this.group,f=this.tracker,g=this.dataLabelsGroup,h,j=this.data,l=c.options.chart.ignoreHiddenSeries;h=this.visible;h=(this.visible=a=a===Ua?!h:a)?"show":"hide";e&&e[h]();if(f)f[h]();else for(e=j.length;e--;){f=
j[e];f.tracker&&f.tracker[h]()}g&&g[h]();d&&c.legend.colorizeItem(this,a);this.isDirty=true;this.options.stacking&&t(c.series,function(n){if(n.options.stacking&&n.visible)n.isDirty=true});if(l)c.isDirtyBox=true;b!==false&&c.redraw();Pa(this,h)},show:function(){this.setVisible(true)},hide:function(){this.setVisible(false)},select:function(a){this.selected=a=a===Ua?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;Pa(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,
c=[].concat(a.graphPath),d=c.length,e=a.chart,f=e.options.tooltip.snap,g=a.tracker,h=b.cursor;h=h&&{cursor:h};var j=a.singlePoints,l;if(d)for(l=d+1;l--;){c[l]===Za&&c.splice(l+1,0,c[l+1]-f,c[l+2],Ja);if(l&&c[l]===Za||l===d)c.splice(l,0,Ja,c[l-2]+f,c[l-1])}for(l=0;l<j.length;l++){d=j[l];c.push(Za,d.plotX-f,d.plotY,Ja,d.plotX+f,d.plotY)}if(g)g.attr({d:c});else a.tracker=e.renderer.path(c).attr({isTracker:true,stroke:Xd,fill:jb,"stroke-width":b.lineWidth+2*f,visibility:a.visible?ub:gb,zIndex:1}).on(Nb?
"touchstart":"mouseover",function(){e.hoverSeries!==a&&a.onMouseOver()}).on("mouseout",function(){b.stickyTracking||a.onMouseOut()}).css(h).add(e.trackerGroup)}};ka=yb(pb);vb.line=ka;ka=yb(pb,{type:"area"});vb.area=ka;ka=yb(pb,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,j,l,n;if(c&&c<a.length-1){a=f.plotY;l=g.plotX;g=g.plotY;var C;h=(1.5*d+f.plotX)/2.5;j=(1.5*e+a)/2.5;l=(1.5*d+l)/2.5;n=(1.5*e+g)/2.5;C=(n-j)*(l-d)/(l-h)+e-n;j+=C;n+=C;if(j>a&&j>e){j=Fa(a,
e);n=2*e-j}else if(j<a&&j<e){j=qb(a,e);n=2*e-j}if(n>g&&n>e){n=Fa(g,e);j=2*e-n}else if(n<g&&n<e){n=qb(g,e);j=2*e-n}b.rightContX=l;b.rightContY=n}if(c){b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,j||e,d,e];f.rightContX=f.rightContY=null}else b=[Za,d,e];return b}});vb.spline=ka;ka=yb(ka,{type:"areaspline"});vb.areaspline=ka;var cd=yb(pb,{type:"column",pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},init:function(){pb.prototype.init.apply(this,
arguments);var a=this,b=a.chart;b.hasColumn=true;b.hasRendered&&t(b.series,function(c){if(c.type===a.type)c.isDirty=true})},translate:function(){var a=this,b=a.chart,c=a.options,d=c.stacking,e=c.borderWidth,f=0,g=a.xAxis.reversed,h=a.xAxis.categories,j={},l,n;pb.prototype.translate.apply(a);t(b.series,function(H){if(H.type===a.type&&H.visible){if(H.options.stacking){l=H.stackKey;if(j[l]===Ua)j[l]=f++;n=j[l]}else n=f++;H.columnIndex=n}});var C=a.data,G=a.closestPoints;h=db(C[1]?C[G].plotX-C[G-1].plotX:
b.plotSizeX/(h&&h.length||1));G=h*c.groupPadding;var fa=(h-2*G)/f,K=c.pointWidth,ia=J(K)?(fa-K)/2:fa*c.pointPadding,u=Fa(B(K,fa-2*ia),1),P=ia+(G+((g?f-a.columnIndex:a.columnIndex)||0)*fa-h/2)*(g?-1:1),O=a.yAxis.getThreshold(c.threshold||0),Q=B(c.minPointLength,5);t(C,function(H){var S=H.plotY,Ta=H.yBottom||O,cb=H.plotX+P,Ib=hd(qb(S,Ta)),Jb=hd(Fa(S,Ta)-Ib),Ob=a.yAxis.stacks[(H.y<0?"-":"")+a.stackKey],Hb;d&&a.visible&&Ob&&Ob[H.x]&&Ob[H.x].setOffset(P,u);if(db(Jb)<Q){if(Q){Jb=Q;Ib=db(Ib-O)>Q?Ta-Q:O-
(S<=O?Q:0)}Hb=Ib-3}pa(H,{barX:cb,barY:Ib,barW:u,barH:Jb});H.shapeType="rect";S=pa(b.renderer.Element.prototype.crisp.apply({},[e,cb,Ib,u,Jb]),{r:c.borderRadius});if(e%2){S.y-=1;S.height+=1}H.shapeArgs=S;H.trackerArgs=J(Hb)&&sa(H.shapeArgs,{height:Fa(6,Jb+3),y:Hb})})},getSymbol:function(){},drawGraph:function(){},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,e;t(a.data,function(f){var g=f.plotY;if(g!==Ua&&!isNaN(g)&&f.y!==null){d=f.graphic;e=f.shapeArgs;if(d){Uc(d);d.animate(e)}else f.graphic=
c[f.shapeType](e).attr(f.pointAttr[f.selected?"select":hb]).add(a.group).shadow(b.shadow)}})},drawTracker:function(){var a=this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options.cursor,h=g&&{cursor:g},j;t(a.data,function(l){e=l.tracker;d=l.trackerArgs||l.shapeArgs;delete d.strokeWidth;if(l.y!==null)if(e)e.attr(d);else l.tracker=c[l.shapeType](d).attr({isTracker:f,fill:Xd,visibility:a.visible?ub:gb,zIndex:1}).on(Nb?"touchstart":"mouseover",function(n){j=n.relatedTarget||n.fromElement;b.hoverSeries!==
a&&Ca(j,"isTracker")!==f&&a.onMouseOver();l.onMouseOver()}).on("mouseout",function(n){if(!a.options.stickyTracking){j=n.relatedTarget||n.toElement;Ca(j,"isTracker")!==f&&a.onMouseOut()}}).css(h).add(l.group||b.trackerGroup)})},animate:function(a){var b=this,c=b.data;if(!a){t(c,function(d){var e=d.graphic;d=d.shapeArgs;if(e){e.attr({height:0,y:b.yAxis.translate(0,0,1)});e.animate({height:d.height,y:d.y},b.options.animation)}});b.animate=null}},remove:function(){var a=this,b=a.chart;b.hasRendered&&
t(b.series,function(c){if(c.type===a.type)c.isDirty=true});pb.prototype.remove.apply(a,arguments)}});vb.column=cd;ka=yb(cd,{type:"bar",init:function(a){a.inverted=this.inverted=true;cd.prototype.init.apply(this,arguments)}});vb.bar=ka;ka=yb(pb,{type:"scatter",translate:function(){var a=this;pb.prototype.translate.apply(a);t(a.data,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){var a=this,b=a.options.cursor,c=b&&{cursor:b},
d;t(a.data,function(e){(d=e.graphic)&&d.attr({isTracker:true}).on("mouseover",function(){a.onMouseOver();e.onMouseOver()}).on("mouseout",function(){a.options.stickyTracking||a.onMouseOut()}).css(c)})},cleanData:function(){}});vb.scatter=ka;ka=yb(Bc,{init:function(){Bc.prototype.init.apply(this,arguments);var a=this,b;pa(a,{visible:a.visible!==false,name:B(a.name,"Slice")});b=function(){a.slice()};Sa(a,"select",b);Sa(a,"unselect",b);return a},setVisible:function(a){var b=this.series.chart,c=this.tracker,
d=this.dataLabel,e=this.connector,f;f=(this.visible=a=a===Ua?!this.visible:a)?"show":"hide";this.group[f]();c&&c[f]();d&&d[f]();e&&e[f]();this.legendItem&&b.legend.colorizeItem(this,a)},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;fc(c,d);B(b,true);a=this.sliced=J(a)?a:!this.sliced;a={translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop};this.group.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}});ka=yb(pb,{type:"pie",isCartesian:false,pointClass:ka,pointAttrToOptions:{stroke:"borderColor",
"stroke-width":"borderWidth",fill:"color"},getColor:function(){this.initialColor=Pb},animate:function(){var a=this;t(a.data,function(b){var c=b.graphic;b=b.shapeArgs;var d=-Zb/2;if(c){c.attr({r:0,start:d,end:d});c.animate({r:b.r,start:b.start,end:b.end},a.options.animation)}});a.animate=null},translate:function(){var a=0,b=-0.25,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f=c.center.concat([c.size,c.innerSize||0]),g=this.chart,h=g.plotWidth,j=g.plotHeight,l,n,C,G=this.data,fa=2*Zb,K,ia=qb(h,
j),u,P,O,Q=c.dataLabels.distance;f=nc(f,function(H,S){return(u=/%$/.test(H))?[h,j,ia,ia][S]*la(H)/100:H});this.getX=function(H,S){C=ta.asin((H-f[1])/(f[2]/2+Q));return f[0]+(S?-1:1)*nb(C)*(f[2]/2+Q)};this.center=f;t(G,function(H){a+=H.y});t(G,function(H){K=a?H.y/a:0;l=X(b*fa*1E3)/1E3;b+=K;n=X(b*fa*1E3)/1E3;H.shapeType="arc";H.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:l,end:n};C=(n+l)/2;H.slicedTranslation=nc([nb(C)*d+g.plotLeft,Bb(C)*d+g.plotTop],X);P=nb(C)*f[2]/2;O=Bb(C)*f[2]/2;H.tooltipPos=
[f[0]+P*0.7,f[1]+O*0.7];H.labelPos=[f[0]+P+nb(C)*Q,f[1]+O+Bb(C)*Q,f[0]+P+nb(C)*e,f[1]+O+Bb(C)*e,f[0]+P,f[1]+O,Q<0?"center":C<fa/4?"left":"right",C];H.percentage=K*100;H.total=a});this.setTooltipPoints()},render:function(){this.drawPoints();this.options.enableMouseTracking!==false&&this.drawTracker();this.drawDataLabels();this.options.animation&&this.animate&&this.animate();this.isDirty=false},drawPoints:function(){var a=this.chart,b=a.renderer,c,d,e,f=this.options.shadow,g,h;t(this.data,function(j){d=
j.graphic;h=j.shapeArgs;e=j.group;g=j.shadowGroup;if(f&&!g)g=j.shadowGroup=b.g("shadow").attr({zIndex:4}).add();if(!e)e=j.group=b.g("point").attr({zIndex:5}).add();c=j.sliced?j.slicedTranslation:[a.plotLeft,a.plotTop];e.translate(c[0],c[1]);g&&g.translate(c[0],c[1]);if(d)d.animate(h);else j.graphic=b.arc(h).attr(pa(j.pointAttr[hb],{"stroke-linejoin":"round"})).add(j.group).shadow(f,g);j.visible===false&&j.setVisible(false)})},drawDataLabels:function(){var a=this.data,b,c=this.chart,d=this.options.dataLabels,
e=B(d.connectorPadding,10),f=B(d.connectorWidth,1),g,h,j=d.distance>0,l,n,C=this.center[1],G=[[],[],[],[]],fa,K,ia,u,P,O,Q,H=4,S;pb.prototype.drawDataLabels.apply(this);t(a,function(Ta){var cb=Ta.labelPos[7];G[cb<0?0:cb<Zb/2?1:cb<Zb?2:3].push(Ta)});G[1].reverse();G[3].reverse();for(Q=function(Ta,cb){return Ta.y>cb.y};H--;){a=0;b=[].concat(G[H]);b.sort(Q);for(S=b.length;S--;)b[S].rank=S;for(u=0;u<2;u++){n=(O=H%3)?9999:-9999;P=O?-1:1;for(S=0;S<G[H].length;S++){b=G[H][S];if(g=b.dataLabel){h=b.labelPos;
ia=ub;fa=h[0];K=h[1];l||(l=g&&g.getBBox().height);if(j)if(u&&b.rank<a)ia=gb;else if(!O&&K<n+l||O&&K>n-l){K=n+P*l;fa=this.getX(K,H>1);if(!O&&K+l>C||O&&K-l<C)if(u)ia=gb;else a++}if(b.visible===false)ia=gb;if(ia===ub)n=K;if(u){g.attr({visibility:ia,align:h[6]})[g.moved?"animate":"attr"]({x:fa+d.x+({left:e,right:-e}[h[6]]||0),y:K+d.y});g.moved=true;if(j&&f){g=b.connector;h=[Za,fa+(h[6]==="left"?5:-5),K,Ja,fa,K,Ja,h[2],h[3],Ja,h[4],h[5]];if(g){g.animate({d:h});g.attr("visibility",ia)}else b.connector=
g=this.chart.renderer.path(h).attr({"stroke-width":f,stroke:d.connectorColor||"#606060",visibility:ia,zIndex:3}).translate(c.plotLeft,c.plotTop).add()}}}}}}},drawTracker:cd.prototype.drawTracker,getSymbol:function(){}});vb.pie=ka;ab.Highcharts={Chart:Hd,dateFormat:Oc,pathAnim:bd,getOptions:function(){return Va},numberFormat:Bd,Point:Bc,Color:$b,Renderer:Xc,seriesTypes:vb,setOptions:function(a){Va=sa(Va,a);Cd();return Va},Series:pb,addEvent:Sa,createElement:ib,discardElement:Hc,css:La,each:t,extend:pa,
map:nc,merge:sa,pick:B,extendClass:yb,version:"2.1.5"}})();

// Copyright (c) 2007 Gregory SCHURGAST (http://www.negko.com, http://prototools.negko.com)
// 
// 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.
//
// VERSION 1.2.20090611

var TableOrderer = Class.create();
//defining the rest of the class implementation

TableOrderer.prototype = {
	initialize: function(element,options) {
		this.element = element;
		this.options = options;
		
		this.options = Object.extend({
			data: false, 				// array of data
			url: false, 				// url to a JSON application containing the data
			allowMultiselect : true, 	// don't work yet
			unsortedColumn : [],		// array of column you don't want to sort
			dateFormat : 'd', 			// d|m ; d => dd/mm/yyyy; m => mm/dd/yyyy
			filter : false,				// show Filter Option. false | 'top' | 'bottom'
			pageCount : 5,				// Number of items by table 
			paginate : false,		    // show Paginate Option. false | 'top' | 'bottom'
			search : false				// show Gloabal Search . falses | 'top' | 'bottom'
		}, options || {});
		
		// saves tool state data for pagination, filtering and searching. 
		this.tools = {
			page: 1,					// for pagination
			pages: 1,					// for pagination
			filterCol: '',				// for filtering
			filterData: '',				// for filtering
			searchData: ''				// for global searching
		};
		
		// separates text messages out 
		this.msgs = {
			loading: 'Loading...',
			emptyResults: 'No matches found',
			errorURL: 'invalid data',
			errorData: 'no data',
			searchLabel: 'Search : ',
			filterLabel: 'Filter Column : ',
			paginationOf: ' of ',
			paginationPages: ' pages ',
			paginationFirst: '<<',
			paginationPrev: '<',
			paginationNext: '>',
			paginationLast: '>>'
		};
		
		this.cache = [];				// for caching capabilities
		this.isCached = false;			// for caching capabilities
		this.container = $(element);
		this.orderField = false;
		this.order = 'asc';	
		this.thClickbfx = this.thClick.bindAsEventListener(this);
		this.thOverbfx = this.thOver.bindAsEventListener(this);
		this.thOutbfx = this.thOut.bindAsEventListener(this);
		this.setData();
		
	},
	
	// clearCache -- Replaces this.cache with orginal data loaded into the table.
	clearCache : function() {
		this.isCached = false;
		this.cache = this.data;
		
		// Clearing the cache does not clear any ordering done on the data, 
		// just operations that remove records from the user's view (i.e. filtering)
		if(this.orderField) {
			this.orderData(this.orderField);
			if (this.order == 'desc') { this.cache = this.cache.reverse(); }
		} 
	},
	
	// preform -- performs any inital operations needed to create the table after the data has been loaded.
	perform : function(){
		this.tools.pages = Math.ceil(this.cache.size() / this.options.pageCount);
		this.setColumnsName();
		this.clearCache();
		this.createTable();
	},
	
	// getData -- gets table data from a @url. The header response from the URL must be application/json
	// param url: URL from where the total table data resides.
	getData : function(url){
		var transmit = new Ajax.Request(url,{
			onLoading : function(){ $(this.element).update(this.msgs.loading); }.bind(this),
			onSuccess: function(transport) {
				this.data = transport.responseJSON;
				this.perform();
			}.bind(this),
			onFailure : function(){ alert(this.msgs.errorURL); }
		});
	},
	
	// setData -- determines if the data is coming from a URL or from a json string on the page.
	setData : function(){
		if (!this.options.data && !this.options.url){alert(this.msgs.errorData);}
		this.data = this.options.data ? this.options.data : false;
		if(this.data) { this.perform(); } else { this.getData(this.options.url); }
	},

	// orderRule -- determines if @s is a date
	// param s: string representing column data
	orderRule : function (s){
		var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4}|\d{2})/;
		var exp=new RegExp(dateRE);
		if ( exp.test(s) ){
			s = this.options.dateFormat == 'd' ? s.replace(dateRE,"$3$2$1") : s.replace(dateRE,"$3$1$2");
		}
		return s;
	},
	
	// defineOrderField -- keeps track of previous orderField columns and sets the current orderField through the triggering element's id.
	// param e: the event object created that triggered this method
	defineOrderField : function(e){
		this.previousOrderField = this.orderField; 
		this.orderField = Event.element(e).id.replace(this.table.id+'-','');
	},

	/*  if you click on a header for the first time order is ascending
	     else it switches between ascending and descending
	*/
	// defineOrder -- determines what the order of the data should be
	defineOrder : function(){ 
		if (this.previousOrderField == this.orderField){ this.order = this.order == 'desc' ? 'asc' : 'desc'; }
		else { this.order = 'asc'; }
	},
	
	/* Ordonne les données du tableau */
	// orderData -- sorts the table's cache by the @order given it.
	// param order: defines the order that the data should be as ascending (asc) or descending (desc)
	orderData : function(order){
		this.cache = this.cache.sortBy(function(s){
			var v = Object.values(s)[Object.keys(s).indexOf(order)];
			return this.orderRule(v);
		}.bind(this));
	},
	
	// thClick -- event handler for when the user clicks on the th cell of the table. It orders the table data by that column's field.
	// param e: event that triggered handler.
	thClick : function(e){
		this.defineOrderField(e);
		this.defineOrder();
		this.orderData(this.orderField);
		
		if (this.order == 'desc') { this.cache = this.cache.reverse(); }
		
		this.updateTable();
	},
	
	// thOver -- event handler for when the user's mouse goes over the th cell.
	// param e: event that triggered handler
	thOver : function(e){
		Event.element(e).addClassName('on');
	},
	
	// thOut -- event handler for when the user's mouse moves out of the th cell.
	// param e: event that triggered handler
	thOut : function(e){
		Event.element(e).removeClassName('on');
	},
		
	// trClick -- event handler for when user clicks on a table row, highlighting the row
	// param e: event that triggered handler
	trClick : function(e){
		this.setSelected(Event.findElement(e,'tr'));
		var selected;
		var items = Event.findElement(e,'tr').descendants().pluck('innerHTML');
		var json = '{';
		var keys  = Object.keys(this.model);
		
		items.each(function(i,index){
			json += index === 0 ? '' : ', '; 
			json += '"'+keys[index]+'": "'+i+'"';
		});
		json += '}';
		selected = json.evalJSON();
	},
	
	// trOver -- event handler for when the user's mouse moves into a table row.
	// param e: event that triggered handler
	trOver : function(e){
		Event.findElement(e,'tr').addClassName('on');
	},
	
	// trOut -- event handler for when the user's mouse moves out of a table row.
	// param e: event that triggered handler
	trOut : function(e){
		Event.findElement(e,'tr').removeClassName('on');
	},
	
	// setSelected -- what to do when a table row is selected.
	// param elt: the table row that is selected
	setSelected : function(elt){
		if (this.options.allowMultiselect){
			if(elt.hasClassName('selected')) { elt.removeClassName('selected'); } else { elt.addClassName('selected'); }
		}
		else{
		/* */
		}
	},

	// addToolsObserver -- binds the event handlers to the events associated with tools only
	addToolsObserver : function(){
		var tid = this.table.id;

		if (this.options.filter){
			var filterDatakbfx = this.filterData.bindAsEventListener(this);
			Event.observe(tid+'-filter-column','change',filterDatakbfx);
			Event.observe(tid+'-filter-data','keyup',filterDatakbfx);
		}

		if (this.options.search){
			var searchDatakbfx = this.searchData.bindAsEventListener(this);
			Event.observe(tid+'-search-data','keyup',searchDatakbfx);
		}
		
		if(this.options.paginate){
			var pagerDatabfx = this.pagerData.bindAsEventListener(this);
			Event.observe(tid + '-page-prev', 'click', pagerDatabfx);
			Event.observe(tid + '-page-next', 'click', pagerDatabfx);
			Event.observe(tid + '-page-last', 'click', pagerDatabfx);
			Event.observe(tid + '-page-first', 'click', pagerDatabfx);
		}
	},
	
	// addTableObserver -- binds event handlers to the events associated with the table generated.
	addTableObserver : function() {
		var tid = this.table.id;
		$$('#'+tid+' th')
			.invoke('observe','click',this.thClickbfx)
			.invoke('observe','mouseover',this.thOverbfx)
			.invoke('observe','mouseout',this.thOutbfx);
		
		$$('#'+tid+' tr.data')
			.invoke('observe','click',this.trClick.bindAsEventListener(this))
			.invoke('observe','mouseover',this.trOver.bindAsEventListener(this))
			.invoke('observe','mouseout',this.trOut.bindAsEventListener(this));
	},
	
	// Two approaches to filtering:
	// 1. If pagination is turned ON then we just recreate the rows using updateTable. Somewhat costly due to creating new elements but hopefully offset by a smaller amount of rows being shown.
	// 2. If pagination is turned OFF then go the slick way of just hiding the rows, which is much faster.
	//
	// filterData -- handler for filtering data. Updates this.tools internal state information for the filter tool and updates the table. Tried optimizing it as much as possible.
	// param e: the event triggering handler
	filterData : function(e){
		var tid = this.table.id;
		var caller = Event.element(e);
		
		if(caller.id == tid + '-filter-column' && this.tools.filterData === ''){
			this.tools.filterCol = $F(tid + '-filter-column');
			return; // if we are just changing the column option and we had not filtered previously then just update the column info.
		}
		
		// Update state information for filter tool.
		this.tools.filterData = $F(tid + '-filter-data');
		if(caller.id == tid + '-filter-column') {
			// clear filter data when changing which column we are filtering on.
			$(tid + '-filter-data').clear();
			this.tools.filterCol = $F(tid + '-filter-column');
			this.tools.filterData = '';
		}

		// Anytime we filter there is a good chance our data view will change.
		this.clearCache();
		
		if(this.options.paginate) {
			this.updateTable();
			return;
		}

		$$('#'+tid+' td.' + tid+'-column-'+this.tools.filterCol).each(function(i){
			i.ancestors()[1].show();
			if(!i.innerHTML.toUpperCase().include(this.tools.filterData.toUpperCase())){
				i.ancestors()[1].hide();
			}
		});
	},

	// pagerData -- handler for pagination. This is modifies the internal state of this.tools for pagination and then updates the table. It supports first, last, next and previous operations on the pages.
	// param e: the event that triggered the handler
	pagerData : function(e){
		var tid = this.table.id;
		var caller = Event.element(e);
		
		switch(caller.id) {
			case tid+'-page-next':
				this.tools.page = ((++this.tools.page) > this.tools.pages) ? --this.tools.page : this.tools.page;
			break;
			case tid+'-page-prev':
				this.tools.page = ((--this.tools.page) > this.tools.pages) ? ++this.tools.page : this.tools.page;
			break;
			case tid+'-page-last':
				this.tools.page = this.tools.pages;
			break;
			default:
				this.tools.page = 1;
		}
		this.updateTable();
	},

	// searchData -- handler for search tool. This modifies the internal state of this.tools for search tool, clears the cache and updates the table.
	// param e: the event that triggered the handler
	searchData : function(e){
		var tid = this.table.id;
		
		// Update state information for search tool.
		this.tools.searchData = $F(tid + '-search-data');

		// Anytime we filter there is a good chance our data view will change.
		this.clearCache();
		
		this.updateTable();
	},
	
	// makeColumnUnsortable -- takes the @columnId and makes its associated th cell unclickable by removing  any user visual cue that it is a sortable column
	// param columnId: the name of the column (field) that will be unsortable. This the same name that is used as part of the column's id.
	makeColumnUnsortable : function(columnId){
		columnId = this.table.id + '-' + columnId;
		$(columnId).setStyle({'backgroundImage' : 'none'});
		Event.stopObserving($(columnId),'click', this.thClickbfx);
		Event.stopObserving($(columnId),'mouseover', this.thOverbfx);
		Event.stopObserving($(columnId),'mouseout', this.thOutbfx);
	},
	
	// makeUnsort -- cycles through each item of options.unsortedColumn and makes them unsortable.
	makeUnsort : function(){
		this.options.unsortedColumn.each(function(i){
			if($(this.table.id + '-' + i)){ this.makeColumnUnsortable(i);}
		}.bind(this));
	},
	
	// createTable -- creates the inital table being ran just once. It writes out the HTML elements for the table and tools interface (i.e. pagination).
	createTable : function(){
		this.container.update();
		this.container.insert({ top: '<table cellspacing="1" cellpadding="0" id="data-grid-'+this.element+'" class="prototools-table"></table>' });
		this.table = $('data-grid-'+this.element);
		this.createTools();
		this.createRows();
		this.addToolsObserver();
		this.addTableObserver();
		this.makeUnsort();
	},
	
	// updateTable -- updates just the table data, writting out the updated rows to the user and recreating the th cells in the process.
	updateTable : function(){
		this.table = $('data-grid-'+this.element);
		$(this.table.id).update();
		this.createRows();
		this.addTableObserver();
		this.makeUnsort();
	},
	
	// createRow -- writes out the HTML for a row using the data in @obj and applies the correct class styles associated with its @index
	// param obj: holdes the data of the row
	// param index: which index row this obj is in context to the table
	createRow : function(obj,index){
		var line = index % 2;
		var row = '<tr class="data line'+line+'" id="'+this.table.id+'-'+index+'">\n';
		var values = Object.values(obj);
		
		this.tableColumnsName.each(function(s,index){
			row += '\t<td class="'+this.table.id+'-column-'+s+'">'+values[index]+'</td>\n';
		}.bind(this));
		row += '\n</tr>';
		return row;
	},
	
	// createFirstRow -- sets up the th cells of the table
	// param obj: This has not been implemented -- FOR FUTURE USE
	createFirstRow : function(obj){
		var row = '<tr>\n';
		this.tableColumnsName.each(function(i){
			row += '\t<th id="'+this.table.id+'-'+i+'">'+i.replace('_',' ').capitalize()+'</th>';
		}.bind(this));
		row += '\n</tr>';
		this.model = Object.clone(obj);		// NOT SURE WHAT THIS IS DOING.
		return row;
	},
	
	// setColumnsName -- column names come from the labels in the data given to the table. Just grab the names from the first record.
	setColumnsName : function(){
		this.tableColumnsName = Object.keys(this.data[0]);
	},
	
	// creatFilter -- creates the HTML elements for the filter tool.
	createFilter : function(){
		var option = '';
		this.tableColumnsName.each(function(i){
			option += '\t<option value="'+i+'">'+i.replace('_',' ').capitalize()+'</option>\n';
		});
		$(this.table.id+'-options').insert({bottom : this.msgs.filterLabel})
		.insert({bottom : '<select id="'+this.table.id+'-filter-column">'+option+'</select>'})
		.insert({bottom : Element('input',{'id' : this.table.id+'-filter-data'})});
		
		this.tools.filterCol = $F(this.table.id + '-filter-column');
		this.tools.filterData = $F(this.table.id + '-filter-data');
	},
	
	// createPager -- creates the HTML elements for the pagination tool
	createPager : function () {
		$(this.table.id+'-pager').insert({bottom : Element('input',{'id' : this.table.id+'-page-first', 'type' : 'button', 'value' : this.msgs.paginationFirst, 'class' : 'first-page-button'})})
		.insert({bottom : Element('input',{'id' : this.table.id+'-page-prev', 'type' : 'button', 'value' : this.msgs.paginationPrev, 'class' : 'prev-page-button'})})
		.insert({bottom : '<span id="' + this.table.id+'-page-current' + '" class="currentpage">' + this.tools.page + '</span>'})
		.insert({bottom : Element('input',{'id' : this.table.id+'-page-next', 'type' : 'button', 'value' : this.msgs.paginationNext, 'class' : 'next-page-button'})})
		.insert({bottom : Element('input',{'id' : this.table.id+'-page-last', 'type' : 'button', 'value' : this.msgs.paginationLast, 'class' : 'last-page-button'})})
		.insert({bottom : this.msgs.paginationOf + '<span id="' + this.table.id + '-page-total' + '" class="totalpages">' + this.tools.pages + '</span>' + this.msgs.paginationPages});
	},

	// createSearch -- creates the HTML elements for the search tool
	createSearch : function(){
		$(this.table.id+'-search').insert({bottom : this.msgs.searchLabel})
		.insert({bottom : Element('input',{'id' : this.table.id+'-search-data'})});
		
		this.tools.searchData = $F(this.table.id + '-search-data');
	},
	
	// A tool is any interface that acts on the table data and not directly placed in the table that is generated.
	//
	// createTools -- determines if each tool is going to be displayed at all or at the top or bottom of the data table. 
	// this should be ran only once when the table is first created since it can be expensive to create HTML elements. 
	// all other times tools are updated using DOM calls. the order that each tool appears is based on where in the code it is create here.
	createTools : function() {
		var filterDiv, pagerDiv, searchDiv;
		
		if (this.options.filter) {
			filterDiv = new Element('div' , {'id' : this.table.id+'-options' , 'class':'prototools-options'});
			if(this.options.filter == 'top') {
				this.table.insert({ before :  filterDiv});
				filterDiv.setStyle('border-bottom : none;');			
			}
			else {
				this.table.insert({ after :  filterDiv});
				filterDiv.setStyle('border-top : none;');			
			}
			this.createFilter(); 
		}
		
		if(this.options.search)
		{
			searchDiv = new Element('div', {'id' : this.table.id + '-search', 'class':'prototools-search'});
			if(this.options.search == 'top') {
				this.table.insert({ before :  searchDiv});
				searchDiv.setStyle('border-bottom : none;');			
			}
			else {
				this.table.insert({ after :  searchDiv});
				searchDiv.setStyle('border-top : none;');			
			}
			this.createSearch();
		}
		
		if(this.options.paginate)
		{
			pagerDiv = new Element('div', {'id' : this.table.id + '-pager', 'class':'prototools-pager'});
			if(this.options.paginate == 'top') {
				this.table.insert({ before :  pagerDiv});
				pagerDiv.setStyle('border-bottom : none;');			
			}
			else {
				this.table.insert({ after :  pagerDiv});
				pagerDiv.setStyle('border-top : none;');			
			}
			this.createPager();
		}
	},
	
	// createRows -- this is really the heart of the script. createRows takes the data  in this.cache passes it through the filter tool, then passes it through the search tool and 
	// finally paginates the results displaying (creating rows) only the current page. if no records result then a message is displayed to the user. this always uses the cache 
	// and never this.data directly
	createRows : function(){
		var line = 1;
		var display, enddisplay, startdisplay, dataView, dat, col, searchStr,row, s;
		
		// header information
		this.table.insert({ top: this.createFirstRow() });	
		
		// data -> {filter} -> dataView -> {paginate} -> display
		dataView = this.cache;
		
		// if filtering is turned off or not currently being used then skip
		if(this.options.filter && !this.isCached && this.tools.filterData !== '') {
			col = this.tools.filterCol;
			dat = this.tools.filterData.toUpperCase();
			dataView = [];

			dataView = this.cache.inject([], function(array, rec, index) {
				if(rec[col].toString().toUpperCase().include(dat))
				{
					array.push(rec);
				}
				
				return array;
			});
		}
		
		if(this.options.search && !this.isCached && this.tools.searchData !== '') {
			dat = this.tools.searchData.toUpperCase();
			
			dataView = dataView.inject([], function(array, value, index) {
				searchStr = Object.values(value).inject('', function(acc, n) {
					return acc + " " + n;
				});
				
				if(searchStr.toUpperCase().include(dat)) {
					array.push(value);
				}
				
				return array;
			});
		}
		display = dataView;
		
		if(this.options.paginate) {
			this.tools.pages = Math.ceil(dataView.size() / this.options.pageCount);
			if(this.tools.page > this.tools.pages) { this.tools.page = this.tools.pages; }
			if(this.tools.page < 1) { this.tools.page = 1; }
			if(this.tools.pages === 0) { this.tools.page = 0; }
			
			$(this.table.id + '-page-current').update(this.tools.page);	// update current page on tool
			$(this.table.id + '-page-total').update(this.tools.pages);	// update total pages on tool
			
			// Instead of displaying all just display a "paginate window" to the user.
			startdisplay = this.options.pageCount * (this.tools.page - 1);
			enddisplay = this.options.pageCount * this.tools.page;
			display = dataView.slice(startdisplay, enddisplay);
		}
		
		display.each(function(i,index){
			this.table.insert({ bottom: this.createRow(i,index) });
			line = (line == 1) ?  2 : 1;
		}.bind(this));
		
		// if there are no results
		if(display.size() === 0) {
			s = this.tableColumnsName.size();
			row = '<tr class="data line0" id="'+this.table.id+'-0">\n';
			row += '\t<td class="'+this.table.id+'-column" colspan="' + s + '">'+this.msgs.emptyResults+'</td>\n';
			row += '\n</tr>';
			this.table.insert({ bottom: row });
		}
		
		if (this.orderField){ $( this.table.id+'-'+this.orderField).addClassName(this.order); }
		
		// the new dataView is set as the cache
		if(!this.isCached) {
			this.isCached = true;
			this.cache = dataView;
		}
	}
};
function doLogin(loginForm)
{
    var toPostObject={'username':$('username').value,'password':$('password').value};
	this.request = new Ajax.Request('/login', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport)
	{
	    var response=transport.responseText.evalJSON();
	    if(response.login=='ok')
	    {
		window.location=window.location.href;
	    }
	    else
	    {
		alert(response.problem);
	    }
	}.bind(this) } );
    return false;
}

function encodeId(decodedId,callBack)
{
    var toPostObject={'act':'encodeId','decodedId':decodedId};
	this.request = new Ajax.Request('/utils', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport)
	{
	    var encodedId=transport.responseText;
	    callBack(encodedId);
	}.bind(this) } );
}

function decodeId(encodedId,callBack)
{
    var toPostObject={'act':'decodeId','encodedId':encodedId};
	this.request = new Ajax.Request('/utils', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport)
	{
	    var decodedId=transport.responseText;
	    callBack(decodedId);
	}.bind(this) } );
}

var searchValue=null;
document.observe('dom:loaded', function()
{
    if($('staffPhotoFilter'))
    {
	$('staffPhotoFilter').observe('keyup', function(event) { $('staffPhotoFilter').fire('staff:Search'); } );
	
	$('staffPhotoFilter').observe('staff:Search', function(event) {
	    searchValue=event.element().value;
	    $$('ul li.staffPhoto').each(function (s)
	    {
		var fullName=s.down('span').innerHTML;
		var extension=s.down('img').title;
		if(fullName.toLowerCase().include(searchValue.toLowerCase()) || extension.startsWith(searchValue))
		    s.show();
		else
		    s.hide();
	    });
	})
	
	if($('staffPhotoFilter').value!='') $('staffPhotoFilter').fire('staff:Search');
    }
    
    if($('publicationsListFilter'))
    {
	$('publicationsListFilter').observe('keyup', function(event) { $('publicationsListFilter').fire('publications:Search'); } );
	
	$('publicationsListFilter').observe('publications:Search', function(event) {
	    searchValue=event.element().value;
	    $$('ul li.publicationLarge').each(function (s)
	    {
		var publicationName=s.down('span').innerHTML;
		if(publicationName.toLowerCase().include(searchValue.toLowerCase()))
		    s.show();
		else
		    s.hide();
	    });
	})
	
	if($('publicationsListFilter').value!='') $('staffPhotoFilter').fire('publications:Search');
    }
});

function removeStaff(staffId)
{
    if(!confirm('Do you really want to remove this staff member?')) return false;
    toPostObject={'act':'deleteStaff','staffId':staffId};
    new Ajax.Request('/staff/teams', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport) {
	window.location=window.location.href;
	}
    });
}

function removeContact(contactId,leadId)
{
    if(!confirm('Do you really want to remove this contact?')) return false;
    toPostObject={'act':'deleteContact','contactId':contactId};
    new Ajax.Request('/leads/actions', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport) {
	window.location='../../view/'+leadId;
	}
    });
}

function loginAs(staffId)
{
    toPostObject={'act':'loginAs'};
    new Ajax.Request('/team/user/'+staffId, {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport) {
	window.location='/';
    } });
}

function logoutAs()
{
    toPostObject={'act':'logoutAs'};
    new Ajax.Request('/team/user/123456789', {postBody:$H(toPostObject).toQueryString(), onSuccess: function(transport) {
	window.location='/';
    } });
    return false;
}
/*
 * Orginal: http://adomas.org/javascript-mouse-wheel/
 * prototype extension by "Frank Monnerjahn" <themonnie@gmail.com>
 */
Object.extend(Event, {
    wheel:function (event){
	var delta = 0;
	if (!event) event = window.event;
	if (event.wheelDelta) {
	    delta = event.wheelDelta/120; 
	    if (window.opera) delta = -delta;
	} else if (event.detail) { delta = -event.detail/3;	}
	return Math.round(delta); //Safari Round
    }
});

/*
Examples:

JS:


var counterDIV=0;
function handleDIV(e) {
    counterDIV +=	Event.wheel(e);
    $('divdelta').innerHTML = counterDIV +'#'+ Event.wheel(e) + ": " + (Event.wheel(e) < 0 ? 'down' : 'up' );
}


HTML:


<div id="divdelta" style="width:200px;background-color:red;padding:30px;">i'm a DIV scroll on me too.</div> 

JS:
Event.observe($('divdelta'), "mousewheel", handleDIV, false);
Event.observe($('divdelta'), "DOMMouseScroll", handleDIV, false); // Firefox
*/

function resizeLeadColumns(targetheight)
{
    new Effect.Tween($('recent').down('div'), $('recent').down('div').getHeight(), (targetheight), {duration: 0.1}, function(h){ this.style.height = h + 'px'; });
    new Effect.Tween($('planner').down('div'), $('planner').down('div').getHeight(), (targetheight), {duration: 0.1}, function(h){ this.style.height = h + 'px'; });
    new Effect.Tween($('callbacks').down('div'), $('callbacks').down('div').getHeight(), (targetheight), {duration: 0.1}, function(h){ this.style.height = h + 'px'; });
    new Effect.Tween($('suggested').down('div'), $('suggested').down('div').getHeight(), (targetheight), {duration: 0.1}, function(h){ this.style.height = h + 'px'; });
    new Effect.Tween($('available').down('div'), $('available').down('div').getHeight(), (targetheight), {duration: 0.1}, function(h){ this.style.height = h + 'px'; });
}

function resizeLeadTable()
{
    if(!$('mainContent')) return;
    var lt = $('mainContent');
    var targetheight = lt.getHeight() + document.viewport.getDimensions().height - $('symfony-wrapper').getHeight() - 15;
    new Effect.Tween('mainContent', lt.getHeight(), targetheight, {duration: 0.2, afterFinish: function() {
        resizeLeadColumns(targetheight-90);
        }}, function(h){ this.style.height = h + 'px'; });
}

Event.observe(window, "resize", function() {
    resizeLeadTable();
});

function isDefined(variable)
{
        return (typeof(window[variable]) == "undefined") ? false : true;
}

function initiAll()
{
    kfElements.init({'autoCompletePath': '/autocomplete'});
}


Element.on(document, 'dom:loaded', function(){
    resizeLeadTable();
    initiAll();
});



