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

var Prototype = {
  Version: '1.6.0.3',

  Browser: {
    IE:     !!(window.attachEvent &&
      navigator.userAgent.indexOf('Opera') === -1),
    Opera:  navigator.userAgent.indexOf('Opera') > -1,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
      navigator.userAgent.indexOf('KHTML') === -1,
    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
  },

  BrowserFeatures: {
    XPath: !!document.evaluate,
    SelectorsAPI: !!document.querySelector,
    ElementExtensions: !!window.HTMLElement,
    SpecificElementExtensions:
      document.createElement('div')['__proto__'] &&
      document.createElement('div')['__proto__'] !==
        document.createElement('form')['__proto__']
  },

  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 = {
  create: function() {
    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) {
      var subclass = function() { };
      subclass.prototype = parent.prototype;
      klass.prototype = new subclass;
      parent.subclasses.push(klass);
    }

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

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

    klass.prototype.constructor = klass;

    return klass;
  }
};

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

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

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

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

    return this;
  }
};

var Abstract = { };

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

Object.extend(Object, {
  inspect: function(object) {
    try {
      if (Object.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;
    }
  },

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

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

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

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

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

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

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

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

  clone: function(object) {
    return Object.extend({ }, object);
  },

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

  isArray: function(object) {
    return object != null && typeof object == "object" &&
      'splice' in object && 'join' in object;
  },

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

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

  isString: function(object) {
    return typeof object == "string";
  },

  isNumber: function(object) {
    return typeof object == "number";
  },

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

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

  bind: function() {
    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
    var __method = this, args = $A(arguments), object = args.shift();
    return function() {
      return __method.apply(object, args.concat($A(arguments)));
    }
  },

  bindAsEventListener: function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function(event) {
      return __method.apply(object, [event || window.event].concat(args));
    }
  },

  curry: function() {
    if (!arguments.length) return this;
    var __method = this, args = $A(arguments);
    return function() {
      return __method.apply(this, args.concat($A(arguments)));
    }
  },

  delay: function() {
    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
    return window.setTimeout(function() {
      return __method.apply(__method, args);
    }, timeout);
  },

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

  wrap: function(wrapper) {
    var __method = this;
    return function() {
      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
    }
  },

  methodize: function() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      return __method.apply(null, [this].concat($A(arguments)));
    };
  }
});

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

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

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();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
});
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, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(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;
  },

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

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

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

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

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

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

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

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

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

  escapeHTML: function() {
    var self = arguments.callee;
    self.text.data = this;
    return self.div.innerHTML;
  },

  unescapeHTML: function() {
    var div = new Element('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  },

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

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

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

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

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

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

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

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

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

    return camelized;
  },

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

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

  dasherize: function() {
    return this.gsub(/_/,'-');
  },

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

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

  unfilterJSON: function(filter) {
    return this.sub(filter || Prototype.JSONFilter, '#{1}');
  },

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

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

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

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

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

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

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

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

if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
  escapeHTML: function() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  },
  unescapeHTML: function() {
    return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
  }
});

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

String.prototype.parseQuery = String.prototype.toQueryParams;

Object.extend(String.prototype.escapeHTML, {
  div:  document.createElement('div'),
  text: document.createTextNode('')
});

String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);

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

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

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

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

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

      while (match != null) {
        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : 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 = {
  each: function(iterator, context) {
    var index = 0;
    try {
      this._each(function(value) {
        iterator.call(context, value, index++);
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

  eachSlice: function(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);
  },

  all: function(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;
  },

  any: function(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;
  },

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

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

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

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

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

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

  include: function(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;
  },

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

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

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

  max: function(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;
  },

  min: function(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;
  },

  partition: function(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];
  },

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

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

  sortBy: function(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');
  },

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

  zip: function() {
    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));
    });
  },

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

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

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  filter:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray,
  every:   Enumerable.all,
  some:    Enumerable.any
});
function $A(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

if (Prototype.Browser.WebKit) {
  $A = function(iterable) {
    if (!iterable) return [];
    // In Safari, only use the `toArray` method if it's not a NodeList.
    // A NodeList is a function, has an function `item` property, and a numeric
    // `length` property. Adapted from Google Doctype.
    if (!(typeof iterable === 'function' && typeof iterable.length ===
        'number' && typeof iterable.item === 'function') && iterable.toArray)
      return iterable.toArray();
    var length = iterable.length || 0, results = new Array(length);
    while (length--) results[length] = iterable[length];
    return results;
  };
}

Array.from = $A;

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  },

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

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

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

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

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

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

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

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

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

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

  clone: function() {
    return [].concat(this);
  },

  size: function() {
    return this.length;
  },

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

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

// use native browser JS 1.6 implementation if available
if (Object.isFunction(Array.prototype.forEach))
  Array.prototype._each = Array.prototype.forEach;

if (!Array.prototype.indexOf) Array.prototype.indexOf = function(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;
};

if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(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;
};

Array.prototype.toArray = Array.prototype.clone;

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

if (Prototype.Browser.Opera){
  Array.prototype.concat = function() {
    var array = [];
    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for (var i = 0, length = arguments.length; i < length; i++) {
      if (Object.isArray(arguments[i])) {
        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  };
}
Object.extend(Number.prototype, {
  toColorPart: function() {
    return this.toPaddedString(2, 16);
  },

  succ: function() {
    return this + 1;
  },

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

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

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

$w('abs round ceil floor').each(function(method){
  Number.prototype[method] = Math[method].methodize();
});
function $H(object) {
  return new Hash(object);
};

var Hash = Class.create(Enumerable, (function() {

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

  return {
    initialize: function(object) {
      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
    },

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

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

    get: function(key) {
      // simulating poorly supported hasOwnProperty
      if (this._object[key] !== Object.prototype[key])
        return this._object[key];
    },

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

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

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

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

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

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

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

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

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

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

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

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

Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
Hash.from = $H;
var ObjectRange = Class.create(Enumerable, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

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

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

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

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

  activeRequestCount: 0
};

Ajax.Responders = {
  responders: [],

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

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

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

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

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate:   function() { Ajax.activeRequestCount++ },
  onComplete: function() { Ajax.activeRequestCount-- }
});

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

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

    if (Object.isString(this.options.parameters))
      this.options.parameters = this.options.parameters.toQueryParams();
    else if (Object.isHash(this.options.parameters))
      this.options.parameters = this.options.parameters.toObject();
  }
});

Ajax.Request = Class.create(Ajax.Base, {
  _complete: false,

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

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

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

    this.parameters = params;

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

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

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

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

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

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

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

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

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

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

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

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

    // user-defined headers
    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

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

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

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

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

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

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

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

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

    if (state == 'Complete') {
      // avoid memory leak in MSIE: clean up
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

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

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

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

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

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

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

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

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

  status:      0,
  statusText: '',

  getStatus: Ajax.Request.prototype.getStatus,

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

  getHeader: Ajax.Request.prototype.getHeader,

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

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

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

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

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

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

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

    $super(url, options);
  },

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

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

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

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

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

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

    this.start();
  },

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

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

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

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

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element))
    element = document.getElementById(element);
  return Element.extend(element);
}

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

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

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

if (!Node.ELEMENT_NODE) {
  // DOM level 2 ECMAScript Language Binding
  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() {
  var element = this.Element;
  this.Element = function(tagName, attributes) {
    attributes = attributes || { };
    tagName = tagName.toLowerCase();
    var cache = Element.cache;
    if (Prototype.Browser.IE && attributes.name) {
      tagName = '<' + tagName + ' name="' + attributes.name + '">';
      delete attributes.name;
      return Element.writeAttribute(document.createElement(tagName), attributes);
    }
    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
  };
  Object.extend(this.Element, element || { });
  if (element) this.Element.prototype = element.prototype;
}).call(window);

Element.cache = { };

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(element, content) {
    element = $(element);
    if (content && content.toElement) content = content.toElement();
    if (Object.isElement(content)) return element.update().insert(content);
    content = Object.toHTML(content);
    element.innerHTML = content.stripScripts();
    content.evalScripts.bind(content).defer();
    return element;
  },

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

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

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

    var content, insert, tagName, childNodes;

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

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

      content = Object.toHTML(content);

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

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

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

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

    return element;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  select: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  adjacent: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element.parentNode, args).without(element);
  },

  identify: function(element) {
    element = $(element);
    var id = element.readAttribute('id'), self = arguments.callee;
    if (id) return id;
    do { id = 'anonymous_element_' + self.counter++ } while ($(id));
    element.writeAttribute('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().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().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(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(className) ?
      'removeClassName' : 'addClassName'](className);
  },

  // removes whitespace-only text node children
  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();
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

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

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

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

    return element;
  },

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

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

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (Prototype.Browser.Opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

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

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

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

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

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

  absolutize: function(element) {
    element = $(element);
    if (element.getStyle('position') == 'absolute') return element;
    // Position.prepare(); // To be done manually by Scripty when it needs it.

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

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

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

  relativize: function(element) {
    element = $(element);
    if (element.getStyle('position') == 'relative') return element;
    // Position.prepare(); // To be done manually by Scripty when it needs it.

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

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

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

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

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

    return $(document.body);
  },

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

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

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

    } while (element = element.offsetParent);

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

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

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

    // find page position of source
    source = $(source);
    var p = source.viewportOffset();

    // find coordinate system to use
    element = $(element);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(element, 'position') == 'absolute') {
      parent = element.getOffsetParent();
      delta = parent.viewportOffset();
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    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;
  }
};

Element.Methods.identify.counter = 1;

Object.extend(Element.Methods, {
  getElementsBySelector: Element.Methods.select,
  childElements: Element.Methods.immediateDescendants
});

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

if (Prototype.Browser.Opera) {
  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
    function(proceed, element, style) {
      switch (style) {
        case 'left': case 'top': case 'right': case 'bottom':
          if (proceed(element, 'position') === 'static') return null;
        case 'height': case 'width':
          // returns '0px' for hidden elements; we want it to return null
          if (!Element.visible(element)) return null;

          // returns the border-box dimensions rather than the content-box
          // dimensions, so we subtract padding and borders from the value
          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) {
  // IE doesn't report offsets correctly for static elements, so we change them
  // to "relative" to get the values, then change them back.
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    function(proceed, element) {
      element = $(element);
      // IE throws an error if element is not in document
      try { element.offsetParent }
      catch(e) { return $(document.body) }
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);
      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    }
  );

  $w('positionedOffset viewportOffset').each(function(method) {
    Element.Methods[method] = Element.Methods[method].wrap(
      function(proceed, element) {
        element = $(element);
        try { element.offsetParent }
        catch(e) { return Element._returnOffset(0,0) }
        var position = element.getStyle('position');
        if (position !== 'static') return proceed(element);
        // Trigger hasLayout on the offset parent so that IE6 reports
        // accurate offsetTop and offsetLeft values for position: fixed.
        var offsetParent = element.getOffsetParent();
        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
          offsetParent.setStyle({ zoom: 1 });
        element.setStyle({ position: 'relative' });
        var value = proceed(element);
        element.setStyle({ position: position });
        return value;
      }
    );
  });

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

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

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

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

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

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

  Element._attributeTranslations = {
    read: {
      names: {
        'class': 'className',
        'for':   'htmlFor'
      },
      values: {
        _getAttr: function(element, attribute) {
          return element.getAttribute(attribute, 2);
        },
        _getAttrNode: function(element, attribute) {
          var node = element.getAttributeNode(attribute);
          return node ? node.value : "";
        },
        _getEv: function(element, attribute) {
          attribute = element.getAttribute(attribute);
          return attribute ? attribute.toString().slice(23, -2) : null;
        },
        _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._getAttr,
      src:         v._getAttr,
      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);
}

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

  // Safari returns margins on body which is incorrect if the child is absolutely
  // positioned.  For performance reasons, redefine Element#cumulativeOffset for
  // KHTML/WebKit only.
  Element.Methods.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

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

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

if (Prototype.Browser.IE || Prototype.Browser.Opera) {
  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
  Element.Methods.update = function(element, content) {
    element = $(element);

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

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

    if (tagName in Element._insertionTranslations.tags) {
      $A(element.childNodes).each(function(node) { element.removeChild(node) });
      Element._getContentFromAnonymousElement(tagName, content.stripScripts())
        .each(function(node) { element.appendChild(node) });
    }
    else element.innerHTML = content.stripScripts();

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

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

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

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

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

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

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

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

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

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

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

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

Element.extend = (function() {
  if (Prototype.BrowserFeatures.SpecificElementExtensions)
    return Prototype.K;

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

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

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

    // extend methods for specific tags
    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

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

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

  }, {
    refresh: function() {
      // extend methods for all tags (Safari doesn't need this)
      if (!Prototype.BrowserFeatures.ElementExtensions) {
        Object.extend(Methods, Element.Methods);
        Object.extend(Methods, Element.Methods.Simulated);
      }
    }
  });

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

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

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

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

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

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

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

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

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

    window[klass] = { };
    window[klass].prototype = document.createElement(tagName)['__proto__'];
    return window[klass];
  }

  if (F.ElementExtensions) {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, 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() {
    var dimensions = { }, B = Prototype.Browser;
    $w('width height').each(function(d) {
      var D = d.capitalize();
      if (B.WebKit && !document.evaluate) {
        // Safari <3.0 needs self.innerWidth/Height
        dimensions[d] = self['inner' + D];
      } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
        // Opera <9.5 needs document.body.clientWidth/Height
        dimensions[d] = document.body['client' + D]
      } else {
        dimensions[d] = document.documentElement['client' + D];
      }
    });
    return dimensions;
  },

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

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

  getScrollOffsets: function() {
    return Element._returnOffset(
      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
  }
};
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license.  Please see http://www.yui-ext.com/ for more information. */

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

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

  },

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

    var e = this.expression;

    // Safari 3 chokes on :*-of-type and :empty
    if (Prototype.Browser.WebKit &&
     (e.include("-of-type") || e.include(":empty")))
      return false;

    // XPath can't do namespaced attributes, nor can it read
    // the "checked" property from DOM nodes
    if ((/(\[[\w-]*?:|:checked)/).test(e))
      return false;

    return true;
  },

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

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

    // Make sure the browser treats the selector as valid. Test on an
    // isolated element to minimize cost of this check.
    try {
      Selector._div.querySelector(this.expression);
    } catch(e) {
      return false;
    }

    return true;
  },

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

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

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

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

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

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

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

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

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

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

    switch (this.mode) {
      case 'selectorsAPI':
        // querySelectorAll queries document-wide, then filters to descendants
        // of the context element. That's not what we want.
        // Add an explicit context to the selector if necessary.
        if (root !== document) {
          var oldId = root.id, id = $(root).identify();
          e = "#" + id + " " + e;
        }

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

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

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

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

    while (e && le !== e && (/\S/).test(e)) {
      le = e;
      for (var i in ps) {
        p = ps[i];
        if (m = e.match(p)) {
          // use the Selector.assertions methods unless the selector
          // is too complex.
          if (as[i]) {
            this.tokens.push([i, Object.clone(m)]);
            e = e.replace(m[0], '');
          } else {
            // reluctantly do a document-wide search
            // and look for a match in the array
            return this.findElements(document).include(element);
          }
        }
      }
    }

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

    return match;
  },

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

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

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

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

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

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

  patterns: {
    // combinators must be listed first
    // (and descendant needs to be last combinator)
    laterSibling: /^\s*~\s*/,
    child:        /^\s*>\s*/,
    adjacent:     /^\s*\+\s*/,
    descendant:   /^\s/,

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

  // for Selector.match and Element#match
  assertions: {
    tagName: function(element, matches) {
      return matches[1].toUpperCase() == element.tagName.toUpperCase();
    },

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

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

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

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

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

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

    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._countedByPrototype = undefined;
      return nodes;
    },

    // mark each child node with its position (for nth calls)
    // "ofType" flag indicates whether we're indexing for nth-of-type
    // rather than nth-child
    index: function(parentNode, reverse, ofType) {
      parentNode._countedByPrototype = Prototype.emptyFunction;
      if (reverse) {
        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
          var node = nodes[i];
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
      }
    },

    // filters out duplicates and extends all nodes
    unique: function(nodes) {
      if (nodes.length == 0) return nodes;
      var results = [], n;
      for (var i = 0, l = nodes.length; i < l; i++)
        if (!(n = nodes[i])._countedByPrototype) {
          n._countedByPrototype = Prototype.emptyFunction;
          results.push(Element.extend(n));
        }
      return Selector.handlers.unmark(results);
    },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

if (Prototype.Browser.IE) {
  Object.extend(Selector.handlers, {
    // IE returns comment nodes on getElementsByTagName("*").
    // Filter them out.
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        if (node.tagName !== "!") a.push(node);
      return a;
    },

    // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node.removeAttribute('_countedByPrototype');
      return nodes;
    }
  });
}

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}
var Form = {
  reset: function(form) {
    $(form).reset();
    return form;
  },

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

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

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

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

  getElements: function(form) {
    return $A($(form).getElementsByTagName('*')).inject([],
      function(elements, child) {
        if (Form.Element.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'].include(element.tagName.toLowerCase());
    });
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
          !['button', 'reset', 'submit'].include(element.type)))
        element.select();
    } catch (e) { }
    return element;
  },

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

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

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

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

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

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

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

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

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

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

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

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

  optionValue: function(opt) {
    // extend element because hasAttribute may not be native
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
};

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

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

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

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

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

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

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

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

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

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

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

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

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

Object.extend(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: { },

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

Event.Methods = (function() {
  var isButton;

  if (Prototype.Browser.IE) {
    var buttonMap = { 0: 1, 1: 4, 2: 2 };
    isButton = function(event, code) {
      return event.button == buttonMap[code];
    };

  } else if (Prototype.Browser.WebKit) {
    isButton = function(event, code) {
      switch (code) {
        case 0: return event.which == 1 && !event.metaKey;
        case 1: return event.which == 1 && event.metaKey;
        default: return false;
      }
    };

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

  return {
    isLeftClick:   function(event) { return isButton(event, 0) },
    isMiddleClick: function(event) { return isButton(event, 1) },
    isRightClick:  function(event) { return isButton(event, 2) },

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

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

      if (currentTarget && currentTarget.tagName) {
        // Firefox screws up the "click" event when moving between radio buttons
        // via arrow keys. It also screws up the "load" and "error" events on images,
        // reporting the document as the target instead of the original image.
        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);
    },

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

    pointer: function(event) {
      var docElement = document.documentElement,
      body = document.body || { scrollLeft: 0, scrollTop: 0 };
      return {
        x: event.pageX || (event.clientX +
          (docElement.scrollLeft || body.scrollLeft) -
          (docElement.clientLeft || 0)),
        y: event.pageY || (event.clientY +
          (docElement.scrollTop || body.scrollTop) -
          (docElement.clientTop || 0))
      };
    },

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

    stop: function(event) {
      Event.extend(event);
      event.preventDefault();
      event.stopPropagation();
      event.stopped = true;
    }
  };
})();

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

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

    return function(event) {
      if (!event) return false;
      if (event._extendedByPrototype) return event;

      event._extendedByPrototype = Prototype.emptyFunction;
      var pointer = Event.pointer(event);
      Object.extend(event, {
        target: event.srcElement,
        relatedTarget: Event.relatedTarget(event),
        pageX:  pointer.x,
        pageY:  pointer.y
      });
      return Object.extend(event, methods);
    };

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

Object.extend(Event, (function() {
  var cache = Event.cache;

  function getEventID(element) {
    if (element._prototypeEventID) return element._prototypeEventID[0];
    arguments.callee.id = arguments.callee.id || 1;
    return element._prototypeEventID = [++arguments.callee.id];
  }

  function getDOMEventName(eventName) {
    if (eventName && eventName.include(':')) return "dataavailable";
    return eventName;
  }

  function getCacheForID(id) {
    return cache[id] = cache[id] || { };
  }

  function getWrappersForEventName(id, eventName) {
    var c = getCacheForID(id);
    return c[eventName] = c[eventName] || [];
  }

  function createWrapper(element, eventName, handler) {
    var id = getEventID(element);
    var c = getWrappersForEventName(id, eventName);
    if (c.pluck("handler").include(handler)) return false;

    var wrapper = function(event) {
      if (!Event || !Event.extend ||
        (event.eventName && event.eventName != eventName))
          return false;

      Event.extend(event);
      handler.call(element, event);
    };

    wrapper.handler = handler;
    c.push(wrapper);
    return wrapper;
  }

  function findWrapper(id, eventName, handler) {
    var c = getWrappersForEventName(id, eventName);
    return c.find(function(wrapper) { return wrapper.handler == handler });
  }

  function destroyWrapper(id, eventName, handler) {
    var c = getCacheForID(id);
    if (!c[eventName]) return false;
    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
  }

  function destroyCache() {
    for (var id in cache)
      for (var eventName in cache[id])
        cache[id][eventName] = null;
  }


  // Internet Explorer needs to remove event handlers on page unload
  // in order to avoid memory leaks.
  if (window.attachEvent) {
    window.attachEvent("onunload", destroyCache);
  }

  // Safari has a dummy event handler on page unload so that it won't
  // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
  // object when page is returned to via the back button using its bfcache.
  if (Prototype.Browser.WebKit) {
    window.addEventListener('unload', Prototype.emptyFunction, false);
  }

  return {
    observe: function(element, eventName, handler) {
      element = $(element);
      var name = getDOMEventName(eventName);

      var wrapper = createWrapper(element, eventName, handler);
      if (!wrapper) return element;

      if (element.addEventListener) {
        element.addEventListener(name, wrapper, false);
      } else {
        element.attachEvent("on" + name, wrapper);
      }

      return element;
    },

    stopObserving: function(element, eventName, handler) {
      element = $(element);
      var id = getEventID(element), name = getDOMEventName(eventName);

      if (!handler && eventName) {
        getWrappersForEventName(id, eventName).each(function(wrapper) {
          element.stopObserving(eventName, wrapper.handler);
        });
        return element;

      } else if (!eventName) {
        Object.keys(getCacheForID(id)).each(function(eventName) {
          element.stopObserving(eventName);
        });
        return element;
      }

      var wrapper = findWrapper(id, eventName, handler);
      if (!wrapper) return element;

      if (element.removeEventListener) {
        element.removeEventListener(name, wrapper, false);
      } else {
        element.detachEvent("on" + name, wrapper);
      }

      destroyWrapper(id, eventName, handler);

      return element;
    },

    fire: function(element, eventName, memo) {
      element = $(element);
      if (element == document && document.createEvent && !element.dispatchEvent)
        element = document.documentElement;

      var event;
      if (document.createEvent) {
        event = document.createEvent("HTMLEvents");
        event.initEvent("dataavailable", true, true);
      } else {
        event = document.createEventObject();
        event.eventType = "ondataavailable";
      }

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

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

      return Event.extend(event);
    }
  };
})());

Object.extend(Event, Event.Methods);

Element.addMethods({
  fire:          Event.fire,
  observe:       Event.observe,
  stopObserving: Event.stopObserving
});

Object.extend(document, {
  fire:          Element.Methods.fire.methodize(),
  observe:       Element.Methods.observe.methodize(),
  stopObserving: Element.Methods.stopObserving.methodize(),
  loaded:        false
});

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

  var timer;

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

  if (document.addEventListener) {
    if (Prototype.Browser.WebKit) {
      timer = window.setInterval(function() {
        if (/loaded|complete/.test(document.readyState))
          fireContentLoadedEvent();
      }, 0);

      Event.observe(window, "load", fireContentLoadedEvent);

    } else {
      document.addEventListener("DOMContentLoaded",
        fireContentLoadedEvent, false);
    }

  } else {
    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
    $("__onDOMContentLoaded").onreadystatechange = function() {
      if (this.readyState == "complete") {
        this.onreadystatechange = null;
        fireContentLoadedEvent();
      }
    };
  }
})();
/*------------------------------- 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');

// This should be moved to script.aculo.us; notice the deprecated methods
// further below, that map to the newer Element methods.
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  // caches x/y coordinate pair to use with overlap
  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);
  },

  // within must be called directly before
  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;
  },

  // Deprecation layer -- use newer Element methods now (1.5.2).

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

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

Element.addMethods();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return styleRules;
};

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

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

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

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

Element.addMethods(Effect.Methods);

/*!
 * jQuery JavaScript Library v1.4.2
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Sat Feb 13 22:33:48 2010 -0500
 */
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.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\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

/*
 * jQuery UI 1.7.2
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/*
 * jQuery UI Slider 1.7.2
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	ui.core.js
 */
(function(a){a.widget("ui.slider",a.extend({},a.ui.mouse,{_init:function(){var b=this,c=this.options;this._keySliding=false;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");this.range=a([]);if(c.range){if(c.range===true){this.range=a("<div></div>");if(!c.values){c.values=[this._valueMin(),this._valueMin()]}if(c.values.length&&c.values.length!=2){c.values=[c.values[0],c.values[0]]}}else{this.range=a("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(c.range=="min"||c.range=="max"){this.range.addClass("ui-slider-range-"+c.range)}this.range.addClass("ui-widget-header")}if(a(".ui-slider-handle",this.element).length==0){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length<c.values.length){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}}this.handles=a(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(d){d.preventDefault()}).hover(function(){if(!c.disabled){a(this).addClass("ui-state-hover")}},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(!c.disabled){a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}else{a(this).blur()}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(d){a(this).data("index.ui-slider-handle",d)});this.handles.keydown(function(i){var f=true;var e=a(this).data("index.ui-slider-handle");if(b.options.disabled){return}switch(i.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!b._keySliding){b._keySliding=true;a(this).addClass("ui-state-active");b._start(i,e)}break}var g,d,h=b._step();if(b.options.values&&b.options.values.length){g=d=b.values(e)}else{g=d=b.value()}switch(i.keyCode){case a.ui.keyCode.HOME:d=b._valueMin();break;case a.ui.keyCode.END:d=b._valueMax();break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g==b._valueMax()){return}d=g+h;break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g==b._valueMin()){return}d=g-h;break}b._slide(i,e,d);return f}).keyup(function(e){var d=a(this).data("index.ui-slider-handle");if(b._keySliding){b._stop(e,d);b._change(e,d);b._keySliding=false;a(this).removeClass("ui-state-active")}});this._refreshValue()},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy()},_mouseCapture:function(d){var e=this.options;if(e.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();var h={x:d.pageX,y:d.pageY};var j=this._normValueFromMouse(h);var c=this._valueMax()-this._valueMin()+1,f;var k=this,i;this.handles.each(function(l){var m=Math.abs(j-k.values(l));if(c>m){c=m;f=a(this);i=l}});if(e.range==true&&this.values(1)==e.min){f=a(this.handles[++i])}this._start(d,i);k._handleIndex=i;f.addClass("ui-state-active").focus();var g=f.offset();var b=!a(d.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=b?{left:0,top:0}:{left:d.pageX-g.left-(f.width()/2),top:d.pageY-g.top-(f.height()/2)-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};j=this._normValueFromMouse(h);this._slide(d,i,j);return true},_mouseStart:function(b){return true},_mouseDrag:function(d){var b={x:d.pageX,y:d.pageY};var c=this._normValueFromMouse(b);this._slide(d,this._handleIndex,c);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._handleIndex=null;this._clickOffset=null;return false},_detectOrientation:function(){this.orientation=this.options.orientation=="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c,h;if("horizontal"==this.orientation){c=this.elementSize.width;h=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;h=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}var f=(h/c);if(f>1){f=1}if(f<0){f=0}if("vertical"==this.orientation){f=1-f}var e=this._valueMax()-this._valueMin(),i=f*e,b=i%this.options.step,g=this._valueMin()+i-b;if(b>(this.options.step/2)){g+=this.options.step}return parseFloat(g.toFixed(5))},_start:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("start",d,b)},_slide:function(f,e,d){var g=this.handles[e];if(this.options.values&&this.options.values.length){var b=this.values(e?0:1);if((this.options.values.length==2&&this.options.range===true)&&((e==0&&d>b)||(e==1&&d<b))){d=b}if(d!=this.values(e)){var c=this.values();c[e]=d;var h=this._trigger("slide",f,{handle:this.handles[e],value:d,values:c});var b=this.values(e?0:1);if(h!==false){this.values(e,d,(f.type=="mousedown"&&this.options.animate),true)}}}else{if(d!=this.value()){var h=this._trigger("slide",f,{handle:this.handles[e],value:d});if(h!==false){this._setData("value",d,(f.type=="mousedown"&&this.options.animate))}}}},_stop:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("stop",d,b)},_change:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("change",d,b)},value:function(b){if(arguments.length){this._setData("value",b);this._change(null,0)}return this._value()},values:function(b,e,c,d){if(arguments.length>1){this.options.values[b]=e;this._refreshValue(c);if(!d){this._change(null,b)}}if(arguments.length){if(this.options.values&&this.options.values.length){return this._values(b)}else{return this.value()}}else{return this._values()}},_setData:function(b,d,c){a.widget.prototype._setData.apply(this,arguments);switch(b){case"disabled":if(d){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled")}else{this.handles.removeAttr("disabled")}case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue(c);break;case"value":this._refreshValue(c);break}},_step:function(){var b=this.options.step;return b},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(c<this._valueMin()){c=this._valueMin()}if(c>this._valueMax()){c=this._valueMax()}return c}else{return this.options.values}},_valueMin:function(){var b=this.options.min;return b},_valueMax:function(){var b=this.options.max;return b},_refreshValue:function(c){var f=this.options.range,d=this.options,l=this;if(this.options.values&&this.options.values.length){var i,h;this.handles.each(function(p,n){var o=(l.values(p)-l._valueMin())/(l._valueMax()-l._valueMin())*100;var m={};m[l.orientation=="horizontal"?"left":"bottom"]=o+"%";a(this).stop(1,1)[c?"animate":"css"](m,d.animate);if(l.options.range===true){if(l.orientation=="horizontal"){(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({left:o+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({width:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}else{(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({bottom:(o)+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({height:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}}lastValPercent=o})}else{var j=this.value(),g=this._valueMin(),k=this._valueMax(),e=k!=g?(j-g)/(k-g)*100:0;var b={};b[l.orientation=="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[c?"animate":"css"](b,d.animate);(f=="min")&&(this.orientation=="horizontal")&&this.range.stop(1,1)[c?"animate":"css"]({width:e+"%"},d.animate);(f=="max")&&(this.orientation=="horizontal")&&this.range[c?"animate":"css"]({width:(100-e)+"%"},{queue:false,duration:d.animate});(f=="min")&&(this.orientation=="vertical")&&this.range.stop(1,1)[c?"animate":"css"]({height:e+"%"},d.animate);(f=="max")&&(this.orientation=="vertical")&&this.range[c?"animate":"css"]({height:(100-e)+"%"},{queue:false,duration:d.animate})}}}));a.extend(a.ui.slider,{getter:"value values",version:"1.7.2",eventPrefix:"slide",defaults:{animate:false,delay:0,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null}})})(jQuery);;

/**
 * jGrowl 1.1.0
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Written by Stan Lemon <stanlemon@mac.com>
 * Last updated: 2008.06.13
 *
 * jGrowl is a jQuery plugin implementing unobtrusive userland notifications.  These 
 * notifications function similarly to the Growl Framework available for
 * Mac OS X (http://growl.info).
 *
 * Changes in 1.1.0
 * - Multiple container and instances.
 * - Standard jQuery.jGrowl() now wraps jQuery.fn.jGrowl() by first establishing a generic jGrowl container.
 * - Instance methods of a jGrowl container can be called by jQuery.fn.jGrowl(methodName)
 * - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container
 * - Added new log callback which is called before anything is done for the notification
 * - Corner's attribute are now applied on an individual notification basis.
 *
 * Changes in 1.0.4
 * - Various CSS fixes so that jGrowl renders correctly in IE6.
 *
 * Changes in 1.0.3
 * - Fixed bug with options persisting across notifications
 * - Fixed theme application bug
 * - Simplified some selectors and manipulations.
 * - Added beforeOpen and beforeClose callbacks
 * - Reorganized some lines of code to be more readable
 * - Removed unnecessary this.defaults context
 * - If corners plugin is present, it's now customizable.
 * - Customizable open animation.
 * - Customizable close animation.
 * - Customizable animation easing.
 * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
 *
 * Changes in 1.0.2
 * - All CSS styling is now external.
 * - Added a theme parameter which specifies a secondary class for styling, such
 *   that notifications can be customized in appearance on a per message basis.
 * - Notification life span is now customizable on a per message basis.
 * - Added the ability to disable the global closer, enabled by default.
 * - Added callbacks for when a notification is opened or closed.
 * - Added callback for the global closer.
 * - Customizable animation speed.
 * - jGrowl now set itself up and tears itself down.
 *
 * Changes in 1.0.1:
 * - Removed dependency on metadata plugin in favor of .data()
 * - Namespaced all events
 *
 * @todo	Group by header.
 */
	
(function(jQuery) {

	/** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/
	jQuery.jGrowl = function( m , o ) {
		// To maintain compatibility with older version that only supported one instance we'll create the base container.
		if ( jQuery('#jGrowl').size() == 0 ) jQuery('<div id="jGrowl"></div>').addClass(jQuery.jGrowl.defaults.position).appendTo('body');
		// Create a notification on the container.
		jQuery('#jGrowl').jGrowl(m,o);
	};


	/** Raise jGrowl Notification on a jGrowl Container **/
	jQuery.fn.jGrowl = function( m , o ) {
		if ( jQuery.isFunction(this.each) ) {
			var args = arguments;

			return this.each(function() {
				var self = this;

				/** Create a jGrowl Instance on the Container if it does not exist **/
				if ( jQuery(this).data('jGrowl.instance') == undefined ) {
					jQuery(this).data('jGrowl.instance', new jQuery.fn.jGrowl());
					jQuery(this).data('jGrowl.instance').startup( this );
				}

				/** Optionally call jGrowl instance methods, or just raise a normal notification **/
				if ( jQuery.isFunction(jQuery(this).data('jGrowl.instance')[m]) ) {
					jQuery(this).data('jGrowl.instance')[m].apply( jQuery(this).data('jGrowl.instance') , jQuery.makeArray(args).slice(1) );
				} else {
					jQuery(this).data('jGrowl.instance').notification( m , o );
				}
			});
		};
	};

	jQuery.extend( jQuery.fn.jGrowl.prototype , {

		/** Default JGrowl Settings **/
		defaults: {
			header: 		'',
			sticky: 		false,
			position: 		'top-right', // Is this still needed?
			glue: 			'after',
			theme: 			'default',
			corners: 		'10px',
			check: 			500,
			life: 			3000,
			speed: 			'normal',
			easing: 		'swing',
			closer: 		true,
			log: 			function(e,m,o) {},
			beforeOpen: 	function(e,m,o) {},
			open: 			function(e,m,o) {},
			beforeClose: 	function(e,m,o) {},
			close: 			function(e,m,o) {},
			animateOpen: 	{
				opacity: 	'show'
			},
			animateClose: 	{
				opacity: 	'hide'
			}
		},
		
		/** jGrowl Container Node **/
		element: 	null,
	
		/** Interval Function **/
		interval:   null,
		
		/** Create a Notification **/
		notification: 	function( message , o ) {
			var self = this;
			var o = jQuery.extend({}, this.defaults, o);

			o.log.apply( this.element , [this.element,message,o] );

			var notification = jQuery('<div class="jGrowl-notification"><div class="close">&times;</div><div class="header">' + o.header + '</div><div class="message">' + message + '</div></div>')
				.data("jGrowl", o).addClass(o.theme).children('div.close').bind("click.jGrowl", function() {
					jQuery(this).unbind('click.jGrowl').parent().trigger('jGrowl.beforeClose').animate(o.animateClose, o.speed, o.easing, function() {
						jQuery(this).trigger('jGrowl.close').remove();
					});
				}).parent();
				
			( o.glue == 'after' ) ? jQuery('div.jGrowl-notification:last', this.element).after(notification) : jQuery('div.jGrowl-notification:first', this.element).before(notification);

			/** Notification Actions **/
			jQuery(notification).bind("mouseover.jGrowl", function() {
				jQuery(this).data("jGrowl").pause = true;
			}).bind("mouseout.jGrowl", function() {
				jQuery(this).data("jGrowl").pause = false;
			}).bind('jGrowl.beforeOpen', function() {
				o.beforeOpen.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.open', function() {
				o.open.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.beforeClose', function() {
				o.beforeClose.apply( self.element , [self.element,message,o] );
			}).bind('jGrowl.close', function() {
				o.close.apply( self.element , [self.element,message,o] );
			}).trigger('jGrowl.beforeOpen').animate(o.animateOpen, o.speed, o.easing, function() {
				jQuery(this).data("jGrowl").created = new Date();
			}).trigger('jGrowl.open');
		
			/** Optional Corners Plugin **/
			if ( jQuery.fn.corner != undefined ) jQuery(notification).corner( o.corners );

			/** Add a Global Closer if more than one notification exists **/
			if ( jQuery('div.jGrowl-notification:parent', this.element).size() > 1 && jQuery('div.jGrowl-closer', this.element).size() == 0 && this.defaults.closer != false ) {
				jQuery('<div class="jGrowl-closer">[ close all ]</div>').addClass(this.defaults.theme).appendTo(this.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing).bind("click.jGrowl", function() {
					jQuery(this).siblings().children('div.close').trigger("click.jGrowl");

					if ( jQuery.isFunction( self.defaults.closer ) ) self.defaults.closer.apply( jQuery(this).parent()[0] , [jQuery(this).parent()[0]] );
				});
			};
		},

		/** Update the jGrowl Container, removing old jGrowl notifications **/
		update:	 function() {
			jQuery(this.element).find('div.jGrowl-notification:parent').each( function() {
				if ( jQuery(this).data("jGrowl") != undefined && jQuery(this).data("jGrowl").created != undefined && (jQuery(this).data("jGrowl").created.getTime() + jQuery(this).data("jGrowl").life)  < (new Date()).getTime() && jQuery(this).data("jGrowl").sticky != true && 
					 (jQuery(this).data("jGrowl").pause == undefined || jQuery(this).data("jGrowl").pause != true) ) {
					jQuery(this).children('div.close').trigger('click.jGrowl');
				}
			});

			if ( jQuery(this.element).find('div.jGrowl-notification:parent').size() < 2 ) {
				jQuery(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
					jQuery(this).remove();
				});
			};
		},

		/** Setup the jGrowl Notification Container **/
		startup:	function(e) {
			this.element = jQuery(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');
			this.interval = setInterval( function() { jQuery(e).data('jGrowl.instance').update(); }, this.defaults.check);
			
			if (jQuery.browser.msie && parseInt(jQuery.browser.version) < 7) jQuery(this.element).addClass('ie6');
		},

		/** Shutdown jGrowl, removing it and clearing the interval **/
		shutdown:   function() {
			jQuery(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();
			clearInterval( this.interval );
		}
	});
	
	/** Reference the Defaults Object for compatibility with older versions of jGrowl **/
	jQuery.jGrowl.defaults = jQuery.fn.jGrowl.prototype.defaults;

})(jQuery);

/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.1.0-pre
* Requires jQuery 1.3+
* Docs: http://docs.jquery.com/Plugins/livequery
*/
 
(function($) {
 
$.extend($.fn, {
  livequery: function(type, fn, fn2) {
    var self = this, q;
 
    // Handle different call patterns
    if ($.isFunction(type))
      fn2 = fn, fn = type, type = undefined;
 
    // See if Live Query already exists
    $.each( $.livequery.queries, function(i, query) {
      if ( self.selector == query.selector && self.context == query.context &&
        type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
          // Found the query, exit the each loop
          return (q = query) && false;
    });
 
    // Create new Live Query if it wasn't found
    q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
 
    // Make sure it is running
    q.stopped = false;
 
    // Run it immediately for the first time
    q.run();
 
    // Contnue the chain
    return this;
  },
 
  expire: function(type, fn, fn2) {
    var self = this;
 
    // Handle different call patterns
    if ($.isFunction(type))
      fn2 = fn, fn = type, type = undefined;
 
    // Find the Live Query based on arguments and stop it
    $.each( $.livequery.queries, function(i, query) {
      if ( self.selector == query.selector && self.context == query.context &&
        (!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
          $.livequery.stop(query.id);
    });
 
    // Continue the chain
    return this;
  }
});
 
$.livequery = function(selector, context, type, fn, fn2) {
  this.selector = selector;
  this.context = context;
  this.type = type;
  this.fn = fn;
  this.fn2 = fn2;
  this.elements = [];
  this.stopped = false;
 
  // The id is the index of the Live Query in $.livequery.queries
  this.id = $.livequery.queries.push(this)-1;
 
  // Mark the functions for matching later on
  fn.$lqguid = fn.$lqguid || $.livequery.guid++;
  if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
 
  // Return the Live Query
  return this;
};
 
$.livequery.prototype = {
  stop: function() {
    var query = this;
 
    if ( this.type )
      // Unbind all bound events
      this.elements.unbind(this.type, this.fn);
    else if (this.fn2)
      // Call the second function for all matched elements
      this.elements.each(function(i, el) {
        query.fn2.apply(el);
      });
 
    // Clear out matched elements
    this.elements = [];
 
    // Stop the Live Query from running until restarted
    this.stopped = true;
  },
 
  run: function() {
    // Short-circuit if stopped
    if ( this.stopped ) return;
    var query = this;
 
    var oEls = this.elements,
      els = $(this.selector, this.context),
      nEls = els.not(oEls);
 
    // Set elements to the latest set of matched elements
    this.elements = els;
 
    if (this.type) {
      // Bind events to newly matched elements
      nEls.bind(this.type, this.fn);
 
      // Unbind events to elements no longer matched
      if (oEls.length > 0)
        $.each(oEls, function(i, el) {
          if ( $.inArray(el, els) < 0 )
            $.event.remove(el, query.type, query.fn);
        });
    }
    else {
      // Call the first function for newly matched elements
      nEls.each(function() {
        query.fn.apply(this);
      });
 
      // Call the second function for elements no longer matched
      if ( this.fn2 && oEls.length > 0 )
        $.each(oEls, function(i, el) {
          if ( $.inArray(el, els) < 0 )
            query.fn2.apply(el);
        });
    }
  }
};
 
$.extend($.livequery, {
  guid: 0,
  queries: [],
  queue: [],
  running: false,
  timeout: null,
 
  checkQueue: function() {
    if ( $.livequery.running && $.livequery.queue.length ) {
      var length = $.livequery.queue.length;
      // Run each Live Query currently in the queue
      while ( length-- )
        $.livequery.queries[ $.livequery.queue.shift() ].run();
    }
  },
 
  pause: function() {
    // Don't run anymore Live Queries until restarted
    $.livequery.running = false;
  },
 
  play: function() {
    // Restart Live Queries
    $.livequery.running = true;
    // Request a run of the Live Queries
    $.livequery.run();
  },
 
  registerPlugin: function() {
    $.each( arguments, function(i,n) {
      // Short-circuit if the method doesn't exist
      if (!$.fn[n]) return;
 
      // Save a reference to the original method
      var old = $.fn[n];
 
      // Create a new method
      $.fn[n] = function() {
        // Call the original method
        var r = old.apply(this, arguments);
 
        // Request a run of the Live Queries
        $.livequery.run();
 
        // Return the original methods result
        return r;
      }
    });
  },
 
  run: function(id) {
    if (id != undefined) {
      // Put the particular Live Query in the queue if it doesn't already exist
      if ( $.inArray(id, $.livequery.queue) < 0 )
        $.livequery.queue.push( id );
    }
    else
      // Put each Live Query in the queue if it doesn't already exist
      $.each( $.livequery.queries, function(id) {
        if ( $.inArray(id, $.livequery.queue) < 0 )
          $.livequery.queue.push( id );
      });
 
    // Clear timeout if it already exists
    if ($.livequery.timeout) clearTimeout($.livequery.timeout);
    // Create a timeout to check the queue and actually run the Live Queries
    $.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
  },
 
  stop: function(id) {
    if (id != undefined)
      // Stop are particular Live Query
      $.livequery.queries[ id ].stop();
    else
      // Stop all Live Queries
      $.each( $.livequery.queries, function(id) {
        $.livequery.queries[ id ].stop();
      });
  }
});
 
// Register core DOM manipulation methods
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove');
 
// Run Live Queries when the Document is ready
$(function() { $.livequery.play(); });
 
})(jQuery);

// bigTarget.js - A jQuery Plugin
// Version 1.0.1
// Written by Leevi Graham - Technical Director - Newism Web Design & Development
// http://newism.com.au
// Notes: Tooltip code from fitted.js - http://www.trovster.com/lab/plugins/fitted/

// create closure
(function($) {
  // plugin definition
  $.fn.bigTarget = function(options) {
    debug(this);
    // build main options before element iteration
    var opts = $.extend({}, $.fn.bigTarget.defaults, options);
    // iterate and reformat each matched element
    return this.each(function() {
      // set the anchor attributes
      var $a = $(this);
      var href = $a.attr('href');
      var title = $a.attr('title');
      // build element specific options
      var o = $.meta ? $.extend({}, opts, $a.data()) : opts;
      // update element styles
      $a.parents(o.clickZone)
        .hover(function() {
          $h = $(this);
          $h.addClass(o.hoverClass);
          if(typeof o.title != 'undefined' && o.title === true && title != '') {
            $h.attr('title',title);
          }
        }, function() {
          
          $h.removeClass(o.hoverClass);
          if(typeof o.title != 'undefined' && o.title === true && title != '') {
            $h.removeAttr('title');
          }
        })
        // click
        .click(function() {
          if(getSelectedText() == "")
          {
            if($a.is('[rel*=external]')){
              window.open(href);
              return false;
            }
            else {
              //$a.click(); $a.trigger('click');
              window.location = href;
            }
          }
        });
    });
  };
  // private function for debugging
  function debug($obj) {
    if (window.console && window.console.log)
    window.console.log('bigTarget selection count: ' + $obj.size());
  };
  // get selected text
  function getSelectedText(){
    if(window.getSelection){
      return window.getSelection().toString();
    }
    else if(document.getSelection){
      return document.getSelection();
    }
    else if(document.selection){
      return document.selection.createRange().text;
    }
  };
  // plugin defaults
  $.fn.bigTarget.defaults = {
    hoverClass  : 'hover',
    clickZone : 'li:eq(0)',
    title   : true
  };
// end of closure
})(jQuery);

/**
 *
 * Copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 */
 
(function($) {
	/**
	 * attaches a character counter to each textarea element in the jQuery object
	 * usage: $("#myTextArea").charCounter(max, settings);
	 */
	
	$.fn.charCounter = function (max, settings) {
		max = max || 100;
		settings = $.extend({
			container: "<span></span>",
			classname: "charcounter",
			format: "<b>%1</b> characters left",
			pulse: true,
			delay: 0
		}, settings);
		var p, timeout;
		
		function count(el, container) {
			el = $(el);
			if (el.val().length > max) {
			    container.css('color', 'red');
          // el.val(el.val().substring(0, max));
			    if (settings.pulse && !p) {
			    	pulse(container, true);
			    };
			}
			else{
			  container.css('color', '#647A1F');
			};
			if (settings.delay > 0) {
				if (timeout) {
					window.clearTimeout(timeout);
				}
				timeout = window.setTimeout(function () {
					container.html(settings.format.replace(/%1/, (max - el.val().length)));
				}, settings.delay);
			} else {
				container.html(settings.format.replace(/%1/, (max - el.val().length)));
			}
		};
		
		function pulse(el, again) {
			if (p) {
				window.clearTimeout(p);
				p = null;
			};
			el.animate({ opacity: 0.1 }, 100, function () {
				$(this).animate({ opacity: 1.0 }, 100);
			});
			if (again) {
				p = window.setTimeout(function () { pulse(el) }, 200);
			};
		};
		
		return this.each(function () {
			var container = (!settings.container.match(/^<.+>$/)) 
				? $(settings.container) 
				: $(settings.container)
					.insertAfter(this)
					.addClass(settings.classname);
			$(this)
				.bind("keydown", function () { count(this, container); })
				.bind("keypress", function () { count(this, container); })
				.bind("keyup", function () { count(this, container); })
				.bind("focus", function () { count(this, container); })
				.bind("mouseover", function () { count(this, container); })
				.bind("mouseout", function () { count(this, container); })
				.bind("paste", function () { 
					var me = this;
					setTimeout(function () { count(me, container); }, 10);
				});
			if (this.addEventListener) {
				this.addEventListener('input', function () { count(this, container); }, false);
			};
			count(this, container);
		});
	};

})(jQuery);

/*
 * Facebox (for jQuery)
 * version: 1.2 (05/05/2008)
 * @requires jQuery v1.2 or later
 *
 * Examples at http://famspam.com/facebox/
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
 *
 * Usage:
 *  
 *  jQuery(document).ready(function() {
 *    jQuery('a[rel*=facebox]').facebox() 
 *  })
 *
 *  <a href="#terms" rel="facebox">Terms</a>
 *    Loads the #terms div in the box
 *
 *  <a href="terms.html" rel="facebox">Terms</a>
 *    Loads the terms.html page in the box
 *
 *  <a href="terms.png" rel="facebox">Terms</a>
 *    Loads the terms.png image in the box
 *
 *
 *  You can also use it programmatically:
 * 
 *    jQuery.facebox('some html')
 *
 *  The above will open a facebox with "some html" as the content.
 *    
 *    jQuery.facebox(function($) { 
 *      $.get('blah.html', function(data) { $.facebox(data) })
 *    })
 *
 *  The above will show a loading screen before the passed function is called,
 *  allowing for a better ajaxy experience.
 *
 *  The facebox function can also display an ajax page or image:
 *  
 *    jQuery.facebox({ ajax: 'remote.html' })
 *    jQuery.facebox({ image: 'dude.jpg' })
 *
 *  Want to close the facebox?  Trigger the 'close.facebox' document event:
 *
 *    jQuery(document).trigger('close.facebox')
 *
 *  Facebox also has a bunch of other hooks:
 *
 *    loading.facebox
 *    beforeReveal.facebox
 *    reveal.facebox (aliased as 'afterReveal.facebox')
 *    init.facebox
 *
 *  Simply bind a function to any of these hooks:
 *
 *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
 *
 */
(function($) {
  $.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax)
    else if (data.image) fillFaceboxFromImage(data.image)
    else if (data.div) fillFaceboxFromHref(data.div)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

  /*
   * Public, $.facebox methods
   */

  $.extend($.facebox, {
    settings: {
      opacity      : 0,
      overlay      : true,
      loadingImage : '/facebox/loading.gif',
      closeImage   : '/facebox/closelabel.gif',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '\
    <div id="facebox" style="display:none;"> \
      <div class="popup"> \
        <table> \
          <tbody> \
            <tr> \
              <td class="tl"/><td class="b"/><td class="tr"/> \
            </tr> \
            <tr> \
              <td class="b"/> \
              <td class="body"> \
                <div class="content"> \
                </div> \
                <div class="footer"> \
                  <a href="#" class="close"> \
                    <img src="/facebox/closelabel.gif" title="close" class="close_image" /> \
                  </a> \
                </div> \
              </td> \
              <td class="b"/> \
            </tr> \
            <tr> \
              <td class="bl"/><td class="b"/><td class="br"/> \
            </tr> \
          </tbody> \
        </table> \
      </div> \
    </div>'
    },

    loading: function() {
      init()
      if ($('#facebox .loading').length == 1) return true
      showOverlay()

      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')

      $('#facebox').css({
        top:	getPageScroll()[1] + (getPageHeight() / 10),
        left:	385.5
      }).show()

      $(document).bind('keydown.facebox', function(e) {
        if (e.keyCode == 27) $.facebox.close()
        return true
      })
      $(document).trigger('loading.facebox')
    },

    reveal: function(data, klass) {
      $(document).trigger('beforeReveal.facebox')
      if (klass) $('#facebox .content').addClass(klass)
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))
      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
    },

    close: function() {
      $(document).trigger('close.facebox')
      return false
    }
  })

  /*
   * Public, $.fn methods
   */

  $.fn.facebox = function(settings) {
    init(settings)

    function clickHandler() {
      $.facebox.loading(true)

      // support for rel="facebox.inline_popup" syntax, to add a class
      // also supports deprecated "facebox[.inline_popup]" syntax
      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
      if (klass) klass = klass[1]

      fillFaceboxFromHref(this.href, klass)
      return false
    }

    return this.click(clickHandler)
  }

  /*
   * Private methods
   */

  // called one time to setup facebox on this page
  function init(settings) {
    if ($.facebox.settings.inited) return true
    else $.facebox.settings.inited = true

    $(document).trigger('init.facebox')
    makeCompatible()

    var imageTypes = $.facebox.settings.imageTypes.join('|')
    $.facebox.settings.imageTypesRegexp = new RegExp('\.' + imageTypes + '$', 'i')

    if (settings) $.extend($.facebox.settings, settings)
    $('body').append($.facebox.settings.faceboxHtml)

    var preload = [ new Image(), new Image() ]
    preload[0].src = $.facebox.settings.closeImage
    preload[1].src = $.facebox.settings.loadingImage

    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click($.facebox.close)
    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
  }
  
  // getPageScroll() by quirksmode.com
  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;	
    }
    return new Array(xScroll,yScroll) 
  }

  // Adapted from getPageSize() by quirksmode.com
  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {	// all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }	
    return windowHeight
  }

  // Backwards compatibility
  function makeCompatible() {
    var $s = $.facebox.settings

    $s.loadingImage = $s.loading_image || $s.loadingImage
    $s.closeImage = $s.close_image || $s.closeImage
    $s.imageTypes = $s.image_types || $s.imageTypes
    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
  }

  // Figures out what you want to display and displays it
  // formats are:
  //     div: #id
  //   image: blah.extension
  //    ajax: anything else
  function fillFaceboxFromHref(href, klass) {
    // div
    if (href.match(/#/)) {
      var url    = window.location.href.split('#')[0]
      var target = href.replace(url,'')
      $.facebox.reveal($(target).clone().show(), klass)

    // image
    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
      fillFaceboxFromImage(href, klass)
    // ajax
    } else {
      fillFaceboxFromAjax(href, klass)
    }
  }

  function fillFaceboxFromImage(href, klass) {
    var image = new Image()
    image.onload = function() {
      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
    }
    image.src = href
  }

  function fillFaceboxFromAjax(href, klass) {
    $.get(href, function(data) { $.facebox.reveal(data, klass) })
  }

  function skipOverlay() {
    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null 
  }

  function showOverlay() {
    if (skipOverlay()) return

    if ($('facebox_overlay').length == 0) 
      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
      .css('opacity', $.facebox.settings.opacity)
      .click(function() { $(document).trigger('close.facebox') })
      .fadeIn(200)
    return false
  }

  function hideOverlay() {
    if (skipOverlay()) return

    $('#facebox_overlay').fadeOut(200, function(){
      $("#facebox_overlay").removeClass("facebox_overlayBG")
      $("#facebox_overlay").addClass("facebox_hide") 
      $("#facebox_overlay").remove()
    })
    
    return false
  }

  /*
   * Bindings
   */

  $(document).bind('close.facebox', function() {
    $(document).unbind('keydown.facebox')
    $('#facebox').fadeOut(function() {
      $('#facebox .content').removeClass().addClass('content')
      hideOverlay()
      $('#facebox .loading').remove()
    })
  })

})(jQuery);


(function($){
	/* hoverIntent by Brian Cherne */
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
	
})(jQuery);


/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);


// Flash 
// Copyright (c) 2005-2006 Justin Palmer (http://encytemedia.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.
//
// Flash is used to manage error messages and notices from 
// Ajax calls passed by Prototype.  Works pretty well with 
// Ajax Global Responders.
//

var Flash = {
  // When given an error message, wrap it in a list 
  // and show it on the screen.  This message will auto-hide 
  // after a specified amount of miliseconds
  error: function(message) {
    if(message == ''){return};
    Flash.jGrowl_with_image(message, "<image style='vertical-align:middle' src='"+Ink.relative_url('/images/growl.gif')+"'>");
  },

  // Notice-level messages.  See Messenger.error for full details.
  notice: function(message) {
    if(message == ''){return};
    Flash.jGrowl_with_image(message, "<image style='vertical-align:middle' src='"+Ink.relative_url('/images/growl_good.gif')+"'>");
  },
  
  jGrowl_with_image: function(message, image) {
    jQuery.jGrowl("<table cellpadding = 4><tr><td style='vertical-align:middle'>" + image + "</td><td valign = top>" + message + "</td></tr></table>", {life: 4000, theme: 'pretty-error'});  
  }

};









/**
*
* jquery.sparkline.js
*
* v1.4
* (c) Splunk, Inc 
* Contact: Gareth Watts (gareth@splunk.com)
* http://omnipotent.net/jquery.sparkline/
*
* Generates inline sparkline charts from data supplied either to the method
* or inline in HTML
* 
* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag
* (Firefox 2.0+, Safari, Opera, etc)
*
* License: New BSD License
* 
* Copyright (c) 2009, Splunk Inc.
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, 
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of Splunk Inc nor the names of its contributors may 
*       be used to endorse or promote products derived from this software without 
*       specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* 
*
* Usage: 
*  $(selector).sparkline(values, options)
*
* If values is undefined or set to 'html' then the data values are read from the specified tag:
*   <p>Sparkline: <span class="sparkline">1,4,6,6,8,5,3,5</span></p>
*   $('.sparkline').sparkline();
* There must be no spaces in the enclosed data set
*
* Otherwise values must be an array of numbers
*    <p>Sparkline: <span id="sparkline1">This text replaced if the browser is compatible</span></p>
*    $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])
*
* For line charts, x values can also be specified:
*   <p>Sparkline: <span class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
*    $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])
*
* Supported options:
*   lineColor - Color of the line used for the chart
*   fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart
*   width - Width of the chart - Defaults to 3 times the number of values in pixels
*   height - Height of the chart - Defaults to the height of the containing element
*   chartRangeMin - Specify the minimum value to use for the range of the chart - Defaults to the minimum value supplied
*   chartRangeMax - Specify the maximum value to use for the range of the chart - Defaults to the maximum value supplied
*   composite - If true then don't erase any existing chart attached to the tag, but draw
*           another chart over the top - Note that width and height are ignored if an
*           existing chart is detected.
*
* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default),
* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'
*    line - Line chart.  Options:
*       spotColor - Set to '' to not end each line in a circular spot
*       minSpotColor - If set, color of spot at minimum value
*       maxSpotColor - If set, color of spot at maximum value
*       spotRadius - Radius in pixels
*       normalRangeMin 
*       normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal"
*                      or expected range of values
*       normalRangeColor - Color to use for the above bar
*       defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart
*
*   bar - Bar chart.  Options:
*       barColor - Color of bars for postive values
*       negBarColor - Color of bars for negative values
*       barWidth - Width of bars in pixels
*       barSpacing - Gap between bars in pixels
*       zeroAxis - Centers the y-axis around zero if true
*
*   tristate - Charts values of win (>0), lose (<0) or draw (=0)
*       posBarColor - Color of win values
*       negBarColor - Color of lose values
*       zeroBarColor - Color of draw values
*       barWidth - Width of bars in pixels
*       barSpacing - Gap between bars in pixels
*       colorMap - Optional mappnig of values to colors to override the *BarColor values above
*
*   discrete - Options:
*       lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
*       thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor
*       thresholdColor
*
*   bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...
*       options:
*       targetColor - The color of the vertical target marker
*       targetWidth - The width of the target marker in pixels
*       performanceColor - The color of the performance measure horizontal bar
*       rangeColors - Colors to use for each qualitative range background color
*
*   pie - Pie chart. Options:
*       sliceColors - An array of colors to use for pie slices
*       offset - Angle in degrees to offset the first slice - Try -90 or +90
*
*   box - Box plot. Options:
*       raw - Set to true to supply pre-computed plot points as values
*             values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier
*             When set to false you can supply any number of values and the box plot will
*             be computed for you.  Default is false.
*       showOutliers - Set to true (default) to display outliers as circles
*       outlierIRQ - Interquartile range used to determine outliers.  Default 1.5
*       boxLineColor - Outline color of the box
*       boxFillColor - Fill color for the box
*       whiskerColor - Line color used for whiskers
*       outlierLineColor - Outline color of outlier circles
*       outlierFillColor - Fill color of the outlier circles
*       spotRadius - Radius of outlier circles
*       medianColor - Line color of the median line
*       target - Draw a target cross hair at the supplied value (default undefined)
*      
*   
*       
*   Examples:
*   $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });
*   $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });
*   $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
*   $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
*   $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
*   $('#pie').sparkline([1,1,2], { type:'pie' });
*/


(function($) {

    // Provide a cross-browser interface to a few simple drawing primitives
    $.fn.simpledraw = function(width, height, use_existing) {
        if (use_existing && this[0].vcanvas) return this[0].vcanvas;
        if (width==undefined) width=$(this).innerWidth();
        if (height==undefined) height=$(this).innerHeight();
        if ($.browser.hasCanvas) {
            return new vcanvas_canvas(width, height, this);
        } else if ($.browser.msie) {
            return new vcanvas_vml(width, height, this);
        } else {
            return false;
        }
    };

    var pending = [];

    $.fn.sparkline = function(uservalues, options) {
        var options = $.extend({
            type : 'line',
            lineColor : '#00f',
            fillColor : '#cdf',
            defaultPixelsPerValue : 3,
            width : 'auto', 
            height : 'auto',
            composite : false
        }, options ? options : {});
        
        return this.each(function() {
            var render = function() {
                var values = (uservalues=='html' || uservalues==undefined) ? $(this).text().split(',') : uservalues;

                var width = options.width=='auto' ? values.length*options.defaultPixelsPerValue : options.width;
                if (options.height == 'auto') {
                    if (!options.composite || !this.vcanvas) {
                        // must be a better way to get the line height
                        var tmp = document.createElement('span');
                        tmp.innerHTML = 'a';
                        $(this).html(tmp);
                        height = $(tmp).innerHeight();
                        $(tmp).remove();
                    }
                } else {
                    height = options.height;
                }

                $.fn.sparkline[options.type].call(this, values, options, width, height);
            }
            if ($(this).is(':hidden') || $(this).parents().is(':hidden')) {
                pending.push([this, render]);
            } else {
                render.call(this);
            }
        });
    };


    $.sparkline_display_visible = function() {
        for (var i=pending.length-1; i>=0; i--) {
            var el = pending[i][0];
            if ($(el).is(':visible') && !$(el).parents().is(':hidden')) {
                pending[i][1].call(el);
                pending.splice(i, 1);
            }
        }
    };

    $.fn.sparkline.line = function(values, options, width, height) {
        var options = $.extend({
            spotColor : '#f80',
            spotRadius : 1.5,
            minSpotColor : '#f80',
            maxSpotColor : '#f80',
            normalRangeMin : undefined,
            normalRangeMax : undefined,
            normalRangeColor : '#ccc',
            chartRangeMin : undefined,
            chartRangeMax : undefined
        }, options ? options : {});

        var xvalues = [], yvalues = [];
        for (i=0; i<values.length; i++) {
            var isstr = typeof(values[i])=='string';
            var isarray = typeof(values[i])=='object' && values[i] instanceof Array;
            var sp = isstr && values[i].split(':');
            if (isstr && sp.length == 2) { // x:y
                xvalues.push(Number(sp[0]));
                yvalues.push(Number(sp[1]));
            } else if (isarray) {
                xvalues.push(values[i][0]);
                yvalues.push(values[i][1]);
            } else {
                xvalues.push(i);
                yvalues.push(Number(values[i]));
            }
        }
        if (options.xvalues) {
            xvalues = options.xvalues;
        }

        var maxy = Math.max.apply(Math, yvalues);
        var maxyval = maxy;
        var miny = Math.min.apply(Math, yvalues);
        var minyval = miny;

        var maxx = Math.max.apply(Math, xvalues);
        var maxxval = maxx;
        var minx = Math.min.apply(Math, xvalues);
        var minxval = minx;

        if (options.normalRangeMin!=undefined) {
            if (options.normalRangeMin<miny)
                miny = options.normalRangeMin;
            if (options.normalRangeMax>maxy)
                maxy = options.normalRangeMax;
        }
        if (options.chartRangeMin!=undefined && options.chartRangeMin<miny) {
            miny = options.chartRangeMin;
        }
        if (options.chartRangeMax!=undefined && options.chartRangeMax>maxy) {
            maxy = options.chartRangeMax;
        }
        var rangex = maxx-minx == 0 ? 1 : maxx-minx;
        var rangey = maxy-miny == 0 ? 1 : maxy-miny;
        var vl = yvalues.length-1;

        if (vl<1) {
            this.innerHTML = '';
            return;
        }

        var target = $(this).simpledraw(width, height, options.composite);
        if (target) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
            var canvas_top = 0;
            var canvas_left = 0;

            if (options.spotRadius && (canvas_width < (options.spotRadius*4) || canvas_height < (options.spotRadius*4))) {
                options.spotRadius = 0;
            }
            if (options.spotRadius) {
                // adjust the canvas size as required so that spots will fit
                if (options.minSpotColor || (options.spotColor && yvalues[vl]==miny)) 
                    canvas_height -= Math.ceil(options.spotRadius);
                if (options.maxSpotColor || (options.spotColor && yvalues[vl]==maxy)) {
                    canvas_height -= Math.ceil(options.spotRadius);
                    canvas_top += Math.ceil(options.spotRadius);
                }
                if (options.minSpotColor || options.maxSpotColor && (yvalues[0]==miny || yvalues[0]==maxy)) {
                    canvas_left += Math.ceil(options.spotRadius);
                    canvas_width -= Math.ceil(options.spotRadius);
                }
                if (options.spotColor || (options.minSpotColor || options.maxSpotColor && (yvalues[vl]==miny||yvalues[vl]==maxy)))
                    canvas_width -= Math.ceil(options.spotRadius);
            }


            canvas_height--;
            if (options.normalRangeMin!=undefined) {
                var ytop = canvas_top+Math.round(canvas_height-(canvas_height*((options.normalRangeMax-miny)/rangey)));
                var height = Math.round((canvas_height*(options.normalRangeMax-options.normalRangeMin))/rangey);
                target.drawRect(canvas_left, ytop, canvas_width, height, undefined, options.normalRangeColor);
            }

            var path = [ [canvas_left, canvas_top+canvas_height] ];
            for(var i=0; i<yvalues.length; i++) {
                var x=xvalues[i], y=yvalues[i];
                path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);
            }
            if (options.fillColor) {
                path.push([canvas_left+canvas_width, canvas_top+canvas_height-1]);
                target.drawShape(path, undefined, options.fillColor);
                path.pop();
            }
            path[0] = [ canvas_left, canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[0]-miny)/rangey))) ];
            target.drawShape(path, options.lineColor);
            if (options.spotRadius && options.spotColor) {
                target.drawCircle(canvas_left+canvas_width,  canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))), options.spotRadius, undefined, options.spotColor);
            }
            if (maxy!=minyval) {
                if (options.spotRadius && options.minSpotColor) {
                    var x = xvalues[yvalues.indexOf(minyval)];
                    target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),  canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))), options.spotRadius, undefined, options.minSpotColor);
                }
                if (options.spotRadius && options.maxSpotColor) {
                    var x = xvalues[yvalues.indexOf(maxyval)];
                    target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),  canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))), options.spotRadius, undefined, options.maxSpotColor);
                }
            }
        } else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
    };

    $.fn.sparkline.bar = function(values, options, width, height) {
        values = $.map(values, Number);
        var options = $.extend({
            type : 'bar',
            barColor : '#00f',
            negBarColor : '#f44',
            zeroColor: undefined,
            zeroAxis : undefined,
            barWidth : 4,
            barSpacing : 1,
            chartRangeMax: undefined,
            chartRangeMin: undefined
        }, options ? options : {});

        var width = (values.length * options.barWidth) + ((values.length-1) * options.barSpacing);
        var max = Math.max.apply(Math, values);
        var min = Math.min.apply(Math, values);
        if (options.chartRangeMin!=undefined && options.chartRangeMin<min) {
            min = options.chartRangeMin;
        }
        if (options.chartRangeMax!=undefined && options.chartRangeMax>max) {
            max = options.chartRangeMax;
        }
        if (options.zeroAxis == undefined) options.zeroAxis = min<0;
        var range = max-min == 0 ? 1 : max-min;

        var target = $(this).simpledraw(width, height);
        if (target) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
            var yzero = min<0 && options.zeroAxis ? canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1;

            for(var i=0; i<values.length; i++) {
                var x = i*(options.barWidth+options.barSpacing);
                var val = values[i];
                var color = (val < 0) ? options.negBarColor : options.barColor;
                if (options.zeroAxis && min<0) {
                    var height = Math.round(canvas_height*((Math.abs(val)/range)))+1;
                    var y = (val < 0) ? yzero : yzero-height;
                } else {
                    var height = Math.round(canvas_height*((val-min)/range))+1;
                    var y = canvas_height-height;
                }
                if (val==0 && options.zeroColor!=undefined) {
                    color = options.zeroColor;
                }
                target.drawRect(x, y, options.barWidth-1, height-1, color, color);
            }
        } else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
    };

    $.fn.sparkline.tristate = function(values, options, width, height) {
        values = $.map(values, Number);
        var options = $.extend({
            barWidth : 4,
            barSpacing : 1,
            posBarColor: '#6f6',
            negBarColor : '#f44',
            zeroBarColor : '#999',
            colorMap : {}
        }, options);

        var width = (values.length * options.barWidth) + ((values.length-1) * options.barSpacing);

        var target = $(this).simpledraw(width, height);
        if (target) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
            var half_height = Math.round(canvas_height/2);

            for(var i=0; i<values.length; i++) {
                var x = i*(options.barWidth+options.barSpacing);
                if (values[i] < 0) {
                    var y = half_height;
                    var height = half_height-1;
                    var color = options.negBarColor;
                } else if (values[i] > 0) {
                    var y = 0;
                    var height = half_height-1;
                    var color = options.posBarColor;
                } else {
                    var y = half_height-1;
                    var height = 2;
                    var color = options.zeroBarColor;
                }
                if (options.colorMap[values[i]]) {
                    color = options.colorMap[values[i]];
                }
                target.drawRect(x, y, options.barWidth-1, height-1, color, color);
            }
        } else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
    };

    $.fn.sparkline.discrete = function(values, options, width, height) {
        values = $.map(values, Number);
        var options = $.extend({
            lineHeight: 'auto',
            thresholdColor: undefined,
            thresholdValue : 0,
            chartRangeMax: undefined,
            chartRangeMin: undefined
        }, options);

        width = options.width=='auto' ? values.length*2 : width;
        var interval = Math.floor(width / values.length);

        var target = $(this).simpledraw(width, height);
        if (target) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
            var line_height = options.lineHeight == 'auto' ? Math.round(canvas_height * 0.3) : options.lineHeight;
            var pheight = canvas_height - line_height;
            var min = Math.min.apply(Math, values);
            var max = Math.max.apply(Math, values);
            if (options.chartRangeMin!=undefined && options.chartRangeMin<min) {
                min = options.chartRangeMin;
            }
            if (options.chartRangeMax!=undefined && options.chartRangeMax>max) {
                max = options.chartRangeMax;
            }
            var range = max-min;

            for(var i=0; i<values.length; i++) {
                var val = values[i];
                var x = (i*interval);
                var ytop = Math.round(pheight-pheight*((val-min)/range));
                target.drawLine(x, ytop, x, ytop+line_height, (options.thresholdColor && val < options.thresholdValue) ? options.thresholdColor : options.lineColor);
            }
        }  else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
                
    };

    $.fn.sparkline.bullet = function(values, options, width, height) {
        values = $.map(values, Number);
        // target, performance, range1, range2, range3
        var options = $.extend({
            targetColor : 'red',
            targetWidth : 3, // width of the target bar in pixels
            performanceColor : 'blue',
            rangeColors : ['#D3DAFE', '#A8B6FF', '#7F94FF' ],
            base : undefined // set this to a number to change the base start number
        }, options);

        
        width = options.width=='auto' ? '4.0em' : width;

        var target = $(this).simpledraw(width, height);
        if (target && values.length>1) {
            var canvas_width = target.pixel_width-Math.ceil(options.targetWidth/2);
            var canvas_height = target.pixel_height;

            var min = Math.min.apply(Math, values);
            var max = Math.max.apply(Math, values);
            if (options.base == undefined) {
                var min = min < 0 ? min : 0;
            } else {
                min = options.base;
            }
            var range = max-min;

            // draw range values
            for(i=2; i<values.length; i++) {
                var rangeval = parseInt(values[i]);
                var rangewidth = Math.round(canvas_width*((rangeval-min)/range));
                target.drawRect(0, 0, rangewidth-1, canvas_height-1, options.rangeColors[i-2], options.rangeColors[i-2]);
            }

            // draw the performance bar
            var perfval = parseInt(values[1]);
            var perfwidth = Math.round(canvas_width*((perfval-min)/range));
            target.drawRect(0, Math.round(canvas_height*0.3), perfwidth-1, Math.round(canvas_height*0.4)-1, options.performanceColor, options.performanceColor);

            // draw the target linej
            var targetval = parseInt(values[0]);
            var x = Math.round(canvas_width*((targetval-min)/range)-(options.targetWidth/2));
            var targettop = Math.round(canvas_height*0.10);
            var targetheight = canvas_height-(targettop*2);
            target.drawRect(x, targettop, options.targetWidth-1, targetheight-1, options.targetColor, options.targetColor);
        }  else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
    };

    $.fn.sparkline.pie = function(values, options, width, height) {
        values = $.map(values, Number);
        var options = $.extend({
            sliceColors : ['#f00', '#0f0', '#00f']
        }, options);

        width = options.width=='auto' ? height : width;

        var target = $(this).simpledraw(width, height);
        if (target && values.length>1) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
                
            var radius = Math.floor(Math.min(canvas_width, canvas_height)/2);
            var total = 0;
            for(var i=0; i<values.length; i++)
                total += values[i];
            var next = 0;
            if (options.offset) {
                next += (2*Math.PI)*(options.offset/360);
            }
            var circle = 2*Math.PI;
            for(var i=0; i<values.length; i++) {
                var start = next;
                var end = next;
                if (total > 0) {  // avoid divide by zero
                    end = next + (circle*(values[i]/total));
                }
                target.drawPieSlice(radius, radius, radius, start, end, undefined, options.sliceColors[i % options.sliceColors.length]);
                next = end;
            }
        }
    };

    function quartile(values, q) {
        if (q==2) {
            var vl2 = Math.floor(values.length/2);
            return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2;
        } else {
            var vl4 = Math.floor(values.length/4);
            return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 : values[vl4*q];
        }
    };

    $.fn.sparkline.box = function(values, options, width, height) {
        values = $.map(values, Number);
        var options = $.extend({
            raw: false,
            boxLineColor: 'black',
            boxFillColor: '#cdf',
            whiskerColor: 'black',
            outlierLineColor: '#333',
            outlierFillColor: 'white',
            medianColor: 'red',
            showOutliers: true,
            outlierIQR: 1.5,
            spotRadius: 1.5,
            target: undefined,
            targetColor: '#4a2',
            chartRangeMax: undefined,
            chartRangeMin: undefined
        }, options);

        width = options.width=='auto' ? '4.0em' : width;

        minvalue = options.chartRangeMin==undefined ? Math.min.apply(Math, values) : options.chartRangeMin;
        maxvalue = options.chartRangeMax==undefined ? Math.max.apply(Math, values) : options.chartRangeMax;
        var target = $(this).simpledraw(width, height);
        if (target && values.length>1) {
            var canvas_width = target.pixel_width;
            var canvas_height = target.pixel_height;
            if (options.raw) {
                if (options.showOutliers && values.length>5) {
                    var loutlier=values[0], lwhisker=values[1], q1=values[2], q2=values[3], q3=values[4], rwhisker=values[5], routlier=values[6];
                } else {
                    var lwhisker=values[0], q1=values[1], q2=values[2], q3=values[3], rwhisker=values[4];
                }
            } else {
                values.sort(function(a, b) { return a-b; });
                var q1 = quartile(values, 1);
                var q2 = quartile(values, 2);
                var q3 = quartile(values, 3);
                var iqr = q3-q1;
                if (options.showOutliers) {
                    var lwhisker=undefined, rwhisker=undefined;
                    for(var i=0; i<values.length; i++) {
                        if (lwhisker==undefined && values[i] > q1-(iqr*options.outlierIQR))
                            lwhisker = values[i];
                        if (values[i] < q3+(iqr*options.outlierIQR))
                            rwhisker = values[i];
                    }
                    var loutlier = values[0];
                    var routlier = values[values.length-1];
                } else {
                    var lwhisker = values[0];
                    var rwhisker = values[values.length-1];
                }
            }

            var unitsize = canvas_width / (maxvalue-minvalue+1);
            var canvas_left = 0;
            if (options.showOutliers) {
                canvas_left = Math.ceil(options.spotRadius);
                canvas_width -= 2*Math.ceil(options.spotRadius);
                var unitsize = canvas_width / (maxvalue-minvalue+1);
                if (loutlier < lwhisker)
                    target.drawCircle((loutlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.spotRadius, options.outlierLineColor, options.outlierFillColor);
                if (routlier > rwhisker)
                    target.drawCircle((routlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.spotRadius, options.outlierLineColor, options.outlierFillColor);
            }

            // box
            target.drawRect(
                Math.round((q1-minvalue)*unitsize+canvas_left),
                Math.round(canvas_height*0.1),
                Math.round((q3-q1)*unitsize), 
                Math.round(canvas_height*0.8), 
                options.boxLineColor, 
                options.boxFillColor);
            // left whisker
            target.drawLine(
                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/2), 
                Math.round((q1-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/2), 
                options.lineColor);
            target.drawLine(
                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/4), 
                Math.round((lwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height-canvas_height/4), 
                options.whiskerColor);
            // right whisker
            target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/2), 
                Math.round((q3-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/2), 
                options.lineColor);
            target.drawLine(
                Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height/4), 
                Math.round((rwhisker-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height-canvas_height/4), 
                options.whiskerColor);
            // median line
            target.drawLine(
                Math.round((q2-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height*0.1),
                Math.round((q2-minvalue)*unitsize+canvas_left), 
                Math.round(canvas_height*0.9),
                options.medianColor);
            if (options.target) {
                var size = Math.ceil(options.spotRadius);
                target.drawLine(
                    Math.round((options.target-minvalue)*unitsize+canvas_left), 
                    Math.round((canvas_height/2)-size), 
                    Math.round((options.target-minvalue)*unitsize+canvas_left), 
                    Math.round((canvas_height/2)+size), 
                    options.targetColor);
                target.drawLine(
                    Math.round((options.target-minvalue)*unitsize+canvas_left-size), 
                    Math.round(canvas_height/2), 
                    Math.round((options.target-minvalue)*unitsize+canvas_left+size), 
                    Math.round(canvas_height/2), 
                    options.targetColor);
            }
        }  else {
            // Remove the tag contents if sparklines aren't supported
            this.innerHTML = '';
        }
    };


    // IE doesn't provide an indexOf method for arrays :-(
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(entry) {
            for(var i=0; i<this.length; i++) {
                if (this[i] == entry)
                    return i;
            }
            return -1;
        }
    }

    // Setup a very simple "virtual canvas" to make drawing the few shapes we need easier
    // This is accessible as $(foo).simpledraw()

    if ($.browser.msie && !document.namespaces['v']) {
        document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
    }

    if ($.browser.hasCanvas == undefined) {
        var t = document.createElement('canvas');
        $.browser.hasCanvas = t.getContext!=undefined;
    }

    var vcanvas_base = function(width, height, target) {
    };

    vcanvas_base.prototype = {
        init : function(width, height, target) {
            this.width = width;
            this.height = height;
            this.target = target;
            if (target[0]) target=target[0];
            target.vcanvas = this;
        },

        drawShape : function(path, lineColor, fillColor) {
            alert('drawShape not implemented');
        },

        drawLine : function(x1, y1, x2, y2, lineColor) {
            return this.drawShape([ [x1,y1], [x2,y2] ], lineColor);
        },

        drawCircle : function(x, y, radius, lineColor, fillColor) {
            alert('drawCircle not implemented');
        },

        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
            alert('drawPieSlice not implemented');
        },

        drawRect : function(x, y, width, height, lineColor, fillColor) {
            alert('drawRect not implemented');
        },

        getElement : function() {
            return this.canvas;
        },

        _insert : function(el, target) {
            $(target).html(el);
        }
    };

    var vcanvas_canvas = function(width, height, target) {
        return this.init(width, height, target);
    };

    vcanvas_canvas.prototype = $.extend(new vcanvas_base, {
        _super : vcanvas_base.prototype,

        init : function(width, height, target) {
            this._super.init(width, height, target);
            this.canvas = document.createElement('canvas');
            if (target[0]) target=target[0];
            target.vcanvas = this;
            $(this.canvas).css({ display:'inline-block', width:width, height:height, verticalAlign:'top' });
            this._insert(this.canvas, target);
            this.pixel_height = $(this.canvas).height();
            this.pixel_width = $(this.canvas).width();
            this.canvas.width = this.pixel_width;
            this.canvas.height = this.pixel_height;
            $(this.canvas).css({width: this.pixel_width, height: this.pixel_height});
        },

        _getContext : function(lineColor, fillColor) {
            var context = this.canvas.getContext('2d');
            if (lineColor != undefined)
                context.strokeStyle = lineColor;
            context.lineWidth = 1;
            if (fillColor != undefined)
                context.fillStyle = fillColor;
            return context;
        },

        drawShape : function(path, lineColor, fillColor) {
            var context = this._getContext(lineColor, fillColor);
            context.beginPath();
            context.moveTo(path[0][0]+0.5, path[0][1]+0.5);
            for(var i=1; i<path.length; i++) {
                context.lineTo(path[i][0]+0.5, path[i][1]+0.5); // the 0.5 offset gives us crisp pixel-width lines
            }
            if (lineColor != undefined) {
                context.stroke();
            }
            if (fillColor != undefined) {
                context.fill();
            }
        },

        drawCircle : function(x, y, radius, lineColor, fillColor) {
            var context = this._getContext(lineColor, fillColor);
            context.beginPath();
            context.arc(x, y, radius, 0, 2*Math.PI, false);
            if (lineColor != undefined) {
                context.stroke();
            }
            if (fillColor != undefined) {
                context.fill();
            }
        }, 

        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
            var context = this._getContext(lineColor, fillColor);
            context.beginPath();
            context.moveTo(x, y);
            context.arc(x, y, radius, startAngle, endAngle, false);
            context.lineTo(x, y);
            context.closePath();
            if (lineColor != undefined) {
                context.stroke();
            }
            if (fillColor) {
                context.fill();
            }
        },

        drawRect : function(x, y, width, height, lineColor, fillColor) {
            return this.drawShape([ [x,y], [x+width, y], [x+width, y+height], [x, y+height], [x, y] ], lineColor, fillColor);
        }
        
    });

    var vcanvas_vml = function(width, height, target) {
        return this.init(width, height, target);
    };

    vcanvas_vml.prototype = $.extend(new vcanvas_base, {
        _super : vcanvas_base.prototype,

        init : function(width, height, target) {
            this._super.init(width, height, target);
            if (target[0]) target=target[0];
            target.vcanvas = this;
            this.canvas = document.createElement('span');
            $(this.canvas).css({ display:'inline-block', position: 'relative', overflow:'hidden', width:width, height:height, margin:'0px', padding:'0px', verticalAlign: 'top'});
            this._insert(this.canvas, target);
            this.pixel_height = $(this.canvas).height();
            this.pixel_width = $(this.canvas).width();
            this.canvas.width = this.pixel_width;
            this.canvas.height = this.pixel_height;;
            var groupel = '<v:group coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'"'
                    +' style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';
            this.canvas.insertAdjacentHTML('beforeEnd', groupel);
            this.group = $(this.canvas).children()[0];
        },

        drawShape : function(path, lineColor, fillColor) {
            var vpath = [];
            for(var i=0; i<path.length; i++) {
                vpath[i] = ''+(path[i][0]-1)+','+(path[i][1]-1);
            }
            var initial = vpath.splice(0,1);
            var stroke = lineColor == undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
            var fill = fillColor == undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
            var closed = vpath[0] == vpath[vpath.length-1] ? 'x ' : '';
            var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" '
                + stroke
                + fill
                +' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" '
                +' path="m '+initial+' l '+vpath.join(', ')+' '+closed+'e">'
                +' </v:shape>';
             this.group.insertAdjacentHTML('beforeEnd', vel);
        },

        drawCircle : function(x, y, radius, lineColor, fillColor) {
            x -= radius+1;
            y -= radius+1;
            var stroke = lineColor == undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
            var fill = fillColor == undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
            var vel = '<v:oval '
                + stroke
                + fill
                +' style="position:absolute;top:'+y+'; left:'+x+'; width:'+(radius*2)+'; height:'+(radius*2)+'"></v:oval>';
            this.group.insertAdjacentHTML('beforeEnd', vel);
            
        },
        
        drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
            if (startAngle == endAngle) {
                return;  // VML seems to have problem when start angle equals end angle.
            }
            if ((endAngle - startAngle) == (2*Math.PI)) {
                startAngle = 0.0;  // VML seems to have a problem when drawing a full circle that doesn't start 0
                endAngle = (2*Math.PI);
            }

            var startx = x + Math.round(Math.cos(startAngle) * radius);
            var starty = y + Math.round(Math.sin(startAngle) * radius);
            var endx = x + Math.round(Math.cos(endAngle) * radius);
            var endy = y + Math.round(Math.sin(endAngle) * radius);

            var vpath = [  x-radius, y-radius, x+radius, y+radius, startx, starty, endx, endy ]; 
            var stroke = lineColor == undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
            var fill = fillColor == undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
            var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" '
                + stroke
                + fill
                +' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" '
                +' path="m '+x+','+y+' wa '+vpath.join(', ')+' x e">'
                +' </v:shape>';
             this.group.insertAdjacentHTML('beforeEnd', vel);
        },

        drawRect : function(x, y, width, height, lineColor, fillColor) {
            return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height], [x+width, y], [x, y] ], lineColor, fillColor);
        }
    });

})(jQuery);


/* Copyright (c) 2008 Kean Loong Tan http://www.gimiti.com/kltan
 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * jFlow
 * Version: 1.2 (July 7, 2008)
 * Requires: jQuery 1.2+
 */
 
(function($) {

	$.fn.jFlow = function(options) {
		var opts = $.extend({}, $.fn.jFlow.defaults, options);
		var randNum = Math.floor(Math.random()*11);
		var jFC = opts.controller;
		var jFS =  opts.slideWrapper;
		var jSel = opts.selectedWrapper;

		var cur = 0;
		var maxi = $(jFC).length;
		// sliding function
		var slide = function (dur, i) {
			$(opts.slides).children().css({
				overflow:"hidden"
			});
			$(opts.slides + " iframe").hide().addClass("temp_hide");
			$(opts.slides).animate({
				marginLeft: "-" + (i * $(opts.slides).find(":first-child").width() + "px")}, 
				opts.duration*(dur),
				opts.easing,
				function(){
					$(opts.slides).children().css({
						overflow:"auto"
					});
					$(".temp_hide").show();
				}
			);
			
		}
		$(this).find(jFC).each(function(i){
			$(this).click(function(){
				if ($(opts.slides).is(":not(:animated)")) {
					$(jFC).removeClass(jSel);
					$(this).addClass(jSel);
					var dur = Math.abs(cur-i);
					slide(dur,i);
					cur = i;
				}
			});
		});	
		
		$(opts.slides).before('<div id="'+jFS.substring(1, jFS.length)+'"></div>').appendTo(jFS);
		
		$(opts.slides).find("div").each(function(){
			$(this).before('<div class="jFlowSlideContainer"></div>').appendTo($(this).prev());
		});
		
		//initialize the controller
		$(jFC).eq(cur).addClass(jSel);
		
		var resize = function (x){
			$(jFS).css({
				position:"relative",
				width: opts.width,
				height: opts.height,
				overflow: "hidden"
			});
			//opts.slides or #mySlides container
			$(opts.slides).css({
				position:"relative",
				width: $(jFS).width()*$(jFC).length+"px",
				height: $(jFS).height()+"px",
				overflow: "hidden"
			});
			// jFlowSlideContainer
			$(opts.slides).children().css({
				position:"relative",
				width: $(jFS).width()+"px",
				height: $(jFS).height()+"px",
				"float":"left",
				overflow:"auto"
			});
			
			$(opts.slides).css({
				marginLeft: "-" + (cur * $(opts.slides).find(":eq(0)").width() + "px")
			});
		}
		
		// sets initial size
		resize();

		// resets size
		$(window).resize(function(){
			resize();						  
		});
		
		$(opts.prev).click(function(){
			if ($(opts.slides).is(":not(:animated)")) {
				var dur = 1;
				if (cur > 0)
					cur--;
				else {
					cur = maxi -1;
					dur = cur;
				}
				$(jFC).removeClass(jSel);
				slide(dur,cur);
				$(jFC).eq(cur).addClass(jSel);
			}
		});
		
		$(opts.next).click(function(){
			if ($(opts.slides).is(":not(:animated)")) {
				var dur = 1;
				if (cur < maxi - 1)
					cur++;
				else {
					cur = 0;
					dur = maxi -1;
				}
				$(jFC).removeClass(jSel);
				slide(dur, cur);
				$(jFC).eq(cur).addClass(jSel);
			}
		});
	};
	
	$.fn.jFlow.defaults = {
		controller: ".jFlowControl", // must be class, use . sign
		slideWrapper : "#jFlowSlide", // must be id, use # sign
		selectedWrapper: "jFlowSelected",  // just pure text, no sign
		easing: "swing",
		duration: 400,
		width: "100%",
		prev: ".jFlowPrev", // must be class, use . sign
		next: ".jFlowNext" // must be class, use . sign
	};
	
})(jQuery);


/*
 Highcharts JS v1.2.5 (2010-04-13)

 (c) 2010 Torstein Hønsi

 License: www.highcharts.com/license
*/
(function(){function jc(a){if(!a||a.constructor!=Array)a=[a];return a}function Qa(a){return a!==ma&&a!==null}function da(){var a=arguments,b,c;for(b=0;b<a.length;b++){c=a[b];if(Qa(c))return c}}function Gb(a,b,c){var d,e="",f=c?"print":"",g=function(i){return V("style",{type:"text/css",media:i?"print":""},null,va.getElementsByTagName("HEAD")[0])};kc||(kc=g());for(d in b)e+=Pb(d)+":"+b[d]+";";if(Ra){b=va.styleSheets;c&&g(true);for(c=b.length-1;c>=0&&b[c].media!=f;)c--;f=b[c];f.addRule(a,e)}else kc.appendChild(va.createTextNode(a+
" {"+e+"}\n"))}function H(a,b){a||(a={});for(var c in b)a[c]=b[c];return a}function Vc(a){Ba=aa(Ba,a);Cc();return Ba}function Ca(a){Qb||(Qb=V(Va));a&&Qb.appendChild(a);Qb.innerHTML=""}function ab(a,b){var c=function(){};c.prototype=new a;H(c.prototype,b);return c}function Hb(a,b){if(typeof a=="string")return a;else if(a.linearGradient){var c=b.createLinearGradient.apply(b,a.linearGradient);p(a.stops,function(d){c.addColorStop(d[0],d[1])});return c}}function V(a,b,c,d,e){a=va.createElement(a);b&&H(a,
b);e&&ra(a,{padding:0,border:"none",margin:0});c&&ra(a,c);d&&d.appendChild(a);return a}function ra(a,b){if(Ra)if(b.opacity!==ma)b.filter="alpha(opacity="+b.opacity*100+")";H(a.style,b)}function Wc(a,b,c,d){var e=Ba.lang;a=a;var f=isNaN(b=Da(b))?2:b;b=c===ma?e.decimalPoint:c;d=d===ma?e.thousandsSep:d;e=a<0?"-":"";c=parseInt(a=Da(+a||0).toFixed(f))+"";var g=(g=c.length)>3?g%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+Da(a-c).toFixed(f).slice(2):"")}function lc(a,
b,c){function d(y){return y.toString().replace(/^([0-9])$/,"0$1")}if(!Qa(b))return"Invalid date";b=new Date(b*Sa);var e=b[mc](),f=b[nc](),g=b[Ib](),i=b[Rb](),k=b[Sb](),j=Ba.lang,r=j.weekdays;j=j.months;b={a:r[f].substr(0,3),A:r[f],d:d(g),e:g,b:j[i].substr(0,3),B:j[i],m:d(i+1),y:k.toString().substr(2,2),Y:k,H:d(e),I:d(e%12||12),l:e%12||12,M:d(b[oc]()),p:e<12?"AM":"PM",P:e<12?"am":"pm",S:d(b.getSeconds())};for(var v in b)a=a.replace("%"+v,b[v]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a}function Cc(){var a=
Ba.global.useUTC;Tb=a?Date.UTC:function(b,c,d,e,f,g){return(new Date(b,c,da(d,1),da(e,0),da(f,0),da(g,0))).getTime()};oc=a?"getUTCMinutes":"getMinutes";mc=a?"getUTCHours":"getHours";nc=a?"getUTCDay":"getDay";Ib=a?"getUTCDate":"getDate";Rb=a?"getUTCMonth":"getMonth";Sb=a?"getUTCFullYear":"getFullYear";Dc=a?"setUTCMinutes":"setMinutes";Ec=a?"setUTCHours":"setHours";pc=a?"setUTCDate":"setDate";Fc=a?"setUTCMonth":"setMonth";Gc=a?"setUTCFullYear":"setFullYear"}function Hc(a){for(var b={x:a.offsetLeft,
y:a.offsetTop};a.offsetParent;){a=a.offsetParent;b.x+=a.offsetLeft;b.y+=a.offsetTop;if(a!=va.body&&a!=va.documentElement){b.x-=a.scrollLeft;b.y-=a.scrollTop}}return b}function Xc(a){function b(l,h){var s;h=da(h,true);na(t,"addSeries",{options:l},function(){s=d(l);s.isDirty=true;t.isDirty=true;h&&t.redraw()});return s}function c(){var l=t.isDirty;p(ya,function(h){if(h.isDirty){h.cleanData();h.getSegments();if(h.options.legendType=="point")l=true}});Cb=null;if(Ub){p(Ka,function(h){h.setScale()});j();
p(Ka,function(h){h.isDirty&&h.redraw()})}p(ya,function(h){h.isDirty&&h.visible&&h.redraw()});if(l){if(Jb&&Jb.renderHTML){Jb.renderHTML(true);Jb.drawGraphics(true)}t.isDirty=false}ub&&ub.resetTracker&&ub.resetTracker();na(t,"redraw")}function d(l){var h=l.type||A.defaultSeriesType,s=bb[h],q=t.hasRendered;if(q)if(Ea&&h=="column")s=Ic;else if(!Ea&&h=="bar")s=Vb;h=new s;h.init(t,l);if(!q&&h.inverted)Ea=true;if(h.isCartesian)Ub=h.isCartesian;ya.push(h);return h}function e(){var l=a.loading;if(!vb){vb=
V(Va,{className:"highcharts-loading"},H(l.style,{left:ga+F,top:I+F,width:sa+F,height:ka+F,zIndex:10,display:"none"}),oa);V("span",{innerHTML:a.lang.loading},l.labelStyle,vb)}ra(vb,{display:""});Db(vb,{opacity:l.style.opacity},{duration:l.showDuration})}function f(){Db(vb,{opacity:0},{duration:a.loading.hideDuration,complete:function(){ra(vb,{display:"none"})}})}function g(l){var h,s,q;for(h=0;h<Ka.length;h++)if(Ka[h].options.id==l)return Ka[h];for(h=0;h<ya.length;h++)if(ya[h].options.id==l)return ya[h];
for(h=0;h<ya.length;h++){q=ya[h].data;for(s=0;s<q.length;s++)if(q[s].id==l)return q[s]}return null}function i(){var l=va.getElementById(qc);if(l)lb=Hc(l)}function k(){var l=a.xAxis||{},h=a.yAxis||{},s;l=jc(l);p(l,function(q,M){q.index=M;q.isX=true});h=jc(h);p(h,function(q,M){q.index=M});Ka=l.concat(h);t.xAxis=[];t.yAxis=[];Ka=qb(Ka,function(q){s=new Fa(t,q);t[s.isXAxis?"xAxis":"yAxis"].push(s);return s});j()}function j(){A.alignTicks!==false&&p(Ka,function(l){l.adjustTickAmount()})}function r(){var l=
[];p(ya,function(h){l=l.concat(Wb(h.data,function(s){return s.selected}))});return l}function v(){return Wb(ya,function(l){return l.selected})}function y(l){var h=Ba.lang;t.toolbar.add("zoom",h.resetZoom,h.resetZoomTitle,function(){na(t,"selection",{resetSelection:true},y);t.toolbar.remove("zoom")});!l||l.resetSelection?p(Ka,function(s){s.setExtremes(null,null,false)}):p(l.xAxis.concat(l.yAxis),function(s){var q=s.axis;if(t.tracker[q.isXAxis?"zoomX":"zoomY"])q.setExtremes(s.min,s.max,false)});c()}
function R(){var l=a.title,h=a.subtitle;if(!t.titleLayer){var s=new pa("title-layer",oa,null,{zIndex:2});l&&l.text&&V("h2",{className:"highcharts-title",innerHTML:l.text},l.style,s.div);h&&h.text&&V("h3",{className:"highcharts-subtitle",innerHTML:h.text},h.style,s.div);t.titleLayer=s}}function E(){var l=true;for(var h in t.resources)t.resources[h]||(l=false);l&&K()}function K(){k();p(ya,function(l){l.translate();l.setTooltipPoints();l.createArea()});t.render=Wa;setTimeout(function(){Wa();na(t,"load")},
0)}function C(){Xa=A.renderTo;qc="highcharts-"+rc++;if(typeof Xa=="string")Xa=va.getElementById(Xa);Xa.innerHTML="";if(!Xa.offsetWidth){rb=Xa.cloneNode(0);ra(rb,{position:wa,top:"-9999px",display:""});va.body.appendChild(rb)}var l=(rb||Xa).offsetHeight;mb=A.width||(rb||Xa).offsetWidth||600;Ga=A.height||(l>I+cb?l:0)||400;oa=V(Va,{className:"highcharts-container"+(A.className?" "+A.className:""),id:qc},H({position:Xb,overflow:db,width:mb+F,height:Ga+F,textAlign:"left"},A.style),rb||Xa)}function Wa(){var l,
h=a.labels,s=a.credits;l=2*(A.borderWidth||0)+(A.shadow?8:0);Jc.drawRect(l/2,l/2,mb-l,Ga-l,A.borderColor,A.borderWidth,A.borderRadius,A.backgroundColor,A.shadow);Jc.drawRect(ga,I,sa,ka,null,null,null,A.plotBackgroundColor,null,Yb);(new pa("plot-border",oa,null,{zIndex:4})).drawRect(ga,I,sa,ka,A.plotBorderColor,A.plotBorderWidth,null,null,A.plotShadow);Ra&&Gb(".highcharts-image-map",{display:"none"},"print");Ub&&p(Ka,function(q){q.render()});R();h.items&&p(h.items,function(){var q=H({className:"highcharts-label"},
this.attributes);sc.drawHtml(this.html,q,H(h.style,this.style))});p(ya,function(q){q.render()});Jb=t.legend=new nb(t);if(!t.toolbar)t.toolbar=Kb(t);if(s.enabled&&!t.credits)t.credits=V("a",{className:"highcharts-credits",href:s.href,innerHTML:s.text,target:s.target},H(s.style,{zIndex:8}),oa);t.hasRendered=true;if(rb){Xa.appendChild(oa);Ca(rb);i()}}function La(){function l(h){var s=h.attributes,q,M;if(s){q=s.length;for(q=q-1;q>=0;q-=1){M=s[q].name;try{if(typeof h[M]=="function")h[M]=null}catch(ea){}}}if(s=
h.childNodes){q=s.length;for(q=q-1;q>=0;q--){s=h.childNodes[q];l(s);s.childNodes.length||Ca(s)}}}p(ya,function(h){h.destroy()});ya=[];l(oa)}function Fa(l,h){function s(){h=aa(L?Zb:tc,Y?la?Yc:Kc:la?Zc:$c,h)}function q(){var m=[],n;Ma=Ta=null;$b=[];p(ya,function(u){n=false;p(["xAxis","yAxis"],function(J){if((J=="xAxis"&&L||J=="yAxis"&&!L)&&(u.options[J]==h.index||u.options[J]===ma&&h.index==0)){u[J]=Ya;$b.push(u);n=true}});if(!u.visible&&A.ignoreHiddenSeries)n=false;if(n){var x;if(!L){x=u.options.stacking;
ac=x=="percent";if(x){var z=m[u.type]||[];m[u.type]=z}if(ac){Ma=0;Ta=99}}if(u.isCartesian){p(u.data,function(J){var G=J.x,ja=J.y;if(Ma===null)Ma=Ta=J[wb];if(L)if(G>Ta)Ta=G;else{if(G<Ma)Ma=G}else if(Qa(ja)){if(x)z[G]=z[G]?z[G]+ja:ja;J=z?z[G]:ja;if(!ac)if(J>Ta)Ta=J;else if(J<Ma)Ma=J;if(x)eb[u.type][G]={total:J,cum:J}}});if(!L&&/(area|column|bar)/.test(u.type))if(Ma>=0){Ma=0;Lc=true}else if(Ta<0){Ta=0;Mc=true}}}})}function M(m,n,u){var x=1,z=0;if(u){x*=-1;z=sb}if(xb){x*=-1;z-=x*sb}if(n){if(xb)m=sb-m;
m=m/yb+W}else m=x*(m-W)*yb+z;return m}function ea(m,n,u){if(u){var x,z,J;x=M(m);var G;m=z=x+bc;x=J=Ga-x-bc;if(Y){x=I;J=Ga-cb;if(m<ga||m>ga+sa)G=true}else{m=ga;z=mb-fb;if(x<I||x>I+ka)G=true}G||Nc.drawLine(m,x,z,J,n,u)}}function xa(m,n,u){m=Lb(m,W);n=Math.min(n,ha);var x=(n-m)*yb;ea(m+(n-m)/2,u,x)}function D(m,n,u,x,z,J,G){var ja,ba,gb,N=h.labels;if(n=="inside")z=-z;if(la)z=-z;n=ba=M(m+zb)+bc;ja=gb=Ga-M(m+zb)-bc;if(Y){ja=Ga-cb-(la?ka:0)+Ua;gb=ja+z}else{n=ga+(la?sa:0)+Ua;ba=n-z}x&&Eb.drawLine(n,ja,ba,
gb,u,x);if(J&&N.enabled)if((m=cc.call({index:G,isFirst:m==fa[0],isLast:m==fa[fa.length-1],value:Ha&&Ha[m]?Ha[m]:m}))||m===0)Eb.addText(m,n+N.x-(zb&&Y?zb*yb*(xb?-1:1):0),ja+N.y-(zb&&!Y?zb*yb*(xb?1:-1):0),N.style,N.rotation,N.align)}function ia(m,n){var u;da(h.allowDecimals,true);Mb=n?1:ta.pow(10,Za(ta.log(m)/ta.LN10));u=m/Mb;n||(n=[1,2,2.5,5,10]);for(var x=0;x<n.length;x++){m=n[x];if(u<=(n[x]+(n[x+1]||n[x]))/2)break}m*=Mb;return m}function U(){fa=[];for(var m=Ba.global.useUTC,n=1E3/Sa,u=6E4/Sa,x=36E5/
Sa,z=864E5/Sa,J=6048E5/Sa,G=2592E6/Sa,ja=31556952E3/Sa,ba=[["second",n,[1,2,5,10,15,30]],["minute",u,[1,2,5,10,15,30]],["hour",x,[1,2,3,4,6,8,12]],["day",z,[1,2]],["week",J,[1,2]],["month",G,[1,2,3,4,6]],["year",ja,null]],gb=ba[6],N=gb[1],Z=gb[2],$a=0;$a<ba.length;$a++){gb=ba[$a];N=gb[1];Z=gb[2];if(ba[$a+1]){var ad=(N*Z[Z.length-1]+ba[$a+1][1])/2;if(Ia<=ad)break}}if(N==ja&&Ia<5*N)Z=[1,2,5];ba=ia(Ia/N,Z);var tb;Z=new Date(W*Sa);Z.setMilliseconds(0);if(N>=n)Z.setSeconds(N>=u?0:ba*Za(Z.getSeconds()/
ba));if(N>=u)Z[Dc](N>=x?0:ba*Za(Z[oc]()/ba));if(N>=x)Z[Ec](N>=z?0:ba*Za(Z[mc]()/ba));if(N>=z)Z[pc](N>=G?1:ba*Za(Z[Ib]()/ba));if(N>=G){Z[Fc](N>=ja?0:ba*Za(Z[Rb]()/ba));tb=Z[Sb]()}if(N>=ja){tb-=tb%ba;Z[Gc](tb)}N==J&&Z[pc](Z[Ib]()-Z[nc]()+h.startOfWeek);$a=1;n=Z.getTime()/Sa;tb=Z[Sb]();u=Z[Rb]();for(x=Z[Ib]();n<ha&&$a<sa;){fa.push(n);if(N==ja)n=Tb(tb+$a*ba,0)/Sa;else if(N==G)n=Tb(tb,u+$a*ba)/Sa;else if(!m&&(N==z||N==J))n=Tb(tb,u,x+$a*ba*(N==z?1:7));else n+=N*ba;$a++}fa.push(n);h.labels.formatter||(cc=
function(){return lc(h.dateTimeLabelFormats[gb[0]],this.value,1)})}function X(){var m=function(x){var z=(Mb<1?O(1/Mb):1)*10;return O(x*z)/z},n;n=Za(W/Ia)*Ia;var u=ta.ceil(ha/Ia)*Ia;fa=[];for(n=m(n);n<=u;){fa.push(n);n=m(n+Ia)}if(Ha){W-=0.5;ha+=0.5}cc||(cc=function(){return this.value})}function ca(){hb?U():X();var m=fa[0],n=fa[fa.length-1];if(h.startOnTick)W=m;else W>m&&fa.shift();if(h.endOnTick)ha=n;else ha<n&&fa.pop()}function za(){if(!hb&&!Ha){var m=Fb,n=fa.length;Fb=Cb[wb];if(n<Fb){for(;fa.length<
Fb;)fa.push(fa[fa.length-1]+Ia);yb*=(n-1)/(Fb-1)}if(Qa(m)&&Fb!=m)Ya.isDirty=true}}function P(){var m,n,u,x=W,z=ha;m=h.maxZoom;var J;q();W=da(Oc,h.min,Ma);ha=da(Pc,h.max,Ta);if(ha-W<m){J=(m-ha+W)/2;W=Lb(W-J,da(h.min,W-J));ha=ta.min(W+m,da(h.max,W+m))}if(!Ha&&!ac){m=ha-W||1;if(!Qa(h.min)&&Qc&&(Ma<0||!Lc))W-=m*Qc;if(!Qa(h.max)&&Rc&&(Ta>0||!Mc))ha+=m*Rc}Ia=Ha||W==ha?1:h.tickInterval=="auto"?(ha-W)*h.tickPixelInterval/sb:h.tickInterval;if(!hb&&h.tickInterval=="auto")Ia=ia(Ia);uc=h.minorTickInterval=="auto"&&
Ia?Ia/5:h.minorTickInterval;ca();yb=sb/(ha-W||1);Cb||(Cb={x:0,y:0});if(!hb&&fa.length>Cb[wb])Cb[wb]=fa.length;if(!L)for(n in eb)for(u in eb[n])eb[n][u].cum=eb[n][u].total;Ya.isDirty=W!=x||ha!=z}function Aa(m,n,u){u=da(u,true);na(Ya,"setExtremes",{min:m,max:n},function(){if(Ha){if(m<0)m=0;if(n>Ha.length-1)n=Ha.length-1}Oc=m;Pc=n;u&&l.redraw()})}function w(m,n){Ha=m;da(n,true)&&o()}function qa(){return{min:W,max:ha,dataMin:Ma,dataMax:Ta}}function S(m){var n=m.width,u=n?vc:wc;u.push(m);n?ea(m.value,
m.color,m.width):xa(m.from,m.to,m.color)}function Na(m){p([wc,vc],function(n){for(var u=0;u<n.length;u++)if(n[u].id==m){n.splice(u,1);break}});Q()}function o(){ub.resetTracker&&ub.resetTracker();Q();p($b,function(m){m.isDirty=true})}function Q(){var m=h.title,n=h.alternateGridColor,u=h.minorTickWidth,x=h.lineWidth,z,J;z=$b.length&&Qa(W)&&Qa(ha);Eb.clear();Nc.clear();if(z){n&&p(fa,function(G,ja){if(ja%2==0&&G<ha)xa(G,fa[ja+1]!==ma?fa[ja+1]:ha,n)});p(wc,function(G){xa(G.from,G.to,G.color)});if(uc&&
!Ha)for(z=W;z<=ha;z+=uc){ea(z,h.minorGridLineColor,h.minorGridLineWidth);u&&D(z,h.minorTickPosition,h.minorTickColor,u,h.minorTickLength)}p(fa,function(G,ja){J=G+zb;ea(J,h.gridLineColor,h.gridLineWidth);D(G,h.tickPosition,h.tickColor,h.tickWidth,h.tickLength,!(G==W&&!h.showFirstLabel||G==ha&&!h.showLastLabel),ja)});p(vc,function(G){ea(G.value,G.color,G.width)})}if(x){u=ga+(la?sa:0)+Ua;z=Ga-cb-(la?ka:0)+Ua;Eb.drawLine(Y?ga:u,Y?z:I,Y?mb-fb:u,Y?z:Ga-cb,h.lineColor,x)}if(m&&m.enabled&&m.text){x=Y?ga:
I;u=Y?sa:ka;x={low:x+(Y?0:u),middle:x+u/2,high:x+(Y?u:0)}[m.align];u=(Y?I+ka:ga)+(Y?1:-1)*(la?-1:1)*m.margin-(Ra?parseInt(m.style.fontSize||m.style.font.replace(/^[a-z ]+/,""))/3:0);Eb.addText(m.text,Y?x:u+(la?sa:0)+Ua,Y?u-(la?ka:0)+Ua:x,m.style,m.rotation||0,{low:"left",middle:"center",high:"right"}[m.align])}Eb.strokeText();Ya.isDirty=false}var L=h.isX,la=h.opposite,Y=Ea?!L:L,eb={bar:{},column:{},area:{},areaspline:{}};s();var Ya=this,hb=h.type=="datetime",Ua=h.offset||0,wb=L?"x":"y",sb=Y?sa:ka,
yb,bc=Y?ga:cb,Eb=new pa("axis-layer",oa,null,{zIndex:7}),Nc=new pa("grid-layer",oa,null,{zIndex:1}),Ma,Ta,$b,Oc,Pc,ha=null,W=null,Qc=h.minPadding,Rc=h.maxPadding,Lc,Mc,ac,Sc=h.events,xc,wc=h.plotBands||[],vc=h.plotLines||[],Ia,uc,Mb,fa,Fb,cc=h.labels.formatter,Ha=h.categories||L&&l.columnCount,xb=h.reversed,zb=Ha&&h.tickmarkPlacement=="between"?0.5:0;if(Ea&&L&&xb===ma)xb=true;la||(Ua*=-1);if(Y)Ua*=-1;H(Ya,{addPlotBand:S,addPlotLine:S,adjustTickAmount:za,categories:Ha,getExtremes:qa,isXAxis:L,options:h,
render:Q,setExtremes:Aa,setScale:P,setCategories:w,translate:M,redraw:o,removePlotBand:Na,removePlotLine:Na,reversed:xb,stacks:eb});for(xc in Sc)Oa(Ya,xc,Sc[xc]);P()}function Kb(){function l(M,ea,xa,D){if(!q[M]){ea=V(Va,{innerHTML:ea,title:xa,onclick:D},H(a.toolbar.itemStyle,{zIndex:1003}),s.div);q[M]=ea}}function h(M){Ca(q[M]);q[M]=null}var s,q={};s=new pa("toolbar",oa,null,{zIndex:1004,width:"auto",height:"auto"});return{add:l,remove:h}}function ob(l,h){function s(o){o=o||Pa.event;if(!o.target)o.target=
o.srcElement;if(!o.pageX)o.pageX=o.clientX+(va.documentElement.scrollLeft||va.body.scrollLeft);if(!o.pageY)o.pageY=o.clientY+(va.documentElement.scrollTop||va.body.scrollTop);return o}function q(o){var Q={xAxis:[],yAxis:[]};p(Ka,function(L){var la=L.translate,Y=L.isXAxis,eb=Ea?!Y:Y;Q[Y?"xAxis":"yAxis"].push({axis:L,value:la(eb?o.pageX-lb.x-ga:ka-o.pageY+lb.y+I,true)})});return Q}function M(){ib.onmousedown=function(o){o=s(o);o.preventDefault&&o.preventDefault();l.mouseIsDown=Nb=true;X=o.pageX;ca=
o.pageY;if(Ub&&(w||qa)){P||(P=V(Va,null,{position:wa,border:"none",background:"#4572A7",opacity:0.25,width:S?0:sa+F,height:Na?0:ka+F}));sc.div.appendChild(P)}};ib.onmousemove=function(o){o=s(o);o.returnValue=false;if(Nb){za=Math.sqrt(Math.pow(X-o.pageX,2)+Math.pow(ca-o.pageY,2))>10;if(S){var Q=o.pageX-X;ra(P,{width:Da(Q)+F,left:(Q>0?0:Q)+X-lb.x-ga+F})}if(Na){o=o.pageY-ca;ra(P,{height:Da(o)+F,top:(o>0?0:o)+ +ca-lb.y-I+F})}}else ea(o);return false};ib.onmouseup=function(){var o;if(P){var Q={xAxis:[],
yAxis:[]},L=P.offsetLeft,la=P.offsetTop,Y=P.offsetWidth,eb=P.offsetHeight;if(za){p(Ka,function(Ya){var hb=Ya.translate,Ua=Ya.isXAxis,wb=Ea?!Ua:Ua,sb=hb(wb?L:ka-la-eb,true);hb=hb(wb?L+Y:ka-la,true);Q[Ua?"xAxis":"yAxis"].push({axis:Ya,min:ta.min(sb,hb),max:Lb(sb,hb)})});na(l,"selection",Q,y);o=true}Ca(P);P=null}l.mouseIsDown=Nb=za=false};ib.onmouseout=function(o){o=o||Pa.event;if((o=o.relatedTarget||o.toElement)&&o!=dc&&o.tagName!="AREA"){D();l.mouseIsDown=Nb=za=false}};ib.onclick=function(o){o=s(o);
o.cancelBubble=true;if(!za)if(U&&o.target.tagName=="AREA"){var Q=U.plotX,L=U.plotY;H(U,{pageX:lb.x+ga+(Ea?sa-L:Q),pageY:lb.y+I+(Ea?ka-Q:L)});na(l.hoverSeries,"click",H(o,{point:U}));U.firePointEvent("click",o)}else{H(o,q(o));na(l,"click",o)}za=false}}function ea(o){var Q=l.hoverPoint,L=l.hoverSeries;if(L){Q||(Q=L.tooltipPoints[Ea?o.pageY-lb.y-I:o.pageX-lb.x-ga]);if(Q&&Q!=U){U&&U.firePointEvent("mouseOut");Q.firePointEvent("mouseOver");Ab&&Ab.refresh(Q);U=Q}}}function xa(){var o="highchartsMap"+bd++;
l.imagemap=ib=V("map",{name:o,id:o,className:"highcharts-image-map"},null,oa);dc=V("img",{useMap:"#"+o},{width:sa+F,height:ka+F,left:ga+F,top:I+F,opacity:0,border:"none",position:wa,clip:"rect(1px,"+sa+"px,"+ka+"px,1px)",zIndex:9},ib);if(!Ra)dc.src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="}function D(){Ab&&Ab.hide();if(l.hoverSeries){l.hoverSeries.setState();U=l.hoverSeries=null}}function ia(o){var Q=0,L,la=ib.childNodes;for(L=0;L<la.length;L++)if(la[L].isLegendArea){Q=
L+1;break}ib.insertBefore(o,la[Q])}var U,X,ca,za,P,Aa=A.zoomType,w=/x/.test(Aa),qa=/y/.test(Aa),S=w&&!Ea||qa&&Ea,Na=qa&&!Ea||w&&Ea;xa();if(h.enabled)l.tooltip=Ab=jb(h);M();setInterval(function(){yc&&yc()},32);H(this,{insertAtFront:ia,zoomX:w,zoomY:qa,resetTracker:D})}function jb(l){function h(ia,U){var X=ia.tooltipPos;U=ia.series;var ca=l.borderColor||ia.color||U.color||"#606060",za=t.inverted,P,Aa,w,qa=ea.offsetHeight;w=ia.tooltipText;M=U;P=X?X[0]:za?sa-ia.plotY:ia.plotX;X=X?X[1]:za?ka-ia.plotX:
ia.plotY;if(P>=0&&P<=sa&&X>=0&&X<=ka)Aa=true;if(w===false||!Aa)q();else{ea.innerHTML=w;ra(ea,{overflow:ec});Aa=ea.offsetWidth-xa;w=ea.offsetHeight-xa;ra(ea,{overflow:db});if(Aa>(D.w||0)+20||Aa<(D.w||0)-20||w>D.h||D.c!=ca||qa!=ea.offsetHeight){D.clear();D.drawRect(xa/2,xa/2,Aa+20,w,ca,xa,l.borderRadius,l.backgroundColor,l.shadow);H(D,{w:Aa,h:w,c:ca})}ca=P-D.w+ga-35;P=X-D.h+10+I;if(ca<5){ca=5;P-=20}if(P<5)P=5;else if(P+D.h>Ga)P=Ga-D.h-5;s(O(ca),O(P));U.drawPointState(ia,"hover");kb.style.visibility=
ec}}function s(ia,U){var X=kb.style.visibility==db,ca=X?ia:(kb.offsetLeft+ia)/2;X=X?U:(kb.offsetTop+U)/2;ra(kb,{left:ca+F,top:X+F});yc=Da(ia-ca)>1||Da(U-X)>1?function(){s(ia,U)}:null}function q(){if(kb)kb.style.visibility=db;M&&M.drawPointState()}var M,ea,xa=l.borderWidth,D;kb=V(Va,null,{position:wa,visibility:db,overflow:db,padding:"0 50px 5px 0",zIndex:8},oa);D=new pa("tooltip-box",kb,null,{width:mb+F,height:Ga+F});ea=V(Va,{className:"highcharts-tooltip"},H(l.style,{maxWidth:mb-40+F,textOverflow:"ellipsis",
position:Xb,zIndex:2}),kb);return{refresh:h,hide:q}}var nb=function(l){function h(Aa){if(Aa){p(U,function(w){Ca(w.legendItem)});U=[]}P&&za.reverse();p(za,function(w){if(w.options.showInLegend){var qa=w.options.legendType=="point"?w.data:[w];p(qa,function(S){S.simpleSymbol=/(bar|pie|area|column)/.test(w.type);S.legendItem=M=V("li",{innerHTML:q.labelFormatter.call(S),className:S.visible?"":Ob},null,D.firstChild);if(S.options&&S.options.showCheckbox)S.checkbox=V("input",{type:"checkbox",checked:S.selected,
defaultChecked:S.selected},q.itemCheckboxStyle,M);Oa(M,"mouseover",function(){S.setState("hover")});Oa(M,"mouseout",function(){S.setState()});Oa(M,"click",function(Na){Na=Na.target;var o="legendItemClick",Q=function(){S.setVisible()};if(Na.tagName=="INPUT")na(S,"checkboxClick",{checked:Na.checked},function(){S.select()});else S.firePointEvent?S.firePointEvent(o,null,Q):na(S,o,null,Q)});U.push(S)})}});P&&za.reverse()}function s(Aa){if(Aa){X.clear();Ca(ca);ca=null}if(za.length){if(q.borderWidth||q.backgroundColor)X.drawRect(D.offsetLeft,
D.offsetTop,D.offsetWidth,D.offsetHeight,q.borderColor,q.borderWidth,q.borderRadius,q.backgroundColor,q.shadow);p(U,function(w){if(w.legendItem){var qa=w.legendItem,S=D.offsetLeft+qa.offsetLeft;qa=D.offsetTop+qa.offsetTop+qa.offsetHeight/2;var Na=w.legendItem.className==Ob,o=Na?q.itemHiddenStyle.color:w.color;!w.simpleSymbol&&w.options&&w.options.lineWidth&&X.drawLine(S,qa,S+xa,qa,o,w.options.lineWidth);if(w.simpleSymbol)X.drawRect(S,qa-6,16,12,null,0,2,o);else if(w.options&&w.options.marker&&w.options.marker.enabled)w.drawMarker(X,
S+xa/2,qa,aa(w.options.marker,Na?{fillColor:o,lineColor:o}:null))}});if(ib){ca=V("area",{shape:"rect",isLegendArea:true,coords:[D.offsetLeft-ga,D.offsetTop-I,D.offsetLeft+D.offsetWidth-ga,D.offsetTop+D.offsetHeight-I].join(",")});ub.insertAtFront(ca);ca.onmouseover=function(w){w=w||Pa.event;w=w.relatedTarget||w.fromElement;if(w!=D&&!Nb){Ab&&Ab.hide();ra(D,{zIndex:10})}};D.onmouseout=ca.onmouseout=function(w){w=w||Pa.event;if((w=w.relatedTarget||w.toElement)&&(w==dc||w.tagName=="AREA"&&w!=ca))ra(D,
{zIndex:7})}}}}var q=l.options.legend;if(q.enabled){var M,ea=q.layout,xa=q.symbolWidth,D,ia="#"+oa.id+" .highcharts-legend li",U=[],X=new pa("legend",oa,null,{zIndex:7}),ca,za=l.series,P=q.reversed;this.dom=D=V(Va,{className:"highcharts-legend highcharts-legend-"+ea,innerHTML:'<ul style="margin:0;padding:0"></ul>'},H({position:wa,zIndex:7},q.style),oa);Gb(ia,H(q.itemStyle,{paddingLeft:xa+q.symbolPadding+F,"float":ea=="horizontal"?"left":"none"}));Gb(ia+":hover",q.itemHoverStyle);Gb(ia+"."+Ob,q.itemHiddenStyle);
Gb(".highcharts-legend-horizontal li",{"float":"left"});h();s();return{renderHTML:h,drawGraphics:s}}};Pa.G_vmlCanvasManager&&Pa.G_vmlCanvasManager.init_(document);Zb=aa(Zb,Ba.xAxis);tc=aa(tc,Ba.yAxis);Ba.xAxis=Ba.yAxis=null;a=aa(Ba,a);var A=a.chart,T=A.margin;T=typeof T=="number"?[T,T,T,T]:T;var I=T[0],fb=T[1],cb=T[2],ga=T[3],Xa,rb,oa,qc,mb,Ga;C();var t=this;T=A.events;var zc,ib,Ab,Nb,Jc=new pa("chart-background",oa),vb,sc,ka,sa,ub,dc,Jb,lb=Hc(oa),Ub=A.showAxes,Ka=[],Cb,ya=[],Yb,Ea,yc,kb;fc=Bb=0;
Oa(Pa,"resize",i);Oa(Pa,"unload",La);if(T)for(zc in T)Oa(t,zc,T[zc]);t.addLoading=function(l){t.resources[l]=false};t.clearLoading=function(l){t.resources[l]=true;E()};t.options=a;t.series=ya;t.container=oa;t.resources={};t.inverted=Ea=a.chart.inverted;t.chartWidth=mb;t.chartHeight=Ga;t.plotWidth=sa=mb-ga-fb;t.plotHeight=ka=Ga-I-cb;t.plotLeft=ga;t.plotTop=I;t.redraw=c;t.addSeries=b;t.getSelectedPoints=r;t.getSelectedSeries=v;t.showLoading=e;t.hideLoading=f;t.get=g;t.destroy=La;t.updatePosition=i;
t.plotLayer=sc=new pa("plot",oa,null,{position:wa,width:sa+F,height:ka+F,left:ga+F,top:I+F,overflow:db,zIndex:3});if(A.plotBackgroundImage){t.addLoading("plotBack");Yb=V("img");Yb.onload=function(){t.clearLoading("plotBack")};Yb.src=A.plotBackgroundImage}p(a.series||[],function(l){d(l)});t.tracker=ub=new ob(t,a.tooltip);E()}function Tc(a){for(var b=[],c=[],d=0;d<a.length;d++){b[d]=a[d].plotX;c[d]=a[d].plotY}this.xdata=b;this.ydata=c;a=[];this.y2=[];var e=c.length;this.n=e;this.y2[0]=0;this.y2[e-1]=
0;a[0]=0;for(d=1;d<e-1;d++){var f=b[d+1]-b[d-1];f=(b[d]-b[d-1])/f;var g=f*this.y2[d-1]+2;this.y2[d]=(f-1)/g;a[d]=(c[d+1]-c[d])/(b[d+1]-b[d])-(c[d]-c[d-1])/(b[d]-b[d-1]);a[d]=(6*a[d]/(b[d+1]-b[d-1])-f*a[d-1])/g}for(b=e-2;b>=0;b--)this.y2[b]=this.y2[b]*this.y2[b+1]+a[b]}var ma,va=document,Pa=window,ta=Math,O=ta.round,Za=ta.floor,Lb=ta.max,Da=ta.abs,gc=ta.cos,hc=ta.sin,B=navigator.userAgent,Ra=/msie/i.test(B)&&!Pa.opera,cd=/AppleWebKit/.test(B),kc,bd=0,Bb,fc,Uc={},rc=0,Sa=1,Qb,Va="div",wa="absolute",
Xb="relative",db="hidden",Ob="highcharts-"+db,ec="visible",F="px",Tb,oc,mc,nc,Ib,Rb,Sb,Dc,Ec,pc,Fc,Gc,ua=(B=Pa.HighchartsAdapter)||{},p=ua.each,Wb=ua.grep,qb=ua.map,aa=ua.merge,Pb=ua.hyphenate,Oa=ua.addEvent,na=ua.fireEvent,Db=ua.animate,Ac=ua.getAjax,bb={};if(!B&&Pa.jQuery){var pb=jQuery;p=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};Wb=pb.grep;qb=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};aa=function(){var a=
arguments;return pb.extend(true,null,a[0],a[1],a[2],a[3])};Pb=function(a){return a.replace(/([A-Z])/g,function(b,c){return"-"+c.toLowerCase()})};Oa=function(a,b,c){pb(a).bind(b,c)};na=function(a,b,c,d){var e=pb.Event(b),f="detached"+b;H(e,c);if(a[b]){a[f]=a[b];a[b]=null}pb(a).trigger(e);if(a[f]){a[b]=a[f];a[f]=null}d&&!e.isDefaultPrevented()&&d(e)};Db=function(a,b,c){pb(a).animate(b,c)};Ac=function(a,b){pb.get(a,null,b)};pb.extend(pb.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}})}else if(!B&&
Pa.MooTools){p=$each;qb=function(a,b){return a.map(b)};Wb=function(a,b){return a.filter(b)};aa=$merge;Pb=function(a){return a.hyphenate()};Oa=function(a,b,c){if(!a.addEvent)if(a.nodeName)a=$(a);else H(a,new Events);a.addEvent(b,c)};na=function(a,b,c,d){b=new Event({type:b,target:a});b=H(b,c);b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)};Db=function(a,b,c){a=new Fx.Morph($(a),H(c,{transition:Fx.Transitions.Quad.easeInOut}));a.start(b)};Ac=function(a,b){(new Request({url:a,
method:"get",onSuccess:b})).send()}}B='normal 12px "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif';ua={enabled:true,align:"center",x:0,y:15,style:{color:"#666",font:B.replace("12px","11px")}};var Ba={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:{margin:[50,50,60,80],borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:true,plotBorderColor:"#C0C0C0"},title:{text:"Chart title",style:{textAlign:"center",color:"#3E576F",font:B.replace("12px","16px"),margin:"10px 0 0 0"}},subtitle:{text:"",
style:{textAlign:"center",color:"#6D869F",font:B,margin:0}},plotOptions:{line:{allowPointSelect:false,showCheckbox:false,animation:true,events:{},lineWidth:2,shadow:true,marker:{enabled:true,symbol:"auto",lineWidth:0,radius:4,lineColor:"#FFFFFF",fillColor:"auto",states:{hover:{},select:{fillColor:"#FFFFFF",lineColor:"auto",lineWidth:2}}},point:{events:{}},dataLabels:aa(ua,{enabled:false,y:-6,formatter:function(){return this.y}}),showInLegend:true,states:{hover:{lineWidth:3,marker:{}},select:{marker:{}}}}},
labels:{style:{position:wa,color:"#3E576F",font:B}},legend:{enabled:true,layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#909090",borderRadius:5,shadow:true,style:{bottom:"10px",left:"80px",padding:"5px"},itemStyle:{listStyle:"none",margin:0,padding:"0 2em 0 0",font:B,cursor:"pointer",color:"#3E576F",position:Xb},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:wa,right:0},symbolWidth:16,symbolPadding:5},loading:{hideDuration:100,
labelStyle:{font:B.replace("normal","bold"),position:Xb,top:"1em"},showDuration:100,style:{position:wa,backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:true,formatter:function(){var a=this,b=a.series,c=b.xAxis,d=a.x;return"<b>"+(a.point.name||b.name)+"</b><br/>"+(Qa(d)?"X value: "+(c&&c.options.type=="datetime"?lc("%Y-%m-%d %H:%M:%S",d):d)+"<br/>":"")+"Y value: "+a.y},backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,shadow:true,snap:10,style:{color:"#333333",
font:B,fontSize:"9pt",padding:"5px",whiteSpace:"nowrap"}},toolbar:{itemStyle:{color:"#4572A7",cursor:"pointer",margin:"20px",font:B}},credits:{enabled:true,text:"Highcharts.com",href:"http://www.highcharts.com",style:{position:wa,right:"10px",bottom:"5px",color:"#999",textDecoration:"none",font:B.replace("12px","10px")},target:"_self"}},Zb={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:ua,lineColor:"#C0D0E0",lineWidth:1,max:null,min:null,maxZoom:null,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",minorTickWidth:1,showFirstLabel:true,showLastLabel:false,startOfWeek:1,startOnTick:false,tickColor:"#C0D0E0",tickInterval:"auto",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{enabled:false,text:"X-values",align:"middle",margin:35,style:{color:"#6D869F",
font:B.replace("normal","bold")}},type:"linear"},tc=aa(Zb,{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:{enabled:true,margin:40,rotation:270,text:"Y-values"}}),$c={labels:{align:"right",x:-8,y:3},title:{rotation:270}},Zc={labels:{align:"left",x:8,y:3},title:{rotation:90}},Kc={labels:{align:"center",x:0,y:14},title:{rotation:0}},Yc=aa(Kc,{labels:{y:-5}});B=Ba.plotOptions;
ua=B.line;B.spline=aa(ua);B.scatter=aa(ua,{lineWidth:0,states:{hover:{lineWidth:0}}});B.area=aa(ua,{fillColor:"auto"});B.areaspline=aa(B.area);B.column=aa(ua,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,pointPadding:0.1,states:{hover:{brightness:0.1,shadow:false},select:{color:"#C0C0C0",borderColor:"#000000",shadow:false}}});B.bar=aa(B.column,{dataLabels:{align:"left",x:5,y:0}});B.pie=aa(ua,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],legendType:"point",size:"90%",
slicedOffset:10,states:{hover:{brightness:0.1,shadow:false}}});Cc();var Bc=function(a){function b(i){if(g=/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(i))f=[parseInt(g[1]),parseInt(g[2]),parseInt(g[3]),parseFloat(g[4])];else if(g=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(i))f=[parseInt(g[1],16),parseInt(g[2],16),parseInt(g[3],16),1]}function c(){return f&&!isNaN(f[0])?"rgba("+f.join(",")+")":a}function d(i){if(typeof i=="number"&&
i!=0)for(var k=0;k<3;k++){f[k]+=parseInt(i*255);if(f[k]<0)f[k]=0;if(f[k]>255)f[k]=255}return this}function e(i){f[3]=i;return this}var f=[],g;b(a);return{get:c,brighten:d,setOpacity:e}},pa=function(a,b,c,d){var e=this,f=b.style;c=H({className:"highcharts-"+a},c);d=H({width:f.width,height:f.height,position:wa,top:0,left:0,margin:0,padding:0,border:"none"},d);a=V(Va,c,d,b);H(e,{div:a,width:parseInt(d.width),height:parseInt(d.height)});e.svg=Ra?"":'<?xml version="1.0" encoding="utf-8"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="'+
e.width+'px" height="'+e.height+'">';e.basicSvg=e.svg};pa.prototype={getCtx:function(){if(!this.ctx){var a=V("canvas",{id:"highcharts-canvas-"+rc++,width:this.width,height:this.height},{position:wa},this.div);if(Ra){G_vmlCanvasManager.initElement(a);a=va.getElementById(a.id)}this.ctx=a.getContext("2d")}return this.ctx},getSvg:function(){if(!this.svgObject){var a=this,b=a.div,c=a.width;a=a.height;if(Ra){if(!va.namespaces.g_vml_){va.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml");va.createStyleSheet().cssText=
"g_vml_\\:*{behavior:url(#default#VML)}"}this.svgObject=V(Va,null,{width:c+F,height:a+F,position:wa},b)}else this.svgObject=V("object",{width:c,height:a,type:"image/svg+xml"},{position:wa,left:0,top:0},b)}return this.svgObject},drawLine:function(a,b,c,d,e,f){var g=this.getCtx();if(a==c)a=c=O(a)+f%2/2;if(b==d)b=d=O(b)+f%2/2;g.lineWidth=f;g.lineCap="round";g.beginPath();g.moveTo(a,b);g.strokeStyle=e;g.lineTo(c,d);g.closePath();g.stroke()},drawPolyLine:function(a,b,c,d,e){var f=this.getCtx(),g=[];if(d&&
c){p(a,function(i){g.push(i===ma?i:i+1)});for(d=1;d<=3;d++)this.drawPolyLine(g,"rgba(0, 0, 0, "+0.05*d+")",6-2*d)}f.beginPath();for(d=0;d<a.length;d+=2)f[d==0?"moveTo":"lineTo"](a[d],a[d+1]);H(f,{lineWidth:c,lineJoin:"round"});if(b&&c){f.strokeStyle=Hb(b,f);f.stroke()}if(e){f.fillStyle=Hb(e,f);f.fill()}},drawRect:function(a,b,c,d,e,f,g,i,k,j){var r=function(){var R;if(c>0&&d>0){v.beginPath();if(g){v.moveTo(a,b+g);v.lineTo(a,b+d-g);v.quadraticCurveTo(a,b+d,a+g,b+d);v.lineTo(a+c-g,b+d);v.quadraticCurveTo(a+
c,b+d,a+c,b+d-g);v.lineTo(a+c,b+g);v.quadraticCurveTo(a+c,b,a+c-g,b);v.lineTo(a+g,b);v.quadraticCurveTo(a,b,a,b+g)}else v.rect(a,b,c,d);v.closePath();R=true}return R},v=this.getCtx(),y=(f||0)%2/2;a=O(a)+y;b=O(b)+y;c=O(c-2*y);d=O(d-2*y);if(k)for(k=1;k<=3;k++)this.drawRect(a+1,b+1,c,d,"rgba(0, 0, 0, "+0.05*k+")",6-2*k,g);j&&v.drawImage(j,a,b,c,d);if(r()){if(i){v.fillStyle=Hb(i,v);v.fill();Pa.G_vmlCanvasManager&&r()}if(f){v.strokeStyle=Hb(e,v);v.lineWidth=f;v.stroke()}}},drawSymbol:function(a,b,c,d,
e,f,g){var i=this.getCtx(),k=/^url\((.*?)\)$/;i.beginPath();if(a=="square"){a=0.707*d;i.moveTo(b-a,c-a);i.lineTo(b+a,c-a);i.lineTo(b+a,c+a);i.lineTo(b-a,c+a);i.lineTo(b-a,c-a)}else if(a=="triangle"){c++;i.moveTo(b,c-1.33*d);i.lineTo(b+d,c+0.67*d);i.lineTo(b-d,c+0.67*d);i.lineTo(b,c-1.33*d)}else if(a=="triangle-down"){c--;i.moveTo(b,c+1.33*d);i.lineTo(b-d,c-0.67*d);i.lineTo(b+d,c-0.67*d);i.lineTo(b,c+1.33*d)}else if(a=="diamond"){i.moveTo(b,c-d);i.lineTo(b+d,c);i.lineTo(b,c+d);i.lineTo(b-d,c);i.lineTo(b,
c-d)}else k.test(a)?V("img",{onload:function(){var j=this,r=Uc[j.src]||[j.width,j.height];ra(j,{left:O(b-r[0]/2)+F,top:O(c-r[1]/2)+F,visibility:ec});Uc[j.src]=r},src:a.match(k)[1]},{position:wa,visibility:Ra?ec:db},this.div):i.arc(b,c,d,0,2*ta.PI,true);if(g){i.fillStyle=g;i.fill()}if(f&&e){i.strokeStyle=f||"rgb(100, 100, 255)";i.lineWidth=e||2;i.stroke()}},drawHtml:function(a,b,c){V(Va,H(b,{innerHTML:a}),H(c,{position:wa}),this.div)},drawText:function(){this.addText.apply(this,arguments);this.strokeText()},
addText:function(a,b,c,d,e,f){if(a||a===0){var g=this,i,k=g.div,j,r="";d=d||{};var v=d.color||"#000000";f=f||"left";var y=parseInt(d.fontSize||d.font.replace(/^[a-z ]+/,""));for(var R in d)r+=Pb(R)+":"+d[R]+";";p(["MozTransform","WebkitTransform","transform"],function(Wa){if(Wa in k.style)j=Wa});if(!e||j){a=V("span",{innerHTML:a},H(d,{position:wa,left:b+F,whiteSpace:"nowrap",bottom:O(g.height-c-y*0.25)+F,color:v}),k);r=a.offsetWidth;if(f=="right")ra(a,{left:b-r+F});else f=="center"&&ra(a,{left:O(b-
r/2)+F});if(e){f={left:0,center:50,right:100}[f];a.style[j]="rotate("+e+"deg)";a.style[j+"Origin"]=f+"% 100%"}}else if(Ra){i=true;d=(e||0)*ta.PI*2/360;e=gc(d);d=hc(d);R=g.width;y=y/3||3;var E=f=="left",K=f=="right",C=E?b:b-R*e;b=K?b:b+R*e;E=E?c:c-R*d;c=K?c:c+R*d;C+=y*d;b+=y*d;E-=y*e;c-=y*e;if(Da(C-b)<0.1)C+=0.1;if(Da(E-c)<0.1)E+=0.1;g.svg+='<g_vml_:line from="'+C+", "+E+'" to="'+b+", "+c+'" stroked="false"><g_vml_:fill on="true" color="'+v+'"/><g_vml_:path textpathok="true"/><g_vml_:textpath on="true" string="'+
a+'" style="v-text-align:'+f+";"+r+'"/></g_vml_:line>'}else{i=true;g.svg+='<g><text transform="translate('+b+","+c+") rotate("+(e||0)+')" style="fill:'+v+";text-anchor:"+{left:"start",center:"middle",right:"end"}[f]+";"+r.replace(/"/g,"'")+'">'+a+"</text></g>"}g.hasObject=i}},strokeText:function(){if(this.hasObject){var a=this.getSvg(),b=this.svg;if(Ra)a.innerHTML=b;else{a.data="data:image/svg+xml,"+b+"</svg>";cd&&this.div.appendChild(a)}}},clear:function(){var a=this,b=this.div;b=b.childNodes;a.ctx&&
a.ctx.clearRect(0,0,a.width,a.height);if(a.svgObject){Ca(a.svgObject);a.svgObject=null;a.svg=a.basicSvg}for(var c=b.length-1;c>=0;c--){a=b[c];/(SPAN|IMG)/.test(a.tagName)&&Ca(a)}},hide:function(){ra(this.div,{display:"none"})},show:function(){ra(this.div,{display:""})},destroy:function(){Ca(this.div);return null}};var ic=function(){};ic.prototype={init:function(a,b){var c=this;c.series=a;c.applyOptions(b);return c},applyOptions:function(a){var b=this,c=b.series;if(typeof a=="number"||a===null)b.y=
a;else if(typeof a=="object"&&typeof a.length!="number"){H(b,a);b.options=a}else if(typeof a[0]=="string"){b.name=a[0];b.y=a[1]}else if(typeof a[0]=="number"){b.x=a[0];b.y=a[1]}if(b.x===ma)b.x=c.autoIncrement()},destroy:function(){var a=this;a.stateLayer&&a.stateLayer.destroy();for(prop in a)a[prop]=null},select:function(a,b){var c=this,d=c.series,e=d.chart,f,g,i=da(c.stateLayer,d.singlePointLayer,e.singlePointLayer);c.selected=a=da(a,!c.selected);d.isDirty=true;c.firePointEvent(a?"select":"unselect");
i&&i.clear();p(e.series,function(k){f=k.stateLayers;b||p(k.data,function(j){if(j.selected&&j!=c){j.selected=false;na(j,"unselect");k.isDirty=true}});if(k.isDirty){for(g in f)f[g].clear();k.render()}})},update:function(a,b){var c=this,d=c.series;b=da(b,true);c.firePointEvent("update",{options:a},function(){c.applyOptions(a);d.isDirty=true;b&&d.chart.redraw()})},remove:function(a){var b=this,c=b.series,d=c.chart,e=c.data;a=da(a,true);b.firePointEvent("remove",null,function(){p(e,function(f,g){f==b&&
e.splice(g,1)});if(b.layer)b.layer=b.layer.destroy();if(b.legendItem){Ca(b.legendItem);b.legendItem=null;d.isDirty=true}c.isDirty=true;a&&d.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series;e=e.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)};na(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=this,b=aa(a.series.options.point,
a.options);b=b.events;var c;a.events=b;for(c in b)Oa(a,c,b[c]);this.hasImportedEvents=true}},setTooltipText:function(){var a=this;a.tooltipText=a.series.chart.options.tooltip.formatter.call({series:a.series,point:a,x:a.category,y:a.y,percentage:a.percentage,total:a.stackTotal})}};var Ja=function(){this.isCartesian=true;this.type="line";this.pointClass=ic};Ja.prototype={init:function(a,b){var c=this,d,e=a.series.length;c.chart=a;b=c.setOptions(b);H(c,{index:e,options:b,name:b.name||"Series "+(e+1),
state:"",visible:b.visible!==false,selected:b.selected==true});a=b.events;for(d in a)Oa(c,d,a[d]);c.getColor();c.getSymbol();c.getData(b)},getData:function(a){var b=this,c=b.chart,d="series"+rc++;if(!a.data&&a.dataURL){c.addLoading(d);Ac(a.dataURL,function(e){b.dataLoaded(e);c.clearLoading(d)})}else b.dataLoaded(a.data)},dataLoaded:function(a){var b=this,c=b.chart,d=b.options,e=[""],f=d.dataParser,g={},i;if(d.dataURL&&!f)f=function(k){return eval(k)};if(f)a=f.call(b,a);b.layerGroup=i=new pa("series-group",
c.plotLayer.div,null,{zIndex:2});d.states.hover.enabled&&e.push("hover");p(e,function(k){g[k]=new pa("state-"+k,i.div)});b.stateLayers=g;b.setData(a,false)},autoIncrement:function(){var a=this,b=a.options,c=a.xIncrement;c=da(c,b.pointStart,0);a.pointInterval=da(a.pointInterval,b.pointInterval,1);a.xIncrement=c+a.pointInterval;return c},cleanData:function(){var a=this;a=a.data;var b;a.sort(function(c,d){return c.x-d.x});for(b=a.length-1;b>=0;b--)a[b-1]&&a[b-1].x==a[b].x&&a.splice(b-1,1)},getSegments:function(){var a=
-1,b=[],c=this.data;p(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;a=aa(b[this.type],b.series,a);b=a.marker;var c=a.states.hover.marker;if(c.lineWidth===ma)c.lineWidth=b.lineWidth+1;if(c.radius===ma)c.radius=b.radius+1;return a},getColor:function(){var a=this.chart.options.colors;this.color=this.options.color||a[Bb++]||"#0000ff";if(Bb>=a.length)Bb=0},getSymbol:function(){var a=
this.chart.options.symbols,b=this.options.marker.symbol||"auto";if(b=="auto")b=a[fc++];this.symbol=b;if(fc>=a.length)fc=0},addPoint:function(a,b,c){var d=this,e=d.data;a=(new d.pointClass).init(d,a);b=da(b,true);e.push(a);c&&e.shift();d.isDirty=true;b&&d.chart.redraw()},setData:function(a,b){var c=this;c.xIncrement=null;a=qb(jc(a),function(d){return(new c.pointClass).init(c,d)});c.data=a;c.cleanData();c.getSegments();c.isDirty=true;da(b,true)&&c.chart.redraw()},remove:function(a){var b=this,c=b.chart;
a=da(a,true);if(!b.isRemoving){b.isRemoving=true;na(b,"remove",null,function(){Ca(b.layerGroup.div);p(b.areas,function(d){Ca(d)});Ca(b.legendItem);b.legendItem=null;p(c.series,function(d,e){d==b&&c.series.splice(e,1)});c.isDirty=true;a&&c.redraw()})}b.isRemoving=false},translate:function(){var a=this.chart,b=this,c=b.options.stacking,d=b.xAxis.categories,e=b.yAxis,f=e.stacks[b.type];p(this.data,function(g){var i=g.x,k=g.y,j;g.plotX=b.xAxis.translate(g.x);if(c&&b.visible&&f[i]){j=f[i];i=j.total;j.cum=
j=j.cum-k;k=j+k;if(c=="percent"){j=i?j*100/i:0;k=i?k*100/i:0}g.percentage=i?g.y*100/i:0;g.stackTotal=i;g.yBottom=e.translate(j,0,1)}if(k!==null)g.plotY=e.translate(k,0,1);g.clientX=a.inverted?a.plotHeight-g.plotX+a.plotTop:g.plotX+a.plotLeft;g.category=d&&d[g.x]!==ma?d[g.x]:g.x})},setTooltipPoints:function(a){var b=this,c=b.chart,d=c.inverted,e=[],f=d?c.plotHeight:c.plotWidth,g,i,k=[];if(a)b.tooltipPoints=null;p(b.segments,function(j){e=e.concat(j)});if(b.xAxis.reversed)e=e.reverse();p(e,function(j,
r){b.tooltipPoints||j.setTooltipText();g=e[r-1]?e[r-1].high+1:0;for(i=j.high=e[r+1]?Za((j.plotX+(e[r+1]?e[r+1].plotX:f))/2):f;g<=i;)k[d?f-g++:g++]=j});b.tooltipPoints=k},drawLine:function(a){var b,c=this,d=c.options,e=c.chart,f=d.animation&&c.animate,g=c.stateLayers[a],i=d.lineColor||c.color,k=d.fillColor=="auto"?Bc(c.color).setOpacity(d.fillOpacity||0.75).get():d.fillColor,j=e.inverted,r=(j?0:e.plotHeight)-c.yAxis.translate(0);if(a)d=aa(d,d.states[a]);f&&c.animate(true);p(c.segments,function(v){var y=
[],R=[];p(v,function(E,K){if(K&&d.step){K=v[K-1];y.push(j?e.plotWidth-K.plotY:E.plotX,j?e.plotHeight-E.plotX:K.plotY)}y.push(j?e.plotWidth-E.plotY:E.plotX,j?e.plotHeight-E.plotX:E.plotY)});if(/area/.test(c.type)){for(b=0;b<y.length;b++)R.push(y[b]);if(d.stacking&&c.type!="areaspline")for(b=v.length-1;b>=0;b--)R.push(v[b].plotX,v[b].yBottom);else R.push(j?r:v[v.length-1].plotX,j?e.plotHeight-v[v.length-1].plotX:r,j?r:v[0].plotX,j?e.plotHeight-v[0].plotX:r);g.drawPolyLine(R,null,null,d.shadow,k)}d.lineWidth&&
g.drawPolyLine(y,i,d.lineWidth,d.shadow)});f&&c.animate()},animate:function(a){var b=this,c=b.chart,d=c.inverted,e=b.layerGroup.div;if(b.visible)if(a)ra(e,H({overflow:db},d?{height:0}:{width:0}));else{Db(e,d?{height:c.plotHeight+F}:{width:c.plotWidth+F},{duration:1E3});this.animate=null}},drawPoints:function(a){var b=this,c=b.stateLayers[a];a=b.options;var d=a.marker;a=b.data;var e=b.chart,f=e.inverted;d.enabled&&p(a,function(g){if(g.plotY!==ma)b.drawMarker(c,f?e.plotWidth-g.plotY:g.plotX,f?e.plotHeight-
g.plotX:g.plotY,aa(d,g.marker));g.selected&&b.drawPointState(g,"select",c)})},drawMarker:function(a,b,c,d){if(d.lineColor=="auto")d.lineColor=this.color;if(d.fillColor=="auto")d.fillColor=this.color;if(d.symbol=="auto")d.symbol=this.symbol;a.drawSymbol(d.symbol,b,c,d.radius,d.lineWidth,d.lineColor,d.fillColor)},drawDataLabels:function(){if(this.options.dataLabels.enabled){var a=this,b,c,d=a.data,e=a.options.dataLabels,f,g=a.dataLabelsLayer,i=a.chart,k=i.inverted,j=a.type,r=j=="pie",v;if(g)g.clear();
else a.dataLabelsLayer=g=new pa("data-labels",a.layerGroup.div,null,{zIndex:1});e.style.color=e.color=="auto"?a.color:e.color;p(d,function(y){var R=y.plotX,E=y.plotY,K=y.tooltipPos;f=e.formatter.call({x:y.x,y:y.y,series:a,point:y});b=(k?i.plotWidth-E:R)+e.x;c=(k?i.plotHeight-R:E)+e.y;if(K){b=K[0]+e.x;c=K[1]+e.y}if(r){if(!y.dataLabelsLayer)y.dataLabelsLayer=new pa("data-labels",y.layer.div,null,{zIndex:3});g=y.dataLabelsLayer}v=e.align;if(j=="column")b+={center:y.w/2,right:y.w}[v]||0;if(f)g[r?"drawText":
"addText"](f,b,c,e.style,e.rotation,v)});r||g.strokeText()}},drawPointState:function(a,b,c){var d=this.chart,e=d.inverted,f=b=="hover";c=c||d.singlePointLayer;var g=this.options;if(f){if(!c)c=d.singlePointLayer=new pa("single-point",d.plotLayer.div,null,{zIndex:3});c.clear()}if(b){var i=g.states[b].marker;b=g.marker.states[b];if(f&&b.radius===ma)b.radius=i.radius+2;if((f=aa(g.marker,a.marker,i,b))&&f.enabled)this.drawMarker(c,e?d.plotWidth-a.plotY:a.plotX,e?d.plotHeight-a.plotX:a.plotY,f)}},destroy:function(){var a=
this,b;p(a.data,function(c){c.destroy()});for(b in a)a[b]=null},render:function(){var a=this,b,c=a.stateLayers;a.drawDataLabels();if(a.visible)for(b in c){a.drawLine(b);a.drawPoints(b)}else a.setVisible(false,false);if(!a.hasRendered&&c.hover){c.hover.hide();hasRendered=true}a.isDirty=false},redraw:function(){var a=this;a.translate();a.setTooltipPoints(true);a.createArea();a.clear();a.render()},clear:function(){var a=this.stateLayers;for(var b in a){a[b].clear();a[b].cleared=true}if(this.dataLabelsLayer){this.dataLabelsLayer.clear();
this.hasDrawnDataLabels=false}},setState:function(a){a=a||"";if(this.state!=a){var b=this,c=b.stateLayers,d=c[a];c=c[b.state];var e=b.singlePointLayer||b.chart.singlePointLayer;b.state=a;if(d)if(a)d.show();else{c&&c.hide();e&&e.clear()}}},setVisible:function(a,b){var c=this,d=c.chart,e=c.layerGroup,f=c.legendItem,g=c.areas,i=c.visible;if(c.visible=a=a===ma?!i:a){c.isDirty=true;e.show()}else e.hide();if(f){f.className=a?"":Ob;d.legend.drawGraphics(true)}g&&p(g,function(k){a?d.tracker.insertAtFront(k):
Ca(k)});d.options.chart.ignoreHiddenSeries&&c.options.stacking&&p(d.series,function(k){if(k.options.stacking&&k.visible)k.isDirty=true});b!==false&&d.redraw();na(c,a?"show":"hide")},show:function(){this.setVisible(true)},hide:function(){this.setVisible(false)},select:function(a){var b=this;b.selected=a=a===ma?!b.selected:a;if(b.checkbox)b.checkbox.checked=a;na(b,a?"select":"unselect")},getAreaCoords:function(){var a=this,b=this.chart,c=b.inverted,d=b.plotWidth,e=b.plotHeight,f=a.xAxis.reversed,g,
i=b.options.tooltip.snap,k=[];p(a.splinedata||a.segments,function(j,r){if((g=j.length>1&&j[0].x>j[1].x)&&!f||f&&!g)j=j.reverse();var v=[],y=[],R=[];p([y,R],function(E){for(var K=0,C=0,Wa,La,Fa=[j[0]],Kb=E==y?1:-1,ob,jb,nb,A,T,I,fb;j[C];){if(j[C].plotX>j[K].plotX+i||C==j.length-1){Wa=j[C];La=j.slice(K,C-1);p(La,function(cb){if(Kb*cb.plotY<Kb*Wa.plotY)Wa=cb});if(O(j[K].plotX)<O(Wa.plotX)||j[C].plotX>j[K].plotX+i)Fa.push(Wa);K=C}C++}Fa[Fa.length-1]!=j[j.length-1]&&Fa.push(j[j.length-1]);for(C=0;C<Fa.length;C++)if(C>
0){jb=Fa[C].plotX;ob=Fa[C].plotY;K=Fa[C-1].plotX;La=Fa[C-1].plotY;A=jb-Fa[C-1].plotX;I=T=ob-Fa[C-1].plotY;nb=-A;fb=ta.sqrt(ta.pow(I,2)+ta.pow(nb,2));if(C==1){K-=i/fb*A;La-=i/fb*T}else if(C==Fa.length-1){jb+=i/fb*A;ob+=i/fb*T}A=Kb*i/fb;K=O(K+A*I);La=O(La+A*nb);jb=O(jb+A*I);nb=O(ob+A*nb);if(E[E.length-1]&&E[E.length-1][0]>K)for(ob=false;!ob;){T=E.pop();I=E[E.length-1];if(!I)break;A=(La-nb)/(K-jb);T=(I[1]-T[1])/(I[0]-T[0]);T=(-T*I[0]+I[1]+A*K-La)/(A-T);A=A*(T-K)+La;if(T>I[0]){E.push([O(T),O(A),1]);ob=
true}}else isNaN(K)||E.push([K,La]);E[E.length-1]&&E[E.length-1][0]<jb&&E.push([jb,nb])}});for(r=0;r<y.length;r++)v.push(c?d-y[r][1]:y[r][0],c?e-y[r][0]:y[r][1]);for(r=R.length-1;r>=0;r--)v.push(c?d-R[r][1]:R[r][0],c?e-R[r][0]:R[r][1]);v.length||v.push(O(j[0].plotX),O(j[0].plotY));v.length&&k.push([v.join(",")])});return k},createArea:function(){if(this.options.enableMouseTracking!==false){var a,b=this,c=b.options,d=b.chart,e=d.tracker,f=b.getAreaCoords(),g=[],i=b.areas,k;i&&p(i,function(j){Ca(j)});
p(f,function(j){k=/^[0-9]+,[0-9]+$/.test(j[0]);a=V("area",{shape:k?"circle":"poly",chart:d,coords:j[0]+(k?","+d.options.tooltip.snap:""),onmouseover:function(){if(!(!b.visible||d.mouseIsDown)){var r=d.hoverSeries;d.hoverPoint=j[1];c.events.mouseOver&&na(b,"mouseOver",{point:d.hoverPoint});r&&r!=b&&r.setState();/(column|bar|pie)/.test(b.type)||e.insertAtFront(a);b.setState("hover");d.hoverSeries=b}},onmouseout:function(){var r=d.hoverSeries;r&&c.events.mouseOut&&na(r,"mouseOut")}});if(c.cursor=="pointer")a.href=
"javascript:;";e.insertAtFront(a);g.push(a)});b.areas=g}}};B=ab(Ja);bb.line=B;B=ab(Ja,{type:"area"});bb.area=B;B=ab(Ja,{type:"spline",translate:function(){var a=this;Ja.prototype.translate.apply(a,arguments);a.splinedata=a.getSplineData()},drawLine:function(){var a=this,b=a.segments;a.segments=a.splinedata;Ja.prototype.drawLine.apply(a,arguments);a.segments=b},getSplineData:function(){var a=this,b=a.chart,c=[],d;p(a.segments,function(e){if(a.xAxis.reversed)e=e.reverse();var f=[],g,i;p(e,function(k,
j){g=e[j+2]||e[j+1]||k;i=e[j-2]||e[j-1]||k;g.plotX>0&&i.plotY<b.plotWidth&&f.push(k)});if(f.length>1)d=O(Lb(b.plotWidth,f[f.length-1].clientX-f[0].clientX)/3);c.push(e.length>1?d?(new Tc(f)).get(d):[]:e)});return a.splinedata=c}});bb.spline=B;Tc.prototype={get:function(a){a||(a=50);var b=this.n;b=(this.xdata[b-1]-this.xdata[0])/(a-1);var c=[],d=[];c[0]=this.xdata[0];d[0]=this.ydata[0];for(var e=[{plotX:c[0],plotY:d[0]}],f=1;f<a;f++){c[f]=c[0]+f*b;d[f]=this.interpolate(c[f]);e[f]={plotX:c[f],plotY:d[f]}}return e},
interpolate:function(a){for(var b=this.n-1,c=0;b-c>1;){var d=(b+c)/2;if(this.xdata[Za(d)]>a)b=d;else c=d}b=Za(b);c=Za(c);d=this.xdata[b]-this.xdata[c];var e=(this.xdata[b]-a)/d;a=(a-this.xdata[c])/d;return e*this.ydata[c]+a*this.ydata[b]+((e*e*e-e)*this.y2[c]+(a*a*a-a)*this.y2[b])*d*d/6}};B=ab(B,{type:"areaspline"});bb.areaspline=B;var Vb=ab(Ja,{type:"column",init:function(){Ja.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&p(b.series,function(c){if(c.type==a.type)c.isDirty=
true})},translate:function(){var a=this,b=a.chart,c=0,d;Ja.prototype.translate.apply(a);p(b.series,function(C){if(C.type==a.type)if(C.options.stacking){Qa(d)||(d=c++);C.columnIndex=d}else C.columnIndex=c++});var e=a.options,f=a.data,g=b.inverted,i=b.plotWidth,k=b.plotHeight,j=a.closestPoints;j=Da(f[1]?f[j].plotX-f[j-1].plotX:g?k:i);var r=j*e.groupPadding,v=j-2*r;v=v/c;var y=e.pointWidth;e=Qa(y)?(v-y)/2:v*e.pointPadding;var R=da(y,v-2*e);b=(b.options.xAxis.reversed?c-a.columnIndex:a.columnIndex)||
0;var E=-(j/2)+r+b*v+e,K=a.yAxis.translate(0);p(f,function(C){C.plotX+=E;C.w=R;C.y0=(g?i:k)-K;C.h=(C.yBottom||C.y0)-C.plotY})},drawLine:function(){},getSymbol:function(){},drawPoints:function(a){var b=this,c=b.options,d=b.chart,e=c.animation&&b.animate,f=d.inverted,g=b.data,i=b.stateLayers[a];e&&this.animate(true);p(g,function(k){if(k.plotY!==ma)i.drawRect(f?k.h>=0?d.plotWidth-k.plotY-k.h:d.plotWidth-k.plotY:k.plotX,f?d.plotHeight-k.plotX-k.w:k.h>=0?k.plotY:k.plotY+k.h,f?Da(k.h):k.w,f?k.w:Da(k.h),
c.borderColor,c.borderWidth,c.borderRadius,k.color||b.color,c.shadow);k.selected&&b.drawPointState(k,"select",i)});e&&b.animate()},drawPointState:function(a,b,c){var d=this,e=d.chart,f=d.options,g=a?a.options:null,i=e.inverted;c=c||d.singlePointLayer;if(b=="hover"){if(!c)c=d.singlePointLayer=new pa("single-point",d.layerGroup.div);c.clear()}if(b&&this.options.states[b]){b=aa(f,f.states[b],g);c.drawRect(i?e.plotWidth-a.plotY-a.h:a.plotX,i?e.plotHeight-a.plotX-a.w:a.plotY,i?a.h:a.w,i?a.w:a.h,b.borderColor,
b.borderWidth,b.borderRadius,Bc(b.color||this.color).brighten(b.brightness).get(),b.shadow)}},getAreaCoords:function(){var a=[],b=this.chart,c=b.inverted;p(this.data,function(d){var e=Lb(Da(d.h),3)*(d.h<0?-1:1),f=c?b.plotWidth-d.plotY-e:d.plotX,g=c?b.plotHeight-d.plotX-d.w:d.plotY,i=g+(c?d.w:e);e=f+(c?e:d.w);if(!c&&Da(e-f)<1)e=f+1;else if(c&&Da(g-i)<1)g=i+1;a.push([qb([f,i,f,g,e,g,e,i],O).join(","),d])});return a},cleanData:function(){var a=this,b=a.data,c,d,e,f;Ja.prototype.cleanData.apply(a);for(f=
b.length-1;f>=0;f--)if(b[f-1]){c=b[f].x-b[f-1].x;if(d===ma||c<d){d=c;e=f}}a.closestPoints=e},animate:function(a){var b=this,c=b.chart,d=c.inverted,e=b.layerGroup.div;if(a)e.style[d?"left":"top"]=(d?-c.plotWidth:c.plotHeight)+F;else{Db(e,c.inverted?{left:0}:{top:0});b.animate=null}},remove:function(){var a=this,b=a.chart;b.hasRendered&&p(b.series,function(c){if(c.type==a.type)c.isDirty=true});Ja.prototype.remove.apply(a,arguments)}});bb.column=Vb;var Ic=ab(Vb,{type:"bar",init:function(a){a.inverted=
this.inverted=true;Vb.prototype.init.apply(this,arguments)}});bb.bar=Ic;B=ab(Ja,{type:"scatter",getAreaCoords:function(){var a=this.data,b=[];p(a,function(c){b.push([[O(c.plotX),O(c.plotY)].join(","),c])});return b},cleanData:function(){}});bb.scatter=B;B=ab(ic,{setState:function(a){this.series.drawPointState(this,a)},init:function(){ic.prototype.init.apply(this,arguments);var a=this,b=a.series,c=b.chart.options.colors;H(a,{visible:a.visible!==false,name:da(a.name,"Slice"),color:a.color||c[Bb++]});
if(Bb>=c.length)Bb=0;if(!a.layer)a.layer=new pa("pie",b.layerGroup.div);b=function(){a.slice()};Oa(a,"select",b);Oa(a,"unselect",b);return a},setVisible:function(a){var b=this,c=b.layer,d=b.legendItem;(b.visible=a=a===ma?!b.visible:a)?c.show():c.hide();if(d){d.className=a?"":Ob;b.series.chart.legend.drawGraphics(true)}},slice:function(a,b){var c=this,d=c.series;b=da(b,true);c.sliced=Qa(a)?a:!c.sliced;d.isDirty=true;b&&d.chart.redraw()}});B=ab(Ja,{type:"pie",isCartesian:false,pointClass:B,getColor:function(){},
translate:function(){var a=0,b=this,c=-0.25,d=b.options,e=d.slicedOffset,f=d.center,g=b.chart;b=b.data;var i=2*ta.PI,k;f.push(d.size);f=qb(f,function(j,r){return/%$/.test(j)?g["plot"+(r?"Height":"Width")]*parseInt(j)/100:j});p(b,function(j){a+=j.y});p(b,function(j){k=a?j.y/a:0;j.start=c*i;c+=k;j.end=c*i;j.percentage=k*100;j.center=[f[0],f[1]];j.size=f[2];var r=(j.end+j.start)/2;j.centerSliced=qb([gc(r)*e+f[0],hc(r)*e+f[1]],O)});this.setTooltipPoints()},render:function(){this.drawPoints();this.drawDataLabels()},
drawPoints:function(){var a=this;p(this.data,function(b){a.drawPoint(b,b.layer.getCtx(),b.color);b.visible===false&&b.setVisible(false);b.selected&&a.drawPointState(b,"select",b.layer)})},getSymbol:function(){},drawPointState:function(a,b,c){var d=this,e=d.options;if(a){c=c||a.stateLayer;if(b=="hover"){if(!c)c=a.stateLayer=new pa("single-point",a.layer.div);c.clear()}if(b&&d.options.states[b]){b=aa(e,e.states[b]);this.drawPoint(a,c.getCtx(),b.color||a.color,b.brightness)}}d.hoverPoint&&d.hoverPoint.stateLayer&&
d.hoverPoint.stateLayer.clear();d.hoverPoint=a},drawPoint:function(a,b,c,d){var e=this.options,f=a.sliced?a.centerSliced:a.center,g=f[0];f=f[1];var i=a.size,k=e.borderWidth,j=Ra&&a.percentage==100?a.start:a.end;if(a.y>0){b.fillStyle=Hb(Bc(c).brighten(d).get(b),b);b.strokeStyle=e.borderColor;b.lineWidth=k;b.beginPath();b.moveTo(g,f);b.arc(g,f,i/2,a.start,j,false);b.lineTo(g,f);b.closePath();b.fill();k&&b.stroke()}},getAreaCoords:function(){var a=[];p(this.data,function(b){for(var c=b.center[0],d=b.center[1],
e=b.size/2,f=b.start,g=b.end,i=[],k=f;k;k+=0.25){if(k>=g)k=g;i=i.concat([c+gc(k)*e,d+hc(k)*e]);if(k>=g)break}i=i.concat([c,d]);b.tooltipPos=[c+2*gc((f+g)/2)*e/3,d+2*hc((f+g)/2)*e/3];a.push([qb(i,O).join(","),b])});return a},setData:function(){var a=this,b=a.data,c;if(b)for(c=b.length-1;c>=0;c--)b[c].remove();Ja.prototype.setData.apply(a,arguments)},clear:function(){p(this.data,function(a){a.layer.clear();a.dataLabelsLayer&&a.dataLabelsLayer.clear();a.stateLayer&&a.stateLayer.clear()})}});bb.pie=B;
Highcharts={numberFormat:Wc,dateFormat:lc,defaultOptions:Ba,setOptions:Vc,Chart:Xc,extendClass:ab,seriesTypes:bb,Layer:pa}})();


// Global namespace for Inkling
var Ink = {
  
  relative_url: function(url) {
    if (Ink.relative_url_root == null || jQuery.trim(url).indexOf('http') == 0) {
      return url;
    };
    
    return Ink.relative_url_root + url;
  },
  
  like: function(source_type, source_id, like_link) {
    var container = jQuery(like_link).parent('.like_container');
    jQuery.ajax({
      type: 'POST',
      url: Ink.relative_url('/likes'),
      data: { source_type: source_type, source_id: source_id },
      beforeSend: function() { jQuery(like_link).replaceWith('<em class="who_likes_this">Saving...</em>'); },
      success: function(data) { container.html(data); }
    });
  }
  
};

String.prototype.wordWrap = function(m, b, c){
    var i, j, s, r = this.split("\n");
    if(m > 0) for(i in r){
        for(s = r[i], r[i] = ""; s.length > m;
            j = c ? m : (j = s.substr(0, m).match(/\S*$/)).input.length - j[0].length
            || m,
            r[i] += s.substr(0, j) + ((s = s.substr(j)).length ? b : "")
        );
        r[i] += s;
    }
    return r.join("\n");
};


function gup( name )
{
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var tmpURL = window.location.href;
  var results = regex.exec( tmpURL );
  if( results == null )
    return "";
  else
    return unescape(results[1]);
}

var Cookie = {
  set: function(name, value, daysToExpire) {
    var expire = '';
    if (daysToExpire != undefined) {
      var d = new Date();
      d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
      expire = '; expires=' + d.toGMTString();
    }
    return (document.cookie = escape(name) + '=' + escape(value || '') + expire);
  },
  get: function(name) {
    var cookie = document.cookie.match(new RegExp('(^|;)\\s*' + escape(name) + '=([^;\\s]*)'));
    return (cookie ? unescape(cookie[2]) : null);
  },
  erase: function(name) {
    var cookie = Cookie.get(name) || true;
    Cookie.set(name, '', -1);
    return cookie;
  },
  accept: function() {
    if (typeof navigator.cookieEnabled == 'boolean') {
      return navigator.cookieEnabled;
    }
    Cookie.set('_test', '1');
    return (Cookie.erase('_test') === '1');
  }
};

function checkAll(checkname, exby) {
  for (i = 0; i < checkname.length; i++)
  checkname[i].checked = exby.checked? true:false
}

function OpenWindow(strURL,strWidth,strHeight)
{
    /* open a new browser window based on info passed to the function */
    window.open(strURL,"","Width=" + strWidth + ",Height=" + strHeight + ",scrollbars=1",0);
}

var flashMovie;
var Events = { 
  highlight: function(event_id) {
    // clear the old events
    $$('div.headlines').each(function(entry) {
          entry.setStyle({backgroundColor: 'white'})
        }); 
      
    $(event_id).setStyle({backgroundColor: 'grey'});
    // alert('hi');
  },
  showAll: function(){
    if (flashMovie) {      
        flashMovie.showAll(); 
     }
  }, 
  setZoom: function(event_id, from, to){
    if (flashMovie) {
      flashMovie.setZoom(from, to);
    }
    Events.highlight(event_id);
  }
};

function amChartInited(chart_id) {
  flashMovie = document.getElementById("amstock");
}

function resizeArea(t) {
  a = t.value.split('\n');
  b=1;
  for (x=0;x < a.length; x++) {
   if (a[x].length >= t.cols) b+= Math.floor(a[x].length/t.cols);
   }
  b+= a.length;
  if (b > t.rows) t.rows = b;
}



function initialize_facebox_links(){
  jQuery.facebox.settings.opacity = 0.4;
	jQuery.facebox.settings.overlay = true;
	jQuery.facebox.settings.closeImage = Ink.relative_url('/facebox/closelabel.gif');
	jQuery.facebox.settings.loadingImage = Ink.relative_url('/facebox/loading.gif');
	jQuery('a[rel*=facebox]').facebox();
}
jQuery(function(){
  initialize_facebox_links();
});


// javascript to make textareas behave more like textbox.  Based on http://jennifermadden.com/javascript/stringEnterKeyDetector.html
// but instead used jquery to find the closest form
function checkEnter(e){ //e is event object passed from function invocation
 
  var characterCode; // literal character code will be stored in this variable

  if(e && e.which){ //if which property of event object is supported (NN4)
    e = e;
    characterCode = e.which; //character code is contained in NN4's which property
  }
  else{
    e = event;
    characterCode = e.keyCode; //character code is contained in IE's keyCode property
  }
  if(characterCode == 13){ //if generated character code is equal to ascii 13 (if enter key)
    
    jQuery(e.currentTarget).closest('form').submit(); //submit the form
    
    return false;
  }
  else{
    return true;
  }
}

function textcounter_options(){
  return {
  			container: "<div></div>",
  			classname: "charcounter",
  			format: "%1 characters available",
  			pulse: false,
  			delay: 0
  		};
}


Ink.Markets = {
  
  request_uri: null,
  
  initialize_page: function() {
    // activate the expand arrows
    jQuery('div.expander').live('click', function(row){
      market_container = jQuery(this).closest(".market_container"); 
      market_container.find(".stock_container").toggle();
      market_container.find("img.expand_triangle").toggle();
      market_container.find("img.expanded_triangle").toggle();
    });
    
    // show the quick trade icon when a market/stock row is hovered
    jQuery('.market_container, .stock_container').live('mouseover', function() {
      jQuery(this).find('.actionicons:first').css('visibility', 'visible');
      jQuery(this).find('.options_link:first').show();
      
    }).live('mouseout', function() {
      jQuery(this).find('.actionicons:first').css('visibility', 'hidden');
      jQuery(this).find('.options_link:first').hide();
    });
    
    // give the arrows the pointer cursor
    jQuery(".expander").css({cursor:"pointer"});
    
    // activate the superfish menus
    jQuery('ul.sf-menu').livequery(function(){
      jQuery(this).superfish({speed:0, disableHI:true, autoArrows:true});
    });
  },
  
  toggle_stocks: function() {
    if(Cookie.get("expanded") == "true"){
      $$('div.stock_container').each(Element.hide);
      $$('img.expanded_triangle').each(Element.hide);
      $$('img.expand_triangle').each(Element.show);
      Cookie.erase('expanded');
    }
    else{
      this.expand_all();
      Cookie.set('expanded', 'true');
    }
  },
  
  expand_all: function() {
    $$('div.stock_container').each(Element.show);
    $$('img.expanded_triangle').each(Element.show);
    $$('img.expand_triangle').each(Element.hide);
  },
  
  expand: function(id) {
    stock_container = jQuery('.stocks_for_market_' + id).closest('.stock_container');
    market_container = stock_container.closest(".market_container");
    stock_container.show(); 
    market_container.find('img.expanded_triangle').show(); 
    market_container.find('img.expand_triangle').hide();
  },
  
  toggle_hide_link: function(element) {
    if(element.innerHTML == "hide") {
      element.innerHTML = "unhide";
    } else {
      element.innerHTML = "hide";
    }
  },
  
  highlight_cashing_out_markets: function(markets_cashing_out) {
    var cash_out_message = '<img src="'+Ink.relative_url('/images/indicator.gif')+'" />&nbsp;<em>processing</em>';
    jQuery.each(markets_cashing_out, function(){
      var container = jQuery('#market_'+this.id+'_container');
      if (container.find('.stock_row').length) {
        jQuery.each(this.stocks, function(){
          var stock = jQuery('#stock_'+this);
          stock.find('.stocklisting').append('<span class="highlighttext" id="resolution_status_'+this+'">'+cash_out_message+'</span>');
          stock.parent().find('ul.sf-menu').remove();
          Ink.Markets.poll_resolution(this);
        });
      } else {
        container.find('.marketlisting').append('<span class="highlighttext" id="resolution_status_'+this.stocks[0]+'">'+cash_out_message+'</span>');
        container.find('ul.sf-menu').remove();
        Ink.Markets.poll_resolution(this.stocks[0]);
      }
    });
  },
  
  poll_resolution: function(stock_id) {
    setTimeout(function() { 
      jQuery.ajax({
        type: 'GET',
        url: Ink.relative_url('/stocks/'+stock_id+'/resolutions/poll'),
        dataType: 'script'
      });
    }, 2000);
  },
  
  update_selected_date: function() {
    // Take the date from the calendar and move it to the right
    var selected = jQuery('.cds_footer span').html();
    if (selected == '&nbsp;') {
      var message = 'Choose a date!';
    } else {
      var message = 'Currently selected: <b>' + selected + ' (Pacific Time)</b>';
    }
    jQuery('#selected_date').html(message).show();
    // Hide the date in the calendar
    jQuery('.cds_footer').hide();
    // Hide the change message
    jQuery('#date_click_message').hide();
  },
  
  show_date_click_message: function() {
    jQuery('#date_click_message').show();
  },
  
  // Tries to come up with a decent, unique symbol based on the stock's name.
  auto_fill_stock_symbol: function(id, existing_symbols) {
    jQuery("#stock_"+id+"_name").change(function() {
      // Break the name into an array of words
      var name_parts = jQuery(this).val().split(" ");
      var symbol = "";
      
      // If there's just one word, use that, otherwise
      // get the first character from each word.
      if (name_parts.length == 1) {
        symbol = name_parts[0];
      } else {
        jQuery.each(name_parts, function(){
          symbol += this.charAt(0);
        });
      }
      
      // Grab the first 5 characters and uppercase them.
      symbol = symbol.substr(0, 5).toUpperCase();
      
      var unique_symbol = false;
      var counter = 2;
      
      // If the symbol already exists for another stock, try making
      // unique by adding 2 through 9 onto the end.
      while (unique_symbol === false && counter < 10) {
        if (!jQuery.isArray(existing_symbols)) {
          unique_symbol = true;
        } else if (jQuery.inArray(symbol, existing_symbols) != -1) {
          if (symbol.length < 5) {
            symbol += counter;
          } else {
            symbol = symbol.substr(0, 4) + counter;
          }
          counter++;
        } else {
          unique_symbol = true;
        }
      }

      jQuery("#stock_"+id+"_symbol").val(symbol);
    });
  },
  
  // Called when the opinion checkbox is changed
  adjust_for_opinion: function() {
    if (jQuery('#opinion').attr('checked') == true) {
      jQuery('.hide_if_opinion').hide();
      // Only non-exclusive options are allowed for opinion markets.
      if (jQuery('#market_class_type_exclusive').attr('checked') == true) {
        jQuery('#market_class_type_options').attr('checked', true);
      }
    } else {
      jQuery('.hide_if_opinion').show();
    }
  }, 
  
  converge_linear: function ( field, limit ) {
    target = parseInt( limit );
    var current = parseInt( field.html() );
    var diff = target - current;
    if( diff ) {
      current += diff > 0 ? 3 : -1;
      field.html( current );
    }
  },
  
  toggle_trade_reason: function(trade_id) {
    var container = jQuery('#trade_'+trade_id+'_reason');
    var ajaxType = 'DELETE';
    
    if (container.hasClass('hidden')) {
      container.removeClass('hidden');
      ajaxType = 'PUT';
    } else {
      container.addClass('hidden');
    }
    
    jQuery.ajax({
      url: Ink.relative_url('/trade_reasons/'+trade_id),
      type: ajaxType
    })
  }, 
  
  cashout_multistock_market: function(market_id) {
    html = '<h2>Choose an answer to cash out.</h2>';
    jQuery('#market_'+market_id+'_container .stock_container').each(function(){
      var stock = jQuery(this);
      var cashout = stock.find('ul.sf-menu li a.cashout');
      if (cashout.length != 0) {
        var answer = stock.find('.market_link');
        html += '<p class="links largetext"><a href="'+cashout.attr('href')+'">'+answer.text()+'</a></p>';
      }
      
      jQuery.facebox(html);
    });
  },
  
  initialize_category_selector: function(request_uri) {
    Ink.Markets.request_uri = request_uri;
    jQuery('#categories').live('mouseenter', function(){
      jQuery(this).addClass('categories_hovered');
      jQuery('#categories_tip').hide();
    }).live('mouseleave', function(){
      jQuery(this).removeClass('categories_hovered');
    });
    
    jQuery('#categories :checkbox').click(function(){
      Ink.Markets.set_category_preferences();
    });
  },
  
  set_category_preferences: function() {
    jQuery('#all_markets').html('<div style="font-size: 3em; padding-top: 40px; text-align:center">Loading...</div>');
    var checkboxes = jQuery('#categories :checkbox');
    var checked = jQuery('#categories :checkbox:checked');
    var category_ids = '';
    
    if (checked.length == 0) {
      var category_ids = 'none';
    } else if (checkboxes.length != checked.length) {
      var category_ids = jQuery.map(checked, function(a){ return jQuery(a).attr('value'); }).join('&');
    }
    
    checkboxes.each(function(){
      var checkbox = jQuery(this);
      if (checkbox.attr('checked')) {
        jQuery('#category_'+checkbox.val()).removeClass('not_shown').addClass('shown');
      } else {
        jQuery('#category_'+checkbox.val()).removeClass('shown').addClass('not_shown');
      }
    });
    
    jQuery.ajax({
      url: Ink.Markets.request_uri,
      data: { 'set_category_ids': category_ids },
      dataType: 'script'
    });
  },
  
  toggle_categories: function() {
    var check = (jQuery('#categories :checkbox').length != jQuery('#categories :checked').length);
    jQuery('#categories :checkbox').attr('checked', check);
    Ink.Markets.set_category_preferences();
  },
  
  toggle_category: function(category_id) {
    var checkbox = jQuery('#category_'+category_id+'_checkbox');
    checkbox.attr('checked', (checkbox.attr('checked') ? false : true));
    Ink.Markets.set_category_preferences();
  },
  
  show_info: function(id) {
    var options_count = 0;
    var options_html = '';
    var html = '';

    var background = jQuery('.market_description');
    if (background.length == 1) {
      options_html += '<option value="'+background.attr('id')+'">'+background.find('h2').text()+'</option>';
      options_count++;
    }

    var answers = jQuery('.stock_description');

    if (answers.length > 0) {
      options_html += '<optgroup label="Possible answers">';
      answers.each(function(){
        var selected = '';
        if (jQuery(this).attr('id') == id) {
          selected = ' selected="selected"';
        } 
        options_html += '<option value="'+jQuery(this).attr('id')+'"'+selected+'>'+jQuery(this).find('h2').text()+'</option>';
        options_count++;
      });
      options_html += '</optgroup>';
    }

    if (options_count > 1) {
      html += "<p><select onchange=\"Ink.Markets.show_info(jQuery(this).val());\">";
      html += options_html;
      html += '</select></p>';
      html += '<style> #more_info h2 { display: none; }</style>';
    }
    
    html += '<div id="more_info">' + jQuery('#'+id).html() + '</div>';
    jQuery.facebox(html);
  },
  
  initialize_trading_interface: function(type, quote_url) {
    jQuery('.tradeboxcontainer').click(function(){
      var radio = jQuery(this).find(':radio');
      if (!radio.attr('disabled')) {
        radio.attr('checked', true);
      }
      
      try { radio.find(':text').get(0).focus(); } catch(e) {};
 
      jQuery('#trade_reason').delay(300).fadeIn();

    });

    jQuery('#custom').click(function(){
      jQuery('#trade_quantity').get(0).focus();
    });

    var custom_quantity = jQuery('#trade_quantity');
    var last_quantity_quoted = null;

    custom_quantity.focus(function(){
      jQuery('#custom').attr('checked', true);
    });

    setInterval(function(){
      var val = custom_quantity.val();
      if (jQuery.trim(val) == '') {
        jQuery('#new_price, #money_spent').html('...');
        return true;
      } else if (val == last_quantity_quoted) {
        return true;
      }

      last_quantity_quoted = val;
      jQuery('#new_price, #money_spent').html('...');
      
      jQuery.ajax({
        type: 'POST',
        dataType: 'script',
        url: quote_url,
        data: { trade: { type: type, quantity: custom_quantity.val() }}
      });
    }, 350);
  }
  
};

Ink.FeaturedMarkets = {
	initialize: function() {
	  this.initialize_sparklines();
	  this.initialize_slider();
	},
	
	initialize_sparklines: function() {
	  // create an empty div offscreen to render the sparklines in
	  jQuery('body').append('<div id="sparkline_renderer" style="position:absolute; left: -9999px; width: 300px"></div>');
	  // move each sparkline into the renderer and then put it back
	  // sparklines don't like being rendered in hidden divs
	  jQuery('.stock_sparkline').each(function() {
	    var parent = jQuery(this).parent();
	    jQuery(this).appendTo('#sparkline_renderer').sparkline('html', { 
	      type: 'line',
	      height: '30px',
	      width: '200px'
	    }).appendTo(parent.css('visibility', 'visible'));
	  });
	},
	
	initialize_slider: function() {
	  var slide_count = jQuery('.featured_market').size();
	  if (slide_count <= 1) {
	    return true;
	  }
    // Since there is more than one featured market, do the slider
    for(var i = 1; i <= slide_count; i++) {
      jQuery('#slide_show_controller').prepend('<a href="#" class="slide_show_control">&nbsp;</a>');
    }
    jQuery("#slide_show_controller").jFlow({
  		slides: "#market_slides",
  		controller: ".slide_show_control",
  		slideWrapper : "#jFlowSlide",
  		selectedWrapper: "slide_selected",
  		duration: 250,
  		prev: ".slide_show_prev",
  		next: ".slide_show_next"
  	});
    jQuery('.featured_market').show();
    jQuery('#slide_show_controller').fadeIn('slow').children().click(function(){
      return false;
    });
	}
}

Ink.Intersite = {
  current_site: null,
  other_sites: null,
  
  initialize_site_switcher: function() {
    jQuery('a#site_switcher').click(function(){
      Ink.Intersite.toggle_other_sites_menu();
      return false;
    });
    
    var manage_link = jQuery('a#other_site_manager');
    manage_link.data('original_html', manage_link.html()).click(function(){
      Ink.Intersite.toggle_manage_items();
      return false;
    });
    
    var add_shadow = true;
    if (jQuery.browser.msie) {
      if (jQuery.browser.version < 7) {
        add_shadow = false;
      }
      Ink.Intersite.position_menu_absolute_in_body();
    }
    
    if (add_shadow === true) {
      jQuery('#other_sites_menu').addClass('sf-shadow');
    }
  },
  
  // Positions the site switcher menu absolute in the body
  // in the same position as the #site_title to avoid problems
  // with IE z-index bugs.
  position_menu_absolute_in_body: function() {
    var site_title_offset      = jQuery('#site_title').offset();
    var site_title_width       = jQuery('#site_title').width();
    var other_sites_menu_width = jQuery('#other_sites_menu').width();
    
    var top  = site_title_offset.top + 4;
    var left = site_title_offset.left + (site_title_width - other_sites_menu_width);
    if (jQuery.browser.version >= 7) {
      left += 8;
    }
    jQuery('#other_sites_menu').css({'top': top, 'left':left}).appendTo('body');
  },
  
  toggle_other_sites_menu: function() {
    var switcher_link = jQuery('#site_switcher');
    
    if (jQuery('#other_sites_menu:visible').length === 0) {
      switcher_link.data('original_html', switcher_link.html());
      switcher_link.html('&nbsp;');
      jQuery('#other_sites_menu').show();
      jQuery(document).bind('click', this.hide_other_sites_menu_if_external_click);
    } else {
      Ink.Intersite.hide_manage_items();
      switcher_link.html(switcher_link.data('original_html'));
      jQuery(document).unbind('click', this.hide_other_sites_menu_if_external_click);
      jQuery('#other_sites_menu').hide();
    }
  },
  
  hide_other_sites_menu_if_external_click: function(event) {
    if (jQuery(event.target).parents('#other_sites_menu').length === 0) {
      //jQuery(event.target).parents('.other_site_manage').length
      Ink.Intersite.toggle_other_sites_menu();
    }
  },
  
  toggle_manage_items: function() {
    var link = jQuery('#other_site_manager');
    
    if (link.hasClass('active')) {
      Ink.Intersite.hide_manage_items();
    } else {
      link.html("Ok, I'm done");
      link.addClass('active');
      jQuery('.other_site_manage').show();
      jQuery('a#other_site_manager').css({'background-color':'black'});
    }
  },
  
  hide_manage_items: function() {
    var link = jQuery('#other_site_manager');
    link.html(link.data('original_html')).removeClass('active');
    jQuery('.other_site_manage').hide();
    jQuery('a#other_site_manager').css({'background-color':''});
  },
  
  // Creates a form (in a facebox) to choose which site to replicate the market to.
  replication_dialog: function(market_id) {
    var html = '\
      <h2><em>'+jQuery('#market_'+market_id+' .market_link.market_link:first').text()+'</em></h2> \
      <p class="bodytext">Which site do you want to replicate to?</p> \
      <form method="post" action="'+Ink.relative_url('/markets/'+market_id+'/intersite_replications')+'" onsubmit="return Ink.Intersite.check_replication_to_current_site('+market_id+');"> \
      <input type="hidden" value="'+form_authenticity_token+'" name="authenticity_token" /> \
      <select name="intersite_replication[site_id]" id="intersite_replication_site_id"> \
      <option value="'+Ink.Intersite.current_site.id+'">This Site ('+Ink.Intersite.current_site.name+')</option>';
      
      jQuery.each(Ink.Intersite.other_sites, function(){
        html += '<option value="'+this.id+'">'+this.name+'</option>';
      });
      
      html += '\
      </select> \
      <p><input type="submit" value="Replicate" /></p> \
      </form>';

    jQuery.facebox(html);
  },
  
  // If the current site is selected as the one to replicate to,
  // submit a (new) form to the Market#replicate action and keep it all local.
  check_replication_to_current_site: function(market_id) {
    if (jQuery('#intersite_replication_site_id').val() == Ink.Intersite.current_site.id) {
      jQuery('\
        <form method="post" action="'+Ink.relative_url('/markets/'+market_id+'/replicate')+'" style="display:none"> \
        <input type="hidden" value="'+form_authenticity_token+'" name="authenticity_token" /> \
        </form>').appendTo('body').submit();
      return false;
    } else {
      return true;
    }
  }
};

Ink.QuickTrade = {
  
  quantity_to_trade:  0,
  quantity_to_calculate: 0,
  last_quantity_calculated: 0,
  ajax_running: false,
  market_recommendation_id: null,
  position_id: null,
  
  initialize_page: function() {
    // Teset these each time quick trade is launched so the values
    // don't carry over to another quick trade session.
    Ink.QuickTrade.quantity_to_trade = 0;
    Ink.QuickTrade.quantity_to_calculate = 0;
    Ink.QuickTrade.last_quantity_calculated = 0;
    Ink.QuickTrade.ajax_running = false;
    
    jQuery('a#buy, a#sell').click(function(){
      jQuery('#commit').hide();
      Ink.QuickTrade.set_quantity_to_calculate(jQuery(this));
      Ink.QuickTrade.calculate_trade();
      return false;
    });

    // checks to see if the quantity desired is not in sync with the
    // calculated quantity. this happens if someone clicks a button rapidly
    setInterval(function() {
      if (Ink.QuickTrade.last_quantity_calculated != Ink.QuickTrade.quantity_to_calculate) {
        Ink.QuickTrade.calculate_trade();
      }
    }, 300);
  },
  
  set_quantity_to_calculate: function(arrow_clicked) {
    if (arrow_clicked.attr('id') == 'buy') {
      if (this.quantity_to_calculate + 5 == 0) {
        this.quantity_to_calculate = 5;
      } else {
        this.quantity_to_calculate  += 5;
      }
    } else if (arrow_clicked.attr('id') == 'sell') {
      if (this.quantity_to_calculate - 5 == 0) {
        this.quantity_to_calculate = -5;
      } else {
        this.quantity_to_calculate  -= 5;
      }
    }
  },
  
  calculate_trade: function() {
    jQuery.ajax({
      type: "GET",
      url: jQuery('a#buy').attr('href'),
      data: { quantity: Ink.QuickTrade.quantity_to_calculate },
      dataType: "script",
      beforeSend: function() { 
        if (Ink.QuickTrade.ajax_running) { return false; } else { Ink.QuickTrade.ajax_running = true; }; 
      },
      complete: function() { 
        Ink.QuickTrade.ajax_running = false;
        Ink.QuickTrade.reset_height();
      }
    });

    jQuery('#trade_tip').html('Calculating...');
  },
  
  toggle_commit_details: function() {
    jQuery("#commit_details").toggle();
    Ink.QuickTrade.reset_height();
  },
  
  reset_height: function() {
    jQuery('#quick_trade').height('');
    jQuery('#quick_trade').height(jQuery('#quick_trade').height());
  },
  
  remove_error_class: function() {
    jQuery('#buy_container, #sell_container, #trade_tip').each(function(){
      if (jQuery(this).hasClass('error')) {
        jQuery(this).removeClass('error');
      }
    });
  },
  
  place_trade: function(url) {
    jQuery('#quick_trade .place_trade').hide();
    jQuery('#quick_trade .saving').show();
    
    jQuery.ajax({
      type: "POST",
      url: url,
      data: { 
        quantity: Ink.QuickTrade.quantity_to_calculate,
        trade_reason: jQuery('#trade_reason').val(),
        authenticity_token: form_authenticity_token
      },
      dataType: "script"
    });
  }
};

Ink.Leaderboard = {
  
  digest: null,
  poll_attempts: 0,
  max_poll_attempts: 30,
  // The stat that's loaded first with no ajax.
  index_stat: '',
  // The currently loaded stat.
  loaded_stat: '',
  
  initialize: function(index_stat) {
    Ink.Leaderboard.index_stat = index_stat;
    jQuery('#stats_nav a#link_'+index_stat).addClass('active');
    Ink.Leaderboard.observe_stat_change();
  },
  
  update: function(digest) {
    this.digest = digest;
    jQuery.ajax({
      type: "POST",
      data: { "_method": "put", "authenticity_token": form_authenticity_token },
      url: Ink.relative_url("/leaderboard")
    });
    this.poll();
  },
  
  poll: function() {    
    if (this.poll_attempts >= this.max_poll_attempts) {
      return;
    } else {
      this.poll_attempts += 1;
    }
    
    setTimeout(function(){
      jQuery.ajax({
        type: "GET",
        url: Ink.relative_url("/leaderboard/new"),
        dataType: "script"
      });
    }, 4000);
  },
  
  show_updated_message: function(digest) {
    if (digest != this.digest) {
      jQuery('#leaderboard_updated').show();
    }
  },
  
  load_stat: function(identifier) {
    jQuery('#stats_nav a').removeClass('active');
    jQuery('#stats_nav a#link_'+identifier).addClass('active');
    Ink.Leaderboard.loaded_stat = identifier;
    window.location.hash = identifier;
    jQuery('#stat_loading').show();
    jQuery('#stat_content').html('');
    jQuery.ajax({
      url: Ink.relative_url('/leaderboard?stat='+identifier),
      success: function(data) {
        jQuery('#stat_content').html(data);
      },
      error: function(error) {
        alert("Sorry, something didn't work right. Please refresh the page and try again.");
      },
      complete: function() {
        jQuery('#stat_loading').hide();
      }
    });
  },
  
  observe_stat_change: function() {
    setInterval(function(){
      var hash_stat = window.location.hash.split('#').reverse()[0];
      // If navigated back to the index
      if (Ink.Leaderboard.loaded_stat != '' && hash_stat == '') {
        hash_stat = Ink.Leaderboard.index_stat;
      }
      if (hash_stat != '' && hash_stat != Ink.Leaderboard.loaded_stat) {
        Ink.Leaderboard.load_stat(hash_stat);
      }
    }, 60);
  }
  
};

Ink.Dashboard = {
  
  liquidation_value_cache: {},
  
  initialize_liquidation: function(options) {
    // Start the slider UI
    jQuery('#position_'+options.id+' .slider').slider({
    	value: options.mid,
    	min: options.min,
    	max: options.max,
    	animate: true,
    	slide: function(event, ui) {
    	  set_value(ui.value);
    	}
    });
    
    // Add the value to the slider handle
    jQuery('#position_'+options.id+' .slider a.ui-slider-handle').append('<span class="value"></span>');
    
    // Returns the profit for a quantity of shares
    var calculate_profit = function(quantity){
      var profit_per_share = (options.up / 100) / options.max;
      var profit_for_quantity = (profit_per_share * quantity).toFixed(2);
      
      if (profit_for_quantity * 1 == 0) {
        return 0; // So we don't return -0.00
      } else {
        return profit_for_quantity;
      }
    }
    
    // Writes profit/loss html to the value span attached to the slider
    var set_value = function(quantity) {
      var profit_for_quantity = calculate_profit(quantity);
      
      var message = 'Liquidate '+quantity+' share';
      if (quantity > 1) {
        message += 's';
      }
      message += ' for a ';
      if (profit_for_quantity > 0) {
        message += 'profit';
      } else {
        message += 'loss'
      }
  	  message += ' of $' + profit_for_quantity;
  	  
  	  jQuery('#position_'+options.id+' .slider .value').html(message).css({ width:'120px', left: '-60px'});
    };
    
    // Start the slider in the middle
    set_value(options.mid);
    
    // Set profits on the legend
    jQuery('#position_'+options.id+' .range  .left_side').html('$'+calculate_profit(options.min));
    jQuery('#position_'+options.id+' .range .right_side').html('$'+calculate_profit(options.max));
  },
  
  load_partial_liquidation: function(position_id) {
    jQuery('#position_'+position_id+' .choices').hide();
    jQuery('#position_'+position_id+' .loading').show();
    
    jQuery.get(Ink.relative_url('/positions/'+position_id+'/liquidations/new'), {},
      function(data){
        jQuery('#position_'+position_id+' .partial_liquidation').html(data).show('fast');
        jQuery('#position_'+position_id+' .loading').hide('fast');
      });
  },
  
  cancel_liquidation: function(position_id) {
    jQuery('#position_'+position_id+' .liquidation').hide();
    jQuery('#position_'+position_id+' .partial_liquidation').hide();
    jQuery('#position_'+position_id+' .choices').show();
  },
  
  liquidate: function(position_id, quantity) {
    // If a quantity is not passed in, use the quantity from the slider.
    if (quantity == null) {
      quantity = jQuery('#position_'+position_id+' .slider').slider('value');
    }
    
    var message = 'Liquidating '+quantity+' share';
    if (quantity > 1) {
      message += 's';
    }
    message += '...';
    
    jQuery('#position_'+position_id+' .liquidation').html('<em>'+message+'</em>');
    
    jQuery.ajax({
      type: 'POST',
      url: Ink.relative_url('/positions/'+position_id+'/liquidations'),
      data: { 
        'quantity': quantity, 
        'authenticity_token': form_authenticity_token
      },
      dataType: 'script'
    });
  },
  
  refresh_position: function(position_id) {
    jQuery('#position_'+position_id+' .refresh').replaceWith('<em class="refresh">refreshing...</em>');
    
    jQuery.ajax({
      type: 'GET',
      url: Ink.relative_url('/positions/'+position_id),
      dataType: 'script'
    });
  },
  
  hide_position: function(position_id) {
    var position = jQuery('#position_'+position_id);
    var group = position.parents('.position_group:first');
    
    // If this is the only position in the market, hide the whole market
    if (group.find('.position:visible').length == 1) {
      group.hide('fast');
    } else {
    // Otherwise just hide the position
      position.hide('fast');
    }
  },
  
  load_performances: function() {
    jQuery.getJSON(Ink.relative_url("/performance.json"), function(performance){
      jQuery("#performance_today").html(performance.today);
      jQuery("#performance_week" ).html(performance.week);
      jQuery("#performance_month").html(performance.month);
      jQuery("#performance_year" ).html(performance.year);
    });
  },
  
  toggle_trades: function(stock_id, position_id) {
    var trades_container = jQuery('#trades_for_stock_'+stock_id);
    if (trades_container.html() == '') {
      trades_container.show().html('<em>Loading...</em>').load(Ink.relative_url('/positions/'+position_id+'/trades'));
    } else {
      if (jQuery('#trades_for_stock_'+stock_id+':visible').length == 0) {
        trades_container.show();
      } else {
        trades_container.hide();
      }
    }
  },
  
  initialize_page: function() {
    jQuery('.liquidate_action').live('mouseover', function(){
      jQuery(this).find('.tip').show();
    }).live('mouseout', function(){
      jQuery(this).find('.tip').hide();
    });

    jQuery('.position').live('mouseover', function(){
      jQuery(this).find('.action_icons').css({'visibility': 'visible'});
    }).live('mouseout', function(){
      jQuery(this).find('.action_icons').css({'visibility': 'hidden'});
    });
    
    this.load_performances();
  }
  
};

Ink.MarketGuess = {
  
  rules: [
    { 
      "starts_with": ["will", "should", "would", "could"], 
      "show": "#binary_market_container", 
      "click": "#binary"
    },
    { 
      "starts_with": ["when", "what day", "what month", "what year", "which day", "which month", "which year"], 
      "show": "#date_market_container", 
      "click": "#date" 
    },
    { 
      "starts_with": ["which", "who", "where"], 
      "show": '#options_market_container', 
      "click": "#event" 
    },
    { 
      "starts_with": ["how many", "what"], 
      "show": "#options_market_container, #number_market_container", 
      "click": "#number" 
    },
    { 
      "starts_with": ["how much"], 
      "show": "#number_market_container", 
      "click": "#number" 
    }
  ],
  
  opinion_keywords: ["should", "would", "could", "you like", "like better", "like more", "like the most", "like best"],
  
  initialize: function() {
    // Using a .guess namespace for these events so they can easily be unbound in the stop() function.
    jQuery('#market_name').bind('keyup.guess change.guess', function() { Ink.MarketGuess.start(); });
  },
  
  start: function() {
    var guessed = false;
    var opinion_market = false;
    var question = jQuery.trim(jQuery('#market_name').val().toLowerCase());
    
    // Execute the rules and guess the market type accordingly.
    jQuery.each(this.rules, function(){
      var rule = this;
      jQuery.each(rule.starts_with, function(){
        if (question.indexOf(this) == 0) {
          jQuery(".market_container").hide();
          jQuery(rule.show).show()
          jQuery(rule.click).click();
          
          guessed = true;
          return false;
        }
      });
      
      // break out of the loop by returning false if a match was found
      if (guessed === true) {
        return false;
      }
    });
    
    // Is this an opinion market?
    jQuery.each(this.opinion_keywords, function(){
      if (question.indexOf(this) != -1) {
        opinion_market = true;
        return false;
      }
    });
    
    jQuery("#opinion").attr("checked", opinion_market);
    Ink.Markets.adjust_for_opinion();
    
    // If we couldn't determine what kind of market they are creating.
    if (guessed === false) {
      this.non_guessed_state();
      jQuery("#binary").click();
    } else {
      jQuery("#unmatched_message").hide();
      jQuery("#matched_message").show();
    }
  },
  
  stop: function() {
    this.non_guessed_state();
    jQuery('#market_name').unbind('.guess');
  },
  
  // Shows all the market types and reverts the "we guessed" message
  non_guessed_state: function() {
    jQuery(".market_container").show();
    jQuery("#unmatched_message").show();
    jQuery("#matched_message").hide();
  }
  
};

Ink.MarketRecommendation = {
  
  presented_market_ids: null,
  
  dismiss: function(id, market_id) {
    jQuery('#market_recommendation_'+id).animate({ opacity: 0 }, 200);
    jQuery.ajax({
      url: Ink.relative_url('/market_recommendations/'+id),
      data: { market_id: market_id, 'presented_market_ids[]': Ink.MarketRecommendation.presented_market_ids },
      type: 'DELETE',
      dataType: 'script' 
    });
  }
  
};

Ink.Menus = {
  timeout: 500, 
  closetimer: 0,
  ddmenuitem: 0,
  
  jsddm_open: function(){
      
    Ink.Menus.jsddm_canceltimer();
    Ink.Menus.jsddm_close();
    Ink.Menus.ddmenuitem = jQuery(this).find('ul').css('visibility', 'visible');
  
    var add_shadow = true;
    if (jQuery.browser.msie) {
      if (jQuery.browser.version < 7) {
        add_shadow = false;
      }
    }
      
    menu = jQuery(this)
    menu_items = menu.find("ul li a");
  
    var position = menu.offset();
    width_of_menu = menu.outerWidth();
    width_of_menu_items = menu_items.outerWidth();
    menu_items.closest("ul").css('left', position.left-(width_of_menu_items-width_of_menu));
  
    if (add_shadow == true) {
      // jQuery("#jsddm li ul li").addClass('sf-shadow');
    }
  },

  jsddm_close: function(){  
    if(Ink.Menus.ddmenuitem) Ink.Menus.ddmenuitem.css('visibility', 'hidden');
  },

  jsddm_timer: function(){  
    Ink.Menus.closetimer = window.setTimeout(Ink.Menus.jsddm_close, Ink.Menus.timeout);
  },

  jsddm_canceltimer: function(){  
    if(Ink.Menus.closetimer){  
      window.clearTimeout(Ink.Menus.closetimer);
      Ink.Menus.closetimer = null;
    }
  }
     
};

jQuery(document).ready(function(){  
  jQuery('#jsddm > li').bind('mouseover', Ink.Menus.jsddm_open); 
  jQuery('#jsddm > li').bind('mouseout',  Ink.Menus.jsddm_timer); 
  document.onclick = Ink.Menus.jsddm_close;
});

Ink.Groups = {
  
  membership_search_mode: 'term', // email_addresses is the other option
  
  initialize: function(initial_markets, initial_memberships, check_initial) {
    jQuery('#search_markets_term').keypress(function(e){
      // If Enter is pressed, search for markets and don't submit the surrounding form.
      if (e.which == 13) {
        Ink.Groups.search_markets();
        return false;
      }
    });
    
    jQuery(':input[name=search_memberships_term]').keypress(function(e){
      if (e.which == 13) {
        if (Ink.Groups.membership_search_mode == 'term') {
          Ink.Groups.search_memberships();
          return false;
        } else {
          return true;
        }
      }
    });
    
    // Add inital markets to the list
    jQuery.each(initial_markets, function(){
      Ink.Groups.add_market(this, check_initial, false);
    });
    
    // And memberships
    jQuery.each(initial_memberships, function(){
      Ink.Groups.add_membership(this, check_initial, false);
    });
  },
  
  search_markets: function() {
    var term = jQuery('#search_markets_term').val();
    if (jQuery.trim(term) == '') {
      return true;
    }
    
    Ink.Groups.clear_search('group_markets');
    
    var original_button_val = jQuery('#search_markets_button').val();
    jQuery('#search_markets_button').val('Searching...').attr('disabled', true);
    
    jQuery.getJSON(Ink.relative_url('/markets.json?term='+term), function(data){
      if (jQuery.isArray(data) && data.length > 0) {
        jQuery.each(data, function(){
          Ink.Groups.add_market(this, false);
        });
      } else {
        jQuery('#no_markets_found').show();
        setTimeout(function(){
          jQuery('#no_markets_found').fadeOut();
        }, 1500);
      }
      jQuery('#search_markets_term').get(0).select();
      jQuery('#search_markets_button').val(original_button_val).attr('disabled', false);
    });
  },
  
  add_market: function(market, checked, highlighted) {
    if (jQuery('#market_'+market.id+'_checkbox').length == 0) {
      jQuery('#group_markets').append('<p><label><input type="checkbox" name="group[market_ids][]" value="'+market.id+'" id="market_'+market.id+'_checkbox" '+(checked ? 'checked="checked"' : '')+' /> '+market.name + '</label></p>');
    }
    
    if (highlighted !== false) {
      jQuery('#market_'+market.id+'_checkbox').parent().addClass('highlighttext');
    }
  },
  
  search_memberships: function() {
    var term_input = jQuery(':input[name=search_memberships_term]:visible');
    var term = term_input.val();
    if (jQuery.trim(term) == '') {
      return true;
    }
    
    Ink.Groups.hide_membership_errors();
    Ink.Groups.clear_search('group_memberships');
    
    var original_button_val = jQuery('.search_memberships_button').val();
    jQuery('.search_memberships_button').val('Searching...').attr('disabled', true);
    
    jQuery.ajax({
      type: "GET",
      url: Ink.relative_url("/group_membership_search.json"),
      data: { term: term, mode: Ink.Groups.membership_search_mode },
      dataType: "json",
      success: function(data) {
        jQuery.each(data.memberships, function(){
          Ink.Groups.add_membership(this, (Ink.Groups.membership_search_mode == 'email_addresses'));
        });
        
        if (Ink.Groups.membership_search_mode == 'term' && data.memberships.length == 0) {
          jQuery('#no_memberships_found').show();
          setTimeout(function(){
            jQuery('#no_memberships_found').fadeOut();
          }, 1500);
        }
        
        if (Ink.Groups.membership_search_mode == 'email_addresses' && data.emails_not_found.length > 0) {
          jQuery('#emails_not_found').html('No registered users were found with these emails: ' + data.emails_not_found.join(', ')).show();
        }
      },
      
      complete: function() {
        term_input.get(0).select();
        jQuery('.search_memberships_button').val(original_button_val).attr('disabled', false);
      }
    });
  },
  
  add_membership: function(membership, checked, highlighted) {
    if (jQuery('#membership_'+membership.id+'_checkbox').length == 0) {
      // Admins get an email address returned too
      if (membership.email || membership.active === false) {
        var display_name = membership.alias;
        if (membership.active === false) {
          display_name += ' <em><small>(not active)</small></em>';
        }
        if (membership.email) {
          display_name += ' <small>'+membership.email+'</small>';
        }
      } else {
        display_name = membership.alias;
      }
      jQuery('#group_memberships').append('<p><label><input type="checkbox" name="group[membership_ids][]" value="'+membership.id+'" id="membership_'+membership.id+'_checkbox" '+(checked ? 'checked="checked"' : '')+' /> '+display_name+'</label></p>');
    }
    
    if (highlighted !== false) {
      jQuery('#membership_'+membership.id+'_checkbox').parent().addClass('highlighttext');
    }
  },
  
  clear_search: function(container_id) {
    jQuery('#'+container_id+' :checkbox').each(function(){
      if (jQuery(this).attr('checked') == false) {
        jQuery(this).parent().remove();
      }
    });
    
    jQuery('#'+container_id+' .highlighttext').removeClass('highlighttext');
  },
  
  hide_membership_errors: function() {
    jQuery('#emails_not_found').hide();
  },
  
  set_membership_search_mode: function(mode) {
    Ink.Groups.membership_search_mode = mode;
    jQuery('.membership_search_mode').hide();
    jQuery('#'+mode+'_membership_search_mode').show();
    Ink.Groups.hide_membership_errors();
    Ink.Groups.clear_search('group_memberships');
    jQuery(':input[name=search_memberships_term]:visible').get(0).focus();
  },
  
  destroy: function(group_id, link_element) {
    if (!confirm('Are you sure you want to delete this group?')) {
      return;
    }
    
    jQuery(link_element).replaceWith('<em>Deleting...</em>');
    
    jQuery.ajax({
      type: "DELETE",
      url: Ink.relative_url("/groups/"+group_id),
      dataType: "script",
      success: function() {
        jQuery("#group_"+group_id+" :checkbox").attr('checked', false);
        jQuery("#group_"+group_id).slideUp();
        jQuery('#facebox a.close').click();
      },
      error: function() {
        Flash.error('Sorry, there was a problem delete this group.');
      }
    });
  }
  
};

Ink.Graphs = {
  
  default_graph_options: {
    credits: { enabled: false },
		title: { text: null },
		colors: ['#a9c55f', '#bbb', '#153b5f'],
		yAxis: { 
		  labels: { enabled: false },
			gridLineColor: '#fff'
		},
		legend: {
			layout: 'horizontal',
			backgroundColor: '#FFFFFF',
			borderColor: null,
			borderRadius: null,
			shadow: false,
			reversed: true,
			itemStyle: {
      	listStyle: 'none',
      	margin: '0 5px 0 0',
      	padding: 0,
      	font: '11px Arial, Helvetica, sans-serif',
      	cursor: 'pointer',
      	color: '#3E576F'
      },
			style: {
				left: '0',
				top: '0',
				bottom: 'auto'
			}
		}
  },
  
  activity: function(renderTo, series) {
    var graph_options = {
			chart: {
				renderTo: renderTo,
				defaultSeriesType: 'column',
				height: 200,
				margin: [25, 0, 20, 20]
			},
			xAxis: { categories: ['14 days ago', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'today'] },
			tooltip: {
				formatter: function() {
					return '<b>'+ this.series.name +'</b><br/>'+
					  this.y +' actions';
				},
				backgroundColor: '#fff'
			},
			plotOptions: {
				column: {
					pointPadding: 0.1,
					groupPadding: 0.1,
					borderWidth: 0,
					shadow: false
				}
			},
			
		  series: series
		};
		
    new Highcharts.Chart(jQuery.extend(Ink.Graphs.default_graph_options, graph_options));
	},
	
	line: function(options) {
	  var graph_options = {
	    chart: {
				renderTo: options.renderTo,
				defaultSeriesType: 'line',
				height: options.height,
				width: options.width,
				margin: [25, 10, 20, 10]
			},
			tooltip: {
				formatter: function() {
					return this.series.name + '<br/><b>'+this.y+options.append_to_tooltip+'</b>';
				},
				backgroundColor: '#fff'
			},
			xAxis: { categories: options.categories },
			series: options.series
	  };
	  
	  return new Highcharts.Chart(jQuery.extend(Ink.Graphs.default_graph_options, graph_options));
	},
	
	pie: function(options) {
	  var graph_options = {
	    chart: {
				renderTo: options.renderTo,
				defaultSeriesType: 'pie',
				margin: [15, 0, 0, 0]
			},
			colors: options.colors,
			plotOptions: {
        pie: {
          dataLabels: { enabled: false }
        }
      },
      tooltip: {
				formatter: function() {
					return '<b>'+this.y +'%</b>';
				},
				backgroundColor: '#fff'
			},
			series: options.series
	  };
	  
	  new Highcharts.Chart(jQuery.extend(Ink.Graphs.default_graph_options, graph_options));
	},
	
	toggle_best_line: function(link) {
	  var series = line_graph.get('best');
	  var checkmark = jQuery(link).parent().find('.check');
	  if (series.visible) {
	    series.hide();
	    checkmark.hide();
	  } else {
	    series.show();
	    checkmark.show();
	  }
	}
  
};

Ink.MarketStats = {

  load_stat: function(url, stat) {
    var join = (url.indexOf('?') != -1 ? '&' : '?');
    jQuery('#'+stat+' .loading').show();
    jQuery('#'+stat+' .container')
      .css('visibility', 'hidden')
      .load(Ink.relative_url(url+join+'stat='+stat), function(){
        jQuery(this).css('visibility', 'visible');
        jQuery('#'+stat+' .loading').hide();
      });
  },

  toggle_experts: function() {
    var non_experts = jQuery('.opinion_strength tr.non_expert');
    var experts = jQuery('.opinion_strength tr.expert');
  
    if (jQuery('#expert .check:visible').length == 0) {
      non_experts.hide();
      experts.show();
      jQuery('#expert .check').show();
    } else {
      non_experts.show();
      experts.show();
      jQuery('#expert .check').hide();
    }
  },
  
  load_tab: function(id) {
    jQuery('#market_stats .tab').hide();
    jQuery('#market_stats #'+id).show();
    
    jQuery('#stats_nav a').removeClass('active');
    jQuery('#stats_nav #'+id+'_link').addClass('active');
  }
  
}