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

  Browser: {
    IE:     !!(window.attachEvent && !window.opera),
    Opera:  !!window.opera,
    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,
    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;

if (Prototype.Browser.WebKit)
  Prototype.BrowserFeatures.XPath = 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 = Object.extend((function(m) {
          return function() { return ancestor[m].apply(this, arguments) };
        })(property).wrap(method), {
          valueOf:  function() { return method },
          toString: function() { return method.toString() }
        });
      }
      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 === undefined) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
    } 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 (value !== undefined)
        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 && object.constructor === Array;
  },

  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].split(",").invoke("strip");
    return names.length == 1 && !names[0] ? [] : names;
  },

  bind: function() {
    if (arguments.length < 2 && arguments[0] === undefined) 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);
  },

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

Function.prototype.defer = Function.prototype.delay.curry(0.01);

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 = count === undefined ? 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 = truncation === undefined ? '...' : 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.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.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('')
});

with (String.prototype.escapeHTML) div.appendChild(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);
    }.bind(this));
  }
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

var $break = { };

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

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

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

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

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

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

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

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

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

    this.each(function(value, index) {
      if (filter.match(value))
        results.push(iterator(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 = fillWith === undefined ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  },

  inject: function(memo, iterator, context) {
    iterator = iterator.bind(context);
    this.each(function(value, index) {
      memo = iterator(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 ? iterator.bind(context) : Prototype.K;
    var result;
    this.each(function(value, index) {
      value = iterator(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

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

  partition: function(iterator, context) {
    iterator = iterator ? iterator.bind(context) : Prototype.K;
    var trues = [], falses = [];
    this.each(function(value, index) {
      (iterator(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) {
    iterator = iterator.bind(context);
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator, context) {
    iterator = iterator.bind(context);
    return this.map(function(value, index) {
      return {value: value, criteria: iterator(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, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

if (Prototype.Browser.WebKit) {
  function $A(iterable) {
    if (!iterable) return [];
    if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
        iterable.toArray) return iterable.toArray();
    var length = iterable.length, 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 (value !== undefined) 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) {
    $R(0, this, true).each(iterator);
    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() {
  if (function() {
    var i = 0, Test = function(value) { this.key = value };
    Test.prototype.key = 'foo';
    for (var property in new Test('bar')) i++;
    return i > 1;
  }()) {
    function each(iterator) {
      var cache = [];
      for (var key in this._object) {
        var value = this._object[key];
        if (cache.include(key)) continue;
        cache.push(key);
        var pair = [key, value];
        pair.key = key;
        pair.value = value;
        iterator(pair);
      }
    }
  } else {
    function each(iterator) {
      for (var key in this._object) {
        var value = this._object[key], pair = [key, value];
        pair.key = key;
        pair.value = value;
        iterator(pair);
      }
    }
  }

  function 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: each,

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

    get: function(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.map(function(pair) {
        var key = encodeURIComponent(pair.key), values = pair.value;

        if (values && typeof values == 'object') {
          if (Object.isArray(values))
            return values.map(toQueryPair.curry(key)).join('&');
        }
        return toQueryPair(key, values);
      }).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 Ajax2 = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
};

Ajax2.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(Ajax2.Responders, Enumerable);

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

Ajax2.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();
  }
});

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

  initialize: function($super, url, options) {
    $super(options);
    this.transport = Ajax2.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 Ajax2.Response(this);
      if (this.options.onCreate) this.options.onCreate(response);
      Ajax2.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 = Ajax2.Request.Events[readyState], response = new Ajax2.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 && contentType
          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
        this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
      Ajax2.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;
    }
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } 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);
    Ajax2.Responders.dispatch('onException', this, exception);
  }
});

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

Ajax2.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  = xml === undefined ? null : xml;
      this.responseJSON = this._getResponseJSON();
    }
  },

  status:      0,
  statusText: '',

  getStatus: Ajax2.Request.prototype.getStatus,

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

  getHeader: Ajax2.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);
    } 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')))
        return null;
    try {
      return this.transport.responseText.evalJSON(options.sanitizeJSON);
    } catch (e) {
      this.request.dispatchException(e);
    }
  }
});

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

    options = options || { };
    var onComplete = options.onComplete;
    options.onComplete = (function(response, param) {
      this.updateContent(response.responseText);
      if (Object.isFunction(onComplete)) onComplete(response, param);
    }).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);
    }

    if (this.success()) {
      if (this.onComplete) this.onComplete.bind(this).defer();
    }
  }
});

Ajax2.PeriodicalUpdater = Class.create(Ajax2.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 Ajax2.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 || { });
}).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).style.display = 'none';
    return element;
  },

  show: function(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, t, range;

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

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

      content = Object.toHTML(content);

      range = element.ownerDocument.createRange();
      t.initializeRange(element, range);
      t.insert(element, range.createContextualFragment(content.stripScripts()));

      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 $A($(element).getElementsByTagName('*')).each(Element.extend);
  },

  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 expression ? Selector.findElement(ancestors, expression, index) :
      ancestors[index || 0];
  },

  down: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return element.firstDescendant();
    var descendants = element.descendants();
    return expression ? Selector.findElement(descendants, expression, index) :
      descendants[index || 0];
  },

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

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

  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] = value === undefined ? true : value;

    for (var attr in attributes) {
      var 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 (element.sourceIndex && !Prototype.Browser.Opera) {
      var e = element.sourceIndex, a = ancestor.sourceIndex,
       nextAncestor = ancestor.nextSibling;
      if (!nextAncestor) {
        do { ancestor = ancestor.parentNode; }
        while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
      }
      if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
    }

    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) {
      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') ?
          (elementStyle.styleFloat === undefined ? '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 (window.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 == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  absolutize: function(element) {
    element = $(element);
    if (element.getStyle('position') == 'absolute') return;
    // 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;
    // 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 == '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 (!document.createRange || Prototype.Browser.Opera) {
  Element.Methods.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 t = Element._insertionTranslations, content, position, pos, tagName;

    for (position in insertions) {
      content  = insertions[position];
      position = position.toLowerCase();
      pos      = t[position];

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

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

      if (t.tags[tagName]) {
        var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
        if (position == 'top' || position == 'after') fragments.reverse();
        fragments.each(pos.insert.curry(element));
      }
      else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());

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

    return element;
  };
}

if (Prototype.Browser.Opera) {
  Element.Methods._getStyle = Element.Methods.getStyle;
  Element.Methods.getStyle = function(element, style) {
    switch(style) {
      case 'left':
      case 'top':
      case 'right':
      case 'bottom':
        if (Element._getStyle(element, 'position') == 'static') return null;
      default: return Element._getStyle(element, style);
    }
  };
  Element.Methods._readAttribute = Element.Methods.readAttribute;
  Element.Methods.readAttribute = function(element, attribute) {
    if (attribute == 'title') return element.title;
    return Element._readAttribute(element, attribute);
  };
}

else if (Prototype.Browser.IE) {
  $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
    Element.Methods[method] = Element.Methods[method].wrap(
      function(proceed, element) {
        element = $(element);
        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;
      }
    );
  });

  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) {
          var 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.clone(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').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 == '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 Position.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 (document.createElement('div').outerHTML) {
  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];
  div.innerHTML = t[0] + html + t[1];
  t[2].times(function() { div = div.firstChild });
  return $A(div.childNodes);
};

Element._insertionTranslations = {
  before: {
    adjacency: 'beforeBegin',
    insert: function(element, node) {
      element.parentNode.insertBefore(node, element);
    },
    initializeRange: function(element, range) {
      range.setStartBefore(element);
    }
  },
  top: {
    adjacency: 'afterBegin',
    insert: function(element, node) {
      element.insertBefore(node, element.firstChild);
    },
    initializeRange: function(element, range) {
      range.selectNodeContents(element);
      range.collapse(true);
    }
  },
  bottom: {
    adjacency: 'beforeEnd',
    insert: function(element, node) {
      element.appendChild(node);
    }
  },
  after: {
    adjacency: 'afterEnd',
    insert: function(element, node) {
      element.parentNode.insertBefore(node, element.nextSibling);
    },
    initializeRange: function(element, range) {
      range.setStartAfter(element);
    }
  },
  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() {
  this.bottom.initializeRange = this.top.initializeRange;
  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, 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 = { };
    $w('width height').each(function(d) {
      var D = d.capitalize();
      dimensions[d] = self['inner' + D] ||
       (document.documentElement['client' + D] || document.body['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();
    this.compileMatcher();
  },

  compileMatcher: function() {
    // Selectors with namespaced attributes can't use the XPath version
    if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
      return this.compileXPathMatcher();

    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;
    if (this.xpath) return document._getElementsByXPath(this.xpath, root);
    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: "[@#{1}]",
    attr: function(m) {
      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 or translate(text(), ' \t\r\n', '') = '')]",
      'checked':     "[@checked]",
      'disabled':    "[@disabled]",
      'enabled':     "[not(@disabled)]",
      'not': function(m) {
        var e = m[6], p = Selector.patterns,
            x = Selector.xpath, le, m, 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 = false;',
    attr: function(m) {
      m[3] = (m[5] || m[6]);
      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); 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]+)\]/,
    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 Selector.operators[matches[2]](nodeValue, matches[3]);
    }
  },

  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) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._counted = true;
      return nodes;
    },

    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._counted = 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._counted = true;
      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._counted)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._counted)) 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])._counted) {
          n._counted = true;
          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, children = [], 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) {
      tagName = 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() == tagName) 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) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      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) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      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._counted) {
          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 && !node.innerHTML.match(/^\s*$/))) 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._counted) 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) 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.startsWith(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() + '-'); }
  },

  matchElements: function(elements, expression) {
    var matches = new Selector(expression).findElements(), h = Selector.handlers;
    h.mark(matches);
    for (var i = 0, results = [], element; element = elements[i]; i++)
      if (element._counted) 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) {
    var exprs = expressions.join(','), expressions = [];
    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
      expressions.push(m[1].strip());
    });
    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;
  }
});

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 (options.hash === undefined) 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 != '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 Ajax2.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.blur();
    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 (value === undefined) return element.checked ? element.value : null;
    else element.checked = !!value;
  },

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

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

  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) {
      var node = Event.extend(event).target;
      return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
    },

    findElement: function(event, expression) {
      var element = Event.element(event);
      return element.match(expression) ? element : element.up(expression);
    },

    pointer: function(event) {
      return {
        x: event.pageX || (event.clientX +
          (document.documentElement.scrollLeft || document.body.scrollLeft)),
        y: event.pageY || (event.clientY +
          (document.documentElement.scrollTop || document.body.scrollTop))
      };
    },

    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._eventID) return element._eventID;
    arguments.callee.id = arguments.callee.id || 1;
    return element._eventID = ++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;
  }

  if (window.attachEvent) {
    window.attachEvent("onunload", destroyCache);
  }

  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;

      if (document.createEvent) {
        var event = document.createEvent("HTMLEvents");
        event.initEvent("dataavailable", true, true);
      } else {
        var 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;
    }
  };
})());

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

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

  var timer, fired = false;

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

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

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

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

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


/* move element with id 'obj_id' to given coordinates */
Helper.prototype.moveTo = function (obj_id, coord_x, coord_y, use_right, use_bottom) {
	try {
		var obj;
		if (document.getElementById(obj_id))
			obj = document.getElementById(obj_id);
		else
			obj = obj_id;
		if (!obj && !obj.style)
			return;
		if (coord_x != null)  {
			if ((typeof coord_x) == "number" || (coord_x.indexOf("px") < 0 || coord_x.indexOf("em") < 0 || coord_x.indexOf("pt") < 0))
				coord_x += "px";
			if (use_right) {
				obj.style.left	= "";
				obj.style.right	= coord_x;
			} else {
				obj.style.left	= coord_x;
				obj.style.right	= "";
			}
		}
		if	(coord_y != null) {
			if ((typeof coord_y) == "number" || (coord_y.indexOf("px") < 0 || coord_y.indexOf("em") < 0 || coord_y.indexOf("pt") < 0))
				coord_y += "px";
			if (use_bottom) {
				obj.style.top		= "";
				obj.style.bottom	= coord_y;
			} else {
				obj.style.top		= coord_y;
				obj.style.bottom	= "";
			}
		}
	} catch(e) {
		;
	}
};


/* move element with id 'obj_id' to given coordinates starting from its current position*/
Helper.prototype.moveBy = function (obj_id, coord_x, coord_y, use_right, use_bottom) {
	var obj;
	var self = new Helper();
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return;
	
	var pos = self.getRealCoordinates(obj);
	
	if (coord_x != null)  {
		//if ((typeof coord_x) == "number" || (coord_x.indexOf("px") < 0 || coord_x.indexOf("em") < 0 || coord_x.indexOf("pt") < 0)) {
		if (coord_y.replace) {
			coord_x.replace(/px/, "");
			coord_x.replace(/em/, "");
			coord_x.replace(/pt/, "");
			coord_x = parseInt(coord_x);
		}
		coord_x += pos[0];
		if (use_right) {
			obj.style.left	= "";
			obj.style.right	= coord_x+"px";
		} else {
			obj.style.left	= coord_x+"px";
			obj.style.right	= "";
		}
	}
	if	(coord_y != null) {
		if (coord_y.replace) {
			coord_y.replace(/px/, "");
			coord_y.replace(/em/, "");
			coord_y.replace(/pt/, "");
			coord_y = parseInt(coord_y);
		}
		coord_y += pos[1];
		if (use_bottom) {
			obj.style.top		= "";
			obj.style.bottom	= coord_y+"px";
		} else {
			obj.style.top		= coord_y+"px";
			obj.style.bottom	= "";
		}
	}
};




Helper.prototype.resizeTo = function (obj_id, width, height) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return;
	if (width != null) {
		if ((typeof width) == "number" || (width.indexOf("px") < 0 || width.indexOf("em") < 0 || width.indexOf("pt") < 0))
			width += "px";
		try {
			obj.style.width	= width;
		} catch (e) {
			obj.style.width = "0px";
		}
	}
	if	(height != null) { 
		if ((typeof height) == "number" || (height.indexOf("px") < 0 || height.indexOf("em") < 0 || height.indexOf("pt") < 0))
			height += "px";
		try {
			obj.style.height = height;	
		} catch (e) {
			obj.style.height = "0px";
		}
	}
};




/* returns an array with (x,y)-coordinates of given element with id 'obj_id'
 * if 'with_unit' is true, the coordinate units will be returned, too */
Helper.prototype.getCoordinates = function (obj_id, with_unit) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return new Array (0, 0);
	var left	= obj.style.left;
	var top		= obj.style.top;
	if (with_unit)
		return new Array (left, top);
	return new Array (parseFloat(left.substring(0, left.length-2)), parseFloat(top.substring(0, top.length-2)));
};


/* returns an array with (x,y)-coordinates of given element with id 'obj_id'
 * if 'with_unit' is true, the coordinate units will be returned, too */
Helper.prototype.getRealCoordinates = function (obj_id) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return new Array (0, 0);
	var left	= obj.offsetLeft;
	var top		= obj.offsetTop;
	return new Array (left, top);
};




/* returns an array with the real (x,y)-coordinates of given element with id 'obj_id' */
/*Helper.prototype.getRealCoordinates = function (obj_id) {
	return new Array (document.getElementById(obj_id).offsetLeft, document.getElementById(obj_id).offsetTop);
}*/

/* returns an array with the real (x,y)-coordinates of given element with id 'obj_id' absolute to the page */
Helper.prototype.getAbsoluteCoordinates = function (obj_id, depth) {
	var obj;
	var self = new Helper();
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return null;
	return new Array (self.abs_left(obj, depth, 0), self.abs_top(obj, depth, 0));
};


Helper.prototype.abs_top = function (obj, depth, current) {
	var self = new Helper();
	if (depth) {
		if (depth == current) {
			return obj.offsetTop;
		} else {
			current++;
			return obj.offsetTop+self.abs_top(obj.offsetParent, depth, current)
		}
	}
	return (obj.offsetParent) ? obj.offsetTop+self.abs_top(obj.offsetParent, depth, current) : obj.offsetTop; 
};

Helper.prototype.abs_left = function (obj, depth, current) {
	var self = new Helper();
	if (depth) {
		if (depth == current) {
			return obj.offsetLeft;
		} else {
			current++;
			return obj.offsetLeft+self.abs_left(obj.offsetParent, depth, current)
		}
	}
	return (obj.offsetParent) ? obj.offsetLeft+self.abs_left(obj.offsetParent, depth, current) : obj.offsetLeft; 
};




/* returns an array with the dimension (width, height) of given element with id 'obj_id'
 * if 'with_unit' is true, the coordinate units will be returned, too */
Helper.prototype.getDimension = function (obj_id, with_unit) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	var width	= obj.style.width;
	var height	= obj.style.height;
	if (with_unit)
		return new Array (width, height);
	return new Array (parseFloat(width.substring(0, width.length-2)), parseFloat(height.substring(0, height.length-2)));
};


/* returns an array with the real dimension (width, height) of given element with id 'obj_id' */
Helper.prototype.getRealDimension = function (obj_id) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj)
		return new Array (0, 0);
	return new Array (obj.offsetWidth, obj.offsetHeight);
};


/* returns an array with the dimension (width, height) of the client area including scrolling offset */
Helper.prototype.getScrollDimension = function () {
	var self = new Helper();
	var x,y;
	var test1		= document.body.scrollHeight;
	var test2		= document.body.offsetHeight;
	var dimension	= self.getInnerDimension();
	if (test1 > test2) {
		x = document.body.scrollWidth;
		y = document.body.scrollHeight;
	} else {
		x = document.body.offsetWidth;
		y = document.body.offsetHeight;
	}
	if (x < dimension[0])
		x = dimension[0];
	if (y < dimension[1])
		y = dimension[1];
	return new Array (x, y);
};


Helper.prototype.getRealScrollDimension = function (obj_id) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	x	= 0;
	y	= 0;
	if (obj.scrollHeight || obj.scrollWidth) {
		x	= obj.scrollWidth;
		y	= obj.scrollHeight;
	}
	if (obj.offsetHeight || obj.scrollWidth) {
		if (obj.offsetWidth > x)
			x = obj.offsetWidth;
		if (obj.offsetHeight > y)
			y = obj.offsetHeight;
	} 
	return new Array (x, y);
};


/* returns an array with the dimension (width, height) of the client area (without any offsets) */
Helper.prototype.getInnerDimension = function () {
	var x,y;
	if (window.innerHeight) {
		x = window.innerWidth;
		y = window.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) {
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	} else if (document.body) {
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return new Array (x, y);
};


/* returns true, if browser is Internet Explorer 6 */
Helper.prototype.isIE = function () {
	if ((document.all) && (window.offscreenBuffering)) {
		if (!window.XMLHttpRequest)
			return true;
	}
	return false;
};

/* returns true, if browser is Internet Explorer 7 */
Helper.prototype.isIE7 = function () {
	if ((document.all) && (window.offscreenBuffering)) {
		if (window.XMLHttpRequest)
			return true;
	}
	return false;
};

/* returns true, if browser is Safari */
Helper.prototype.isSafari = function () {
	return (navigator.userAgent.toLowerCase().indexOf('safari') != -1);
};


/* returns true, if browser is Netscape */
Helper.prototype.isNetscape = function () {
	if(navigator.appName.indexOf("Netscape") != -1)
		return true;
	return false;
};

/* returns true, if browser is Opera */
Helper.prototype.isOpera = function () {
	return (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
};



/* increases the transparency of given ID 'obj_id' by 'value' */
Helper.prototype.incOpacity = function (obj_id, value) {
	var self = new Helper();
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (self.isIE() || self.isIE7()) {
		var newVal = (parseFloat(obj.filters.alpha.opacity/100) + value)*100;
		obj.filters.alpha.opacity = parseInt(newVal);
	} else {
		var newVal = parseFloat(obj.style.opacity) + value;
		obj.style.opacity = newVal;
		if (obj.style.MozOpacity != newVal) {
			newVal = parseFloat(obj.style.MozOpacity) + value;
			obj.style.MozOpacity = newVal;
		}
	}
};



/* set the transparency of given ID 'obj_id' to 'value' */
Helper.prototype.setOpacity = function (obj_id, value) {
	var self = new Helper();
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (self.isIE() || self.isIE7()) {
		var newVal = parseFloat(value)*100;
		//obj.filters.alpha.opacity = newVal;
		if (obj.style.filter) {
			obj.filters.alpha.opacity = parseInt(newVal);
		} else {
			obj.style.filter = "Alpha(opacity="+parseInt(newVal)+")";
		}
	} else {
		obj.style.opacity = value;
		if (obj.style.MozOpacity != value) {
			obj.style.MozOpacity = value;
		}
	}
};



/* switches the image of element with ID 'obj_id' to 'url' */
Helper.prototype.switchImage = function (obj_id, url)	{
	document.getElementById(obj_id).src = url;
};


/* add an event listener for 'event_type' to given object 'obj' and bind function 'event_func' to it */
/*Helper.prototype.addEvent = function (obj_id, event_type, event_func, use_caption) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if(!obj) return false;
	if (obj.addEventListener) {
		obj.addEventListener(event_type, event_func, use_caption);
		return true;
	} else if (obj.attachEvent) {
		return obj.attachEvent("on"+event_type, event_func);
	} else {
		return false;
	}
}

Helper.prototype.removeEvent = function (obj_id, event_type, fn ) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if(!obj) return false;
	if ( obj.detachEvent ) {
		obj.detachEvent( 'on'+event_type, obj[event_type+fn] );
		obj[type+fn] = null;
	} else
		obj.removeEventListener( event_type, fn, false );
} */

Helper.prototype.addEvent = function ( obj_id, type, fn, use_caption ) {
	var obj;
	var self = new Helper();
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj) return false;	
	if (self.isIE() || self.isIE7()) {
		Event.observe(obj, type, fn, use_caption);
		return true;
	}
	if (obj.addEventListener) {
		obj.addEventListener( type, fn, false );
	} else if (obj.attachEvent) {
		obj["e"+type+fn] = fn;
		obj[type+fn] = function() { obj["e"+type+fn]( window.event ); };
		obj.attachEvent( "on"+type, obj[type+fn] );
	}
	return true;
};

Helper.prototype.removeEvent = function ( obj_id, type, fn, use_caption ) {
	var obj;
	var self = new Helper();
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if (!obj) return false;
	if (self.isIE() || self.isIE7()) {
		Event.stopObserving(obj, type, fn);
		return true;
	}
	if (obj.removeEventListener) {
		obj.removeEventListener( type, fn, false );
	} else if (obj.detachEvent) {
		obj.detachEvent( "on"+type, obj[type+fn] );
		obj[type+fn] = null;
		obj["e"+type+fn] = null;
	}
	return true;
};


Helper.prototype.getBodyScrollPosition = function () {
	var scrollPosX, scrollPosY;
	if (typeof window.pageYOffset != 'undefined') {
		scrollPosX = window.pageXOffset;
		scrollPosY = window.pageYOffset;
	} else if (typeof document.compatMode != 'undefined' && document.compatMode != 'BackCompat') {
		scrollPosX = document.documentElement.scrollLeft;
		scrollPosY = document.documentElement.scrollTop;
	} else if (typeof document.body != 'undefined') {
		scrollPosX = document.body.scrollLeft;
		scrollPosY = document.body.scrollTop;
	}
	return new Array (scrollPosX, scrollPosY);
};

Helper.prototype.getScrollPosition = function (obj_id) {
	var obj;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if(!obj) return new Array (0, 0);
	var x,y;
	if (obj.pageXOffset) {	
		x = obj.pageXOffset;
		y = obj.pageYOffset;
	} else {
		x = obj.scrollLeft;
		y = obj.scrollTop;
	}
	return new Array (x, y);
};

Helper.prototype.scrollToBottom = function (obj_id, parent_id) {
	var self = new Helper();
	dim_obj			= self.getRealDimension(obj_id)[1];
	dim_parent		= self.getRealDimension(parent_id)[1];
	coord_obj		= self.getCoordinates(obj_id)[1];
	coord_parent	= self.getCoordinates(parent_id)[1];

	if (dim_obj < dim_parent) {
		self.moveTo(obj_id, null, 0);
	} else {
		self.moveTo(obj_id, null, dim_parent-dim_obj);
	}
};


Helper.prototype.replace = function (string, search, replacetxt) {
	output = "" + string;
	while (output.indexOf(search) >- 1) {
		pos= output.indexOf(search);
		output = "" + (output.substring(0, pos) + replacetxt + output.substring((pos + search.length), output.length));
	}
	return output;
};


Helper.prototype.findImageSources = function (html) {
	if (!html) return new Array ();
	imgs	= new Array ();
	html	= html.toLowerCase().split('<img ');
	for (var i=0; i < html.length; i++) {
		var start = html[i].indexOf('src="')+5;
		var end	  = html[i].indexOf('"', start);
		if (html[i].substring(start, end).length > 4)
			imgs.push(html[i].substring(start, end));
	}
	return imgs;
};


Helper.prototype.preloadImages = function (stringarray) {
	if (!document.pics) document.pics = new Array();
	completed = true;
	for (i in stringarray) {
		if (!document.pics[i]) {
			document.pics[i] = new Image();
			document.pics[i].src = stringarray[i];
		}
		if (!document.pics[i].complete)
			completed = false;
	}
	if (completed)
		document.pics = null;
	return completed;
};


Helper.prototype.hexToDec = function (hex) {
	hex = parseInt (hex, 16);
	return (isNaN(hex)) ? false: hex;
};


Helper.prototype.decToHex = function (dec) {
	hex="0123456789ABCDEF";
	olddec = dec;
	dec = parseInt(dec);
	out = "";
	if (isNaN(dec))
		return false;
	if (dec == 0)
		return "00";
	while (dec != 0) {
		out = hex.charAt (dec%16) + out;
		dec = dec >> 4;
	}
	if (out.length%2 != 0)
			out = "0"+out;
	return out;
};


Helper.prototype.toHexColor = function (col) {
	var self = new Helper();
	if (typeof col == "Array" && col.length == 3) {
		return self.decToHex(col[0]) + self.decToHex(col[1]) + self.decToHex(col[2]);
	} else 	if ( (col.substring(0,1) == "#" && (col.length==7 || col.length == 4)) || 
			(col.length == 7)) {
				col = col.replace("#", "");
				return col;
	}else if (col.substring(0,4) == "rgb(") {
		col = col.replace(/rgb\(/, "");
		col = col.replace(")", "");
		col = col.replace(" ", "");
		col = col.split(",", 3);
		return self.decToHex(col[0]) + self.decToHex(col[1]) + self.decToHex(col[2]);
	}
	
	return "0";
};


Helper.prototype.fadeIn = function (obj_id, onFinish_func, step, hideAfterSeconds, displayBlock, force_fade) {
	var obj;
	var self = this;
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if ((true && !force_fade) || self.isIE() || self.isIE7()) {
		self.setOpacity(obj, 1);
		if (displayBlock)
			obj.style.display		= "block";
		else
			obj.style.display		= "";
		obj.style.visibility	= "visible";
		if (onFinish_func)
			onFinish_func();
		return;
	}
	if (!step || step == 0) {
		step = 0;
		self.setOpacity(obj_id, 0);
		if (displayBlock)
			obj.style.display		= "block";
		else
			obj.style.display		= "";
		obj.style.visibility	= "visible";
	}
	if (step < 9) {
		step++;
		self.incOpacity(obj_id, 0.1);
		var self = this;
		window.setTimeout(function(){self.fadeIn(obj_id, onFinish_func, step);}, 50);
	} else {
		self.incOpacity(obj_id, 0.1);
		if (onFinish_func)
			onFinish_func();
	}
	if (hideAfterSeconds) {
		var self = this;
		window.setTimeout(function() {self.fadeOut(obj_id, true);}, hideAfterSeconds);
	}
};

Helper.prototype.fadeOut = function (obj_id, displayNone, onFinish_func, step, force_fade) {
	var obj;
	var self = new Helper();
	if (document.getElementById(obj_id))
		obj = document.getElementById(obj_id);
	else
		obj = obj_id;
	if ((true && !force_fade) || self.isIE() || self.isIE7()) {
		self.setOpacity(obj, 0);
		if (displayNone == true)
			obj.style.display = "none";
		obj.style.visibility	= "hidden";
		if (onFinish_func) {
			onFinish_func();
		}
		return;
	}
	if (!step || step == 0) {
		step = 0;
		self.setOpacity(obj_id, 1);
	}
	if (step < 9) {
		step++;
		self.incOpacity(obj_id, -0.1);
		var self = this;
		window.setTimeout(function(){self.fadeOut(obj_id, displayNone, onFinish_func, step);}, 50);
	} else {
		self.setOpacity(obj_id, 0);
		if (displayNone == true)
			obj.style.display = "none";
		obj.style.visibility	= "hidden";
		if (onFinish_func) {
			onFinish_func();
		}
	}
};


Helper.prototype.waitForBody = function (callback_func, params) {
	var self = this;

	/*if (!callback_func)
		return;
		
	if (document.observe) {
		return document.observe("dom:loaded", function() { callback_func(params); });
	}*/

	if (document.body && document.body_loaded && document.body_loaded == 1) {
		callback_func(params);
		return;
	} else {
		window.setTimeout(function(){self.waitForBody(callback_func, params);}, 100);
		return;
	}
	
	if (callback_func) {
		if (!document.helper_waiting_objects)
			document.helper_waiting_objects = new Array();
		document.helper_waiting_objects.push(new Array (callback_func, params));
	}
	
	
	if (document.body && document.body_loaded && document.body_loaded == 1) {
		if (callback_func)
			callback_func(params);alert(document.helper_waiting_objects);
		while (document.helper_waiting_objects.length > 0) {
			if (document.helper_waiting_objects[0][0])
				document.helper_waiting_objects[0][0](document.helper_waiting_objects[0][1]);
			document.helper_waiting_objects.shift();
		}
	} else {
		window.setTimeout(function(){self.waitForBody(null, null);}, 100);
	}
};


Helper.prototype.execJS2 = function (node) {
 /* Element auf Javascript überprüfen, und falls nötig ausführen */
 var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
 var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
 var bMoz = (navigator.appName == 'Netscape');
 var st = node.getElementsByTagName('script'); var strExec;
   
 for(var i=0;i<st.length; i++) { if (bSaf) { strExec = st[i].innerHTML; } else if (bOpera) { strExec = st[i].text; }
   else if (bMoz) { strExec = st[i].textContent; } else { strExec = st[i].text; } try { eval(strExec); } catch(e) { alert(e);}}
};


Helper.prototype.execJS = function (obj) {
	var scripts = obj.getElementsByTagName("script");

	for (i=0; i < scripts.length; i++) {
		if (scripts[i].getAttribute("type", false) == "text/javascript") {
			eval(scripts[i].innerHTML);
		}
	}
};

Helper.prototype.execJSCount = function (obj, maxcount) {
	var scripts = obj.getElementsByTagName("script");

	var exec	= "";
	var count = scripts.length;
	if (count > maxcount) count = maxcount;

	for (i=0; i < count; i++) {
		if (scripts[i].getAttribute("type", false) == "text/javascript") {
			exec += scripts[i].innerHTML;
		} 
	}
	eval(exec);
};

	
Helper.prototype.serialize = function (elem) {
	if (elem == null || elem == undefined || elem.constructor == Function) return 'N;';
	var self = new Helper();
	switch (elem.constructor) {
		case String:  return 's:' + elem.length + ':"' + elem + '";';
		case Number:  return (elem % 1 ? 'd:' : 'i:') + elem + ';';
		case Boolean: return 'b:' + (elem ? '1' : '0') + ';';     
		case Date:    return self.serialize(elem.getTime());
		case RegExp:  return self.serialize(elem.toSource());
		case Error:   return self.serialize(elem.message);
		case Array:
		case Object:
			var content = '', i = 0;
			for (var j in elem) { 
				content += self.serialize(j) + self.serialize(elem[j]);
				i++; 
			}
			return 'a:' + i + ':{' + content + '}';
		default:
			return self.serialize(elem.toString());
	}
};


Helper.prototype.getElementsByName	= function (name, pParent, _tags) {
	var parent	= pParent || document;
	var els		= new Array ();
	var tags	= _tags || new Array ("div", "span", "table", "tr", "td", "form", "input", "textarea", "select", "option", "a");
	for (var i=0; i < tags.length; i++) {
		var elements	= parent.getElementsByTagName(tags[i]);
		//var elements	= parent.childNodes;
		for (var y=0; y < elements.length; y++) {
			if (elements[y].getAttribute("name", false) == name)
				els.push(elements[y]);
		}
	}
	
	return els;
};

Helper.prototype.getElementsByClassName	= function (name, pParent, _tags) {
	var parent	= pParent || document;
	var els		= new Array ();
	var tags	= _tags || new Array ("div", "span", "table", "tr", "td", "form", "input", "textarea", "select", "option", "a");
	for (var i=0; i < tags.length; i++) {
		var elements	= parent.getElementsByTagName(tags[i]);
		//var elements	= parent.childNodes;
		for (var y=0; y < elements.length; y++) {
			if (elements[y].getAttribute("class", false) == name || elements[y].className == name)
				els.push(elements[y]);
		}
	}
	
	return els;
};

String.prototype.trim = function () {
	var self = new Helper();
    return (self.replace(/\s+$/,"").replace(/^\s+/,""));
};


Helper.prototype.fckEditorFix = function () {
	for ( i = 0; i < parent.frames.length; ++i ) if ( parent.frames[i].FCK ) parent.frames[i].FCK.UpdateLinkedField();
};



Helper.prototype.checkTextarealengthInterval = function (textarea, maxlength, containerId) {
	var el		= document.getElementById(containerId);
	if (!el || !textarea)
		return;

	var chars	= textarea.value.length;
	if (chars > maxlength) {
		textarea.value	= textarea.value.substring(0, maxlength);
		chars			= maxlength;
	}
	if (el)
		el.innerHTML	= (maxlength - chars);
};

Helper.prototype.checkTextarealength = function (textarea, maxlength, containerId) {
	if (!textarea)
		return;
	var self = this;
	eval("textarea.onfocus = function() { document.checkTextarealength_timer_"+containerId+" = window.setInterval(function() { document.helper.checkTextarealengthInterval(textarea, maxlength, containerId); }, 500); }");
	eval("textarea.onblur = function() { window.clearInterval(document.checkTextarealength_timer_"+containerId+"); }");
};


Helper.prototype.makeModal	= function (obj) {
	if (document.getElementById(obj))
		obj = document.getElementById(obj);
	if (!obj)
		return;
	var self	= this;

	if (!(document.body && document.body_loaded && document.body_loaded == 1)) {
		self.waitForBody(function() { self.makeModal(obj); });
		return;
	}
	
	if (!document.helper_modal_div) {
		document.helper_modal_div					= document.createElement("div");
		document.helper_modal_div.style.display		= "none";
		document.helper_modal_div.style.position	= "absolute";
		document.helper_modal_div.style.zIndex		= 99999;
		document.helper_modal_div.style.top			= "0px";
		document.helper_modal_div.style.left		= "0px";
		document.helper_modal_div.style.backgroundColor	= "#000";
		document.body.appendChild(document.helper_modal_div);
	}
	
	var id		= obj.getAttribute("id", false);
	obj.setAttribute("id", id+"_modal", false);
	obj						= obj.cloneNode(true);
	obj.setAttribute("id", id, false);
	obj.style.position		= "absolute";
	obj.style.zIndex		= 100000;
	obj.style.display		= "block";
	obj.style.visibility	= "hidden";
	obj.style.top			= "0px";
	obj.style.left			= "0px";

	document.body.appendChild(obj);

	var dim				= self.getRealDimension(obj);
	var scrolling		= self.getBodyScrollPosition();
	var inner_dim		= self.getInnerDimension();
	var full_dim		= self.getScrollDimension();
	
	var new_x		= (inner_dim[0]-dim[0])/2;
	var new_y		= (inner_dim[1]-dim[1])/2;
	var scrolling	= new Array (0, 0);

	self.moveTo(obj, new_x + scrolling[0], new_y+scrolling[1]);
	self.resizeTo(document.helper_modal_div, full_dim[0], full_dim[1]);
	
	document.helper_modal_div.style.display	= "block";
	self.setOpacity(document.helper_modal_div, 0);
	
	self.fadeIn(document.helper_modal_div, null, 7);
	self.fadeIn(obj);
};

Helper.prototype.unModal	= function (obj) {
	if (document.getElementById(obj))
		obj = document.getElementById(obj);
	if (!obj)
		return;
	var id	= obj.getAttribute("id", true);
	/*if (document.getElementById(id+"_modal"))
		document.getElementById(id+"_modal").setAttribute("id", id, false);*/
	document.helper.fadeOut(document.helper_modal_div, true, null, 7);
};



Helper.prototype.multiselect_changed = function (select, key, loopval, maxval, reset, selectname, noval, cbFunc) {
	
	if (!noval)
		noval = "-1";

	if (reset || select.value == noval) {
		if (reset) {
			select		= document.helper.getElementsByName(selectname, null, new Array ("select"));
			select		= select[loopval];
			if (select.value == noval) {
				if (cbFunc)
					cbFunc();
				return;
			}
			select.value = noval;
		}
		
		var els	= document.helper.getElementsByName(select.name, null, new Array ("select"));
		
		var i = loopval;
		for (i = loopval; i < els.length -1; i++) {
			els[i].value = els[i+1].value;
		}

		els[els.length -1].value = noval;
		
		var fadet = false;
		for (var i=1; i < maxval; i++) {
			var el		= document.getElementById('multiselect_'+key+'_'+i);
			var next	= document.getElementById('multiselect_'+key+'_'+(i+1));
			var prev	= new Array ();
			var found	= false;
			for (var j=i-1; j > -1; j--) {
				if (els[j] && els[j].value == noval) {
					found = true;
					break;
				}
			}
			
			if ((!next || next.style.display == "none") && found) {
				document.helper.fadeOut(el, true);
				fadet = true;
				break;
			} else if (!found) {
				if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
					document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "none";
			}
		}
		for (i = 0; i < els.length -1; i++) {
			if (els[i].value == noval) {
				if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
					document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "none";
			} else {
				if (document.getElementById('multiselect_delete_'+key+'_'+(i))) {
					document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "";
				}
			}
		}
		if (cbFunc)
			cbFunc();
		return;
	}
	
	var els	= document.helper.getElementsByName(select.name, null, new Array ("select"));
	
	for (i = 0; i < els.length; i++) {
		if (els[i].value == noval) {
			if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
				document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "none";
		} else {
			if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
				document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "";
		}
			
		if (i == loopval) {
			continue;
		}
		if (els[i].value == select.value) {
			select.value = noval;
			if (cbFunc)
				cbFunc();
			return;
		}
	}
	
	
	if (select.value == noval) {
		for (var i=0; i < maxval; i++) {
			var el = document.getElementById('multiselect_'+key+'_'+i);
			if (!el)
				continue;
			if (i > 0 && el.style.display != "none")
				document.helper.fadeOut(el, true);
		}
		
		var els	= document.helper.getElementsByName(select.name, null, new Array ("select"));
		
		for (var i=0; i < els.length; i++)
			els[i].value = noval;
		
		var el = document.getElementById('multiselect_'+key+'_0');
		if (el && el.style.display == "none")
			document.helper.fadeIn(el, null, null, null, true);
	
		if (cbFunc)
			cbFunc();
		return;
	}
	

	if (document.getElementById('multiselect_'+key+'_'+(loopval+1)) && document.getElementById('multiselect_'+key+'_'+(loopval+1)).style.display == 'none') 
		document.helper.fadeIn('multiselect_'+key+'_'+(loopval+1), null, null, null, true);
	
	var els	= document.helper.getElementsByName(select.name, null, new Array ("select"));
		
	for (var i=0; i < els.length; i++) {
		if (els[i].value == noval) {
			if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
				document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "none";
		} else {
			if (document.getElementById('multiselect_delete_'+key+'_'+(i)))
				document.getElementById('multiselect_delete_'+key+'_'+(i)).style.display	= "";
		}
	}
	
	if (cbFunc)
		cbFunc();
};

Helper.prototype.reset_multiselect = function (keys, _idAppend) {
	idAppend	= _idAppend || "";
	for (var y=0; y < keys.length; y++) {
		var key	= keys[y];
		y++;
		var maxval	= keys[y];
		eval("var els = document.helper.getElementsByName('"+key+"[]', null, new Array('select'));");
		var found = false;
		for (var i=0; i < els.length; i++) {
			for (var ix=0; ix < maxval; ix++) {
				if (!document.getElementById('multiselect_'+key+'_'+ix+idAppend)) {
					continue;
				}
					
				var el	= document.getElementById('multiselect_'+key+'_'+ix+idAppend).getElementsByTagName("select")[0];
				
				/*if (!el)
					continue;*/
				
				if (el.value == "-1") {
					if (document.getElementById('multiselect_delete_'+key+'_'+(ix)+idAppend))
						document.getElementById('multiselect_delete_'+key+'_'+(ix)+idAppend).style.display	= "none";
					if (document.getElementById('multiselect_'+key+'_'+ix+idAppend))
						document.getElementById('multiselect_'+key+'_'+ix+idAppend).style.display	= "none";
				} else {
					found == true;
					if (document.getElementById('multiselect_delete_'+key+'_'+(ix)+idAppend))
						document.getElementById('multiselect_delete_'+key+'_'+(ix)+idAppend).style.display	= "";
					if (document.getElementById('multiselect_'+key+'_'+ix+idAppend))
						document.getElementById('multiselect_'+key+'_'+ix+idAppend).style.display	= "";
				}
			}
		}
		if (!found) {
			if (document.getElementById('multiselect_delete_'+key+'_0'+idAppend))
				document.getElementById('multiselect_delete_'+key+'_0'+idAppend).style.display	= "";
			if (document.getElementById('multiselect_'+key+'_0'+idAppend))
				document.getElementById('multiselect_'+key+'_0'+idAppend).style.display	= "";
		}
	}
	return;
};

Helper.prototype.xmlGetData	= function (field, str) {
	var len		= field.length;
	var idx1	= str.indexOf("<"+field+">") + len + 2;
	var idx2	= str.indexOf("</"+field+">");
	if (idx1 > 0 && idx2 > idx1) {
		return str.substring(idx1, idx2);
	}
	return "";
};

Helper.prototype.numeralsOnly = function (evt) {
    evt = (evt) ? evt : event;
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : 
        ((evt.which) ? evt.which : 0));
    if (charCode > 31 && (charCode < 48 || charCode > 57)) {
       // alert("Enter numerals only in this field.");
        return false;
    }
    return true;
};

document.helper = new Helper();;
function layoutFix () {
/*	if (document.helper.isSafari()) {
		if (document.getElementById('mod_profile_head'))
			document.getElementById('mod_profile_head').style.marginTop = "20px";
	}*/
	
	if (!document.helper.isIE7()) {
		layoutFix_width();
		window.setInterval(layoutFix_width, 1000);
	}
}

function layoutFix_width () {
	if (document.body.offsetWidth && document.body.offsetWidth <= 1024 && document.body.offsetWidth > 980) {
		document.body.style.overflowX = "hidden";
	} else {
		document.body.style.overflowX = "auto";
	}
	
	var dim = document.helper.getInnerDimension();
	if (!document.body.scrollHeight)
		return;
		
	if (document.body.scrollHeight <= dim[1]) {
		/*if (document.body.style.overflowY != "scroll")
			document.body.style.overflowY = "hidden";*/
	} else {
		document.body.style.overflowY = "scroll";
	}
}
	
function tour_showNext () {
	if (!document.tour_item) {
		document.tour_item = 2;
	} else {
		document.tour_item++;
	}
	
	if (document.tour_item > 3)
		document.tour_item = 1;
	window.setTimeout(function () {tour_show(document.tour_item);}, 1);
}
	
function tour_show (item) {
	document.tour_item = item;
		
	for (var i=1; i < 5; i++) {
		if (i == item)
			continue;
		if (document.getElementById("tourlink_00"+i)) {
			if (document.getElementById("tourlink_00"+i).className != "tour_inactive") {
				document.getElementById("tourlink_00"+i).className='tour_inactive';
				document.getElementById("tourlink_00"+i).setAttribute("class", "tour_inactive", false);
			}
		}
		if (document.getElementById("tour_00"+i)) {
			if (document.getElementById("tour_00"+i).style.display != "none")
				document.getElementById("tour_00"+i).style.display = "none";
		}
		if (document.getElementById("information_00"+i)) {
			if (document.getElementById("information_00"+i).style.display != "none")
				document.getElementById("information_00"+i).style.display = "none";
		}
	}

	if (document.getElementById("tourlink_00"+item)) {
		if (document.getElementById("tourlink_00"+item) != "tour_active") {
			document.getElementById("tourlink_00"+item).setAttribute("class", "tour_inactive", false);
			document.getElementById("tourlink_00"+item).className='tour_active';
		}
	}
	if (document.getElementById("tour_00"+item)) {
		if (document.getElementById("tour_00"+item).style.display == "none")
			document.helper.fadeIn("tour_00"+item);
	}
	if (document.getElementById("information_00"+item)) {
		if (document.getElementById("information_00"+item).style.display == "none")
			document.getElementById("information_00"+item).style.display = "";
	}
}
;
;function Ajax (ttl) {

	var event_func;

	var xmlhttp;
	var use_xml					= false;
	//var use_ajax_loader_div		= false;
	//ajax_loader_div	= null;
	if (!Ajax.instances)
		Ajax.instances = 0;
		

	var instance = Ajax.instances++;
	
	var REQUEST_GET		= 0;
	var REQUEST_HEAD	= 1;
	var REQUEST_POST	= 2;
	var REQUEST_XML		= 3;
	
	var timeout			= null;
	var time_to_live	= (ttl) ? ttl:5;
	
	var helper			= new Helper();
	var self			= this;
	
	/*with (document) {
		write('<div id="ajax_ajax_loader_div" style="position:absolute; top: 0px; left: 0px; color: black; background-color: gray; opacity: 0.5; -moz-opacity: 0.5; filter:alpha(opacity=50); display:none; z-index: 1111; text-align: center; vertical-align: middle;"><br><br>Loading data...</div>');
	}*/
	/*ajax_loader_div							= document.createElement("div");
	ajax_loader_div.style.position			= "absolute";
	ajax_loader_div.style.top				= "0px";
	ajax_loader_div.style.left				= "0px";
	ajax_loader_div.style.color				= "#000";
	ajax_loader_div.style.backgroundColor	= "gray";
	ajax_loader_div.style.zIndex			= "1111";
	ajax_loader_div.style.textAlign			= "center";
	ajax_loader_div.style.verticalAlign		= "middle";
	ajax_loader_div.style.display			= "none";
	ajax_loader_div.innerHTML				= "<br><br>Loading data...";
	ajax_loader_div.setAttribute("id", "ajax_ajax_loader_div"+instance, false);*/
	//helper.setOpacity(ajax_loader_div, 0.5);
	//helper.waitForBody(function(){document.body.appendChild(ajax_loader_div);});	
	
	
	this.request_get = function (src_file, params, request_func, func_param, use_loader, xml) {
		use_xml = xml;		
		use_ajax_loader_div	= false;
		event_func = request_func;
		this.request(src_file, params, REQUEST_GET, func_param);
	};
		
	this.request_post = function (src_file, params, request_func, func_param, use_loader, xml) {
		use_xml = xml;		
		use_ajax_loader_div	= false;
		event_func = request_func;
		this.request(src_file, params, REQUEST_POST, func_param);
	};
	
	this.request_head = function (src_file, params, request_func, func_param, use_loader, xml) {
		use_xml = xml;		
		use_ajax_loader_div	= false;
		event_func = request_func;
		this.request(src_file, params, REQUEST_HEAD, func_param);
	};
	
	this.request_xml = function (src_file, params, request_func, func_param, use_loader) {
		use_xml = true;		
		use_ajax_loader_div	= false;
		event_func = request_func;
		this.request(src_file, params, REQUEST_XML, func_param);
	};
	
	
	function getRequester () {
		try {
			if (window.ActiveXObject) {
				for (var i=5; i; i--) {
					try {
						if (i == 2) {
							xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
						} else {
							xmlhttp = new ActiveXObject("Msxml2.XMLHTTP." + i + ".0");
						}
						break;
					} catch (excNotLoadable) {
						xmlhttp = false;
					}
				}
			} else if (window.XMLHttpRequest) {
				xmlhttp = new XMLHttpRequest();
			}
		} catch (excNotLoadable) {
			xmlhttp = false;
		}
	};
	
	
	this.request = function (src_file, params, request_type, func_param) {
		if (!params)
			params = '';

		if (isNaN(request_type))
			request_type = REQUEST_GET;

		if (xmlhttp) {
			free(); //setTimeout(function(){self.request(src_file, params, request_type, func_param);}, Math.round(Math.random()*100));
		}

		if (!xmlhttp) {
				getRequester();
		}
				
		/*ajax_loader_div.style.display = "none";
		if (use_ajax_loader_div) {
			window_dim = helper.getInnerDimension();
			helper.resizeTo(ajax_loader_div, window_dim[0], window_dim[1]);
			ajax_loader_div.style.display = "block";
		}*/
		if (timeout)
			clearTimeout(timeout);
		timeout = setTimeout(function(){self.handle_timeout(func_param);}, time_to_live*1000); 
		

		if (request_type != REQUEST_HEAD && (params && params.substr (0, 1) == '&' || params.substr(0, 1) == '?'))
			params = params.substring (1, params.length);


		var dataReturn = params ? params : src_file;

		switch (request_type) {
			case REQUEST_XML:
				params = "xml=" + params;
				
			case REQUEST_POST:
				xmlhttp.open("POST", src_file, true);
				xmlhttp.setRequestHeader("Pragma", "no-cache");
				xmlhttp.setRequestHeader("Cache-Control", "must-revalidate");
				xmlhttp.setRequestHeader("If-Modified-Since", document.lastModified);
				xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
				xmlhttp.setRequestHeader("Content-length", params.length);
				break;

			case REQUEST_HEAD:
				xmlhttp.open("HEAD", src_file, true);
				params = null;
				break;
			
			default:
				var p_file = src_file + (params ? '?' + params : '');
				xmlhttp.open("GET", p_file, true);
				params = null;
		};

		xmlhttp.onreadystatechange = function(){self.process_response(func_param);};

		xmlhttp.send(params);

		return dataReturn;
	};

	
	this.process_response = function (func_param) {
		switch (xmlhttp.readyState) {
			
			case 0:	// uninitialized
			
			case 1: // loading
			
			case 2: // loaded
			
			case 3: // interactive
				break;

			case 4: // complete
				/*if (ajax_loader_div && ajax_loader_div.style && ajax_loader_div.style.display)
					ajax_loader_div.style.display = "none";*/
				try {
					if (xmlhttp.status == 200) {
						clearTimeout(timeout);
						parse_data(func_param);
					} else {
						clearTimeout(timeout);
						//alert("AJAX error!\n HTTP status = " + xmlhttp.status + "\n" + xmlhttp.statusText);
						free();
						event_func(false, func_param);
					}
				} catch (e) {
				}
		};
	};

	
	this.handle_timeout = function (func_param) {
		//alert("AJAX error!\n Timeout");
		/*if (ajax_loader_div)
			ajax_loader_div.style.display = "none";	*/
		event_func(false, func_param);
		free();
	};
	
	
	function free () {
		if (xmlhttp) {
			try {
				xmlhttp.abort();
			} catch (e) {
			}
			xmlhttp = false;
		}	
	};
	
	function parse_data(func_param) {
		if (use_xml) {
			event_func(xmlhttp.responseXML, func_param, xmlhttp.responseText);
			free();
		} else {
			event_func(xmlhttp.responseText, func_param, xmlhttp.responseXML);
			free();
		}
	};

};;
if ( use_popups == undefined ) {
	var use_popups = false;
}

function launchTellFriend ()
{
	if ( use_popups == false ) {
		window.location.href = 'index.php?ext=recommend';
		return;
	}

	var left = (screen.width/2) - 280/2;
	var top = (screen.height/2) - 280/2;
	var win = "width=340,height=210,left=" + left + ",top=" + top + ",copyhistory=no,directories=no,menubar=no,location=no,resizable=yes,scrollbars=yes";
	window.open("index.php?ext=recommend",'tellfriend',win);
};
//\/////
//\  overLIB 4.23 - You may not remove or change this notice.
//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
//\     Modified August 20, 2006.  Changed the routine name from
//\			createPopup to olCreatePopup to avoid conflicts with
//\			a Windows OS function of the same name.
//\
//\  Contributors are listed on the homepage.
//\  This file might be old, always check for the latest version at:
//\  http://www.bosrup.com/web/overlib/
//\
//\  Please read the license agreement (available through the link above)
//\  before using overLIB. Direct any licensing questions to erik@bosrup.com.
//\
//\  Do not sell this as your own work or remove this copyright notice. 
//\  For full details on copying or changing this script please read the
//\  license agreement at the link above. Please give credit on sites that
//\  use overLIB and submit changes of the script so other people can use
//\  them as well.
//\/////

////////
// PRE-INIT
// Ignore these lines, configuration is below.
////////
var olLoaded=0, pmStart=10000000, pmUpper=10001000, pmCount=pmStart+1, pms=new Array(), pmt='', olInfo=new Info('4.23', 0);
var FREPLACE=0, FBEFORE=1, FAFTER=2, FALTERNATE=3, FCHAIN=4;
var olHideForm=0;  // parameter for hiding SELECT and ActiveX elements in IE5.5+
var olHautoFlag = 0;
var olVautoFlag = 0;
var hookPts=new Array(),postParse=new Array(),cmdLine=new Array(),runTime=new Array();
var coreCmds='donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,' +
 'fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,' +
 'autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,' +
 'padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,' +
 'captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,' +
 'mouseoff,closetitle,cssoff,compatmode,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass';
registerCommands(coreCmds);
////////
// DEFAULT CONFIGURATION
// Settings you want everywhere are set here. All of this can also be
// changed on your html page or through an overLIB call.
////////
if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#FFFFFF";
if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#EDA822";
if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";
if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";
if (typeof ol_closecolor=='undefined') var ol_closecolor="#FFFFFF";
if (typeof ol_textfont=='undefined') var ol_textfont="Arial,Helvetica";
if (typeof ol_captionfont=='undefined') var ol_captionfont="Arial,Helvetica";
if (typeof ol_closefont=='undefined') var ol_closefont="Arial,Helvetica";
if (typeof ol_textsize=='undefined') var ol_textsize="1";
if (typeof ol_captionsize=='undefined') var ol_captionsize="1";
if (typeof ol_closesize=='undefined') var ol_closesize="1";
if (typeof ol_width=='undefined') var ol_width="250";
if (typeof ol_border=='undefined') var ol_border="1";
if (typeof ol_cellpad=='undefined') var ol_cellpad=2;
if (typeof ol_offsetx=='undefined') var ol_offsetx=10;
if (typeof ol_offsety=='undefined') var ol_offsety=10;
if (typeof ol_text=='undefined') var ol_text="Default Text";
if (typeof ol_cap=='undefined') var ol_cap="";
if (typeof ol_sticky=='undefined') var ol_sticky=0;
if (typeof ol_background=='undefined') var ol_background="";
if (typeof ol_close=='undefined') var ol_close="Close";
if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;
if (typeof ol_status=='undefined') var ol_status="";
if (typeof ol_autostatus=='undefined') var ol_autostatus=0;
if (typeof ol_height=='undefined') var ol_height=-1;
if (typeof ol_snapx=='undefined') var ol_snapx=0;
if (typeof ol_snapy=='undefined') var ol_snapy=0;
if (typeof ol_fixx=='undefined') var ol_fixx=-1;
if (typeof ol_fixy=='undefined') var ol_fixy=-1;
if (typeof ol_relx=='undefined') var ol_relx=null;
if (typeof ol_rely=='undefined') var ol_rely=null;
if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";
if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";
if (typeof ol_padxl=='undefined') var ol_padxl=1;
if (typeof ol_padxr=='undefined') var ol_padxr=1;
if (typeof ol_padyt=='undefined') var ol_padyt=1;
if (typeof ol_padyb=='undefined') var ol_padyb=1;
if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;
if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;
if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;
if (typeof ol_capicon=='undefined') var ol_capicon="";
if (typeof ol_frame=='undefined') var ol_frame=self;
if (typeof ol_timeout=='undefined') var ol_timeout=0;
if (typeof ol_function=='undefined') var ol_function=null;
if (typeof ol_delay=='undefined') var ol_delay=0;
if (typeof ol_hauto=='undefined') var ol_hauto=1;
if (typeof ol_vauto=='undefined') var ol_vauto=0;
if (typeof ol_closeclick=='undefined') var ol_closeclick=0;
if (typeof ol_wrap=='undefined') var ol_wrap=0;
if (typeof ol_followmouse=='undefined') var ol_followmouse=1;
if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;
if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';
if (typeof ol_compatmode=='undefined') var ol_compatmode=0;
if (typeof ol_css=='undefined') var ol_css=CSSOFF;
if (typeof ol_fgclass=='undefined') var ol_fgclass="";
if (typeof ol_bgclass=='undefined') var ol_bgclass="";
if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";
if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";
if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
////////
// ARRAY CONFIGURATION
////////
if (typeof ol_texts=='undefined') var ol_texts=new Array("Text 0","Text 1");
if (typeof ol_caps=='undefined') var ol_caps=new Array("Caption 0","Caption 1");
////////
// END OF CONFIGURATION
// Don't change anything below this line, all configuration is above.
////////
////////
// INIT
////////
// Runtime variables init. Don't change for config!
var o3_text="";
var o3_cap="";
var o3_sticky=0;
var o3_background="";
var o3_close="Close";
var o3_hpos=RIGHT;
var o3_offsetx=2;
var o3_offsety=2;
var o3_fgcolor="";
var o3_bgcolor="";
var o3_textcolor="";
var o3_capcolor="";
var o3_closecolor="";
var o3_width=100;
var o3_border=1;
var o3_cellpad=2;
var o3_status="";
var o3_autostatus=0;
var o3_height=-1;
var o3_snapx=0;
var o3_snapy=0;
var o3_fixx=-1;
var o3_fixy=-1;
var o3_relx=null;
var o3_rely=null;
var o3_fgbackground="";
var o3_bgbackground="";
var o3_padxl=0;
var o3_padxr=0;
var o3_padyt=0;
var o3_padyb=0;
var o3_fullhtml=0;
var o3_vpos=BELOW;
var o3_aboveheight=0;
var o3_capicon="";
var o3_textfont="Verdana,Arial,Helvetica";
var o3_captionfont="Verdana,Arial,Helvetica";
var o3_closefont="Verdana,Arial,Helvetica";
var o3_textsize="1";
var o3_captionsize="1";
var o3_closesize="1";
var o3_frame=self;
var o3_timeout=0;
var o3_timerid=0;
var o3_allowmove=0;
var o3_function=null; 
var o3_delay=0;
var o3_delayid=0;
var o3_hauto=0;
var o3_vauto=0;
var o3_closeclick=0;
var o3_wrap=0;
var o3_followmouse=1;
var o3_mouseoff=0;
var o3_closetitle='';
var o3_css=CSSOFF;
var o3_compatmode=0;
var o3_fgclass="";
var o3_bgclass="";
var o3_textfontclass="";
var o3_captionfontclass="";
var o3_closefontclass="";
// Display state variables
var o3_x=0;
var o3_y=0;
var o3_showingsticky=0;
var o3_removecounter=0;
// Our layer
var over=null;
var fnRef, hoveringSwitch=false;
var isMac=(navigator.userAgent.indexOf("Mac")!=-1);
var olHideDelay;
// Decide browser version
var olOp=(navigator.userAgent.toLowerCase().indexOf('opera') > -1 && document.createTextNode);  // Opera 7
var olNs4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4);
var olNs6=(document.getElementById)? true : false;
var olKq=olNs6&&/konqueror/i.test(navigator.userAgent);
var olIe4=(document.all) ? true : false;
var olIe5=false;
var olIe55=false;
var docRoot='document.body';
// Resize fix for NS4.x to keep track of layer
if (olNs4) {
	var oW=window.innerWidth;
	var oH=window.innerHeight;
	window.onresize=function () {if (oW!=window.innerWidth||oH!=window.innerHeight) location.reload(); };
}
// Microsoft Stupidity Check(tm).
if (olIe4) {
	var agent=navigator.userAgent;
	if (/MSIE/.test(agent)) {
		var versNum=parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/)[1]);
		if (versNum >= 5){
			olIe5=true;
			olIe55=(versNum>=5.5&&!olOp) ? true : false;
			if (olNs6) olNs6=false;
		}
	}
	if (olNs6) olIe4=false;
}
if(document.compatMode && document.compatMode=='CSS1Compat') docRoot= ((olIe4&&!olOp) ? 'document.documentElement' : docRoot);
if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,false);
else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);
// Capture events,alt. diffuses the overlib function.
var capExtent;
////////
// PUBLIC FUNCTIONS
////////
// overlib(arg0,...,argN)
// Loads parameters into global runtime variables.
function overlib() {
	if(!olLoaded||isExclusive(arguments)) return true;
	if(olCheckMouseCapture) olMouseCapture();
	if (over) {
		over = (typeof over.id != 'string') ? o3_frame.document.all['overDiv'] : over;
		cClick();
	}
	// Load defaults to runtime.
  olHideDelay=0;
	o3_text=ol_text;
	o3_cap=ol_cap;
	o3_sticky=ol_sticky;
	o3_background=ol_background;
	o3_close=ol_close;
	o3_hpos=ol_hpos;
	o3_offsetx=ol_offsetx;
	o3_offsety=ol_offsety;
	o3_fgcolor=ol_fgcolor;
	o3_bgcolor=ol_bgcolor;
	o3_textcolor=ol_textcolor;
	o3_capcolor=ol_capcolor;
	o3_closecolor=ol_closecolor;
	o3_width=ol_width;
	o3_border=ol_border;
	o3_cellpad=ol_cellpad;
	o3_status=ol_status;
	o3_autostatus=ol_autostatus;
	o3_height=ol_height;
	o3_snapx=ol_snapx;
	o3_snapy=ol_snapy;
	o3_fixx=ol_fixx;
	o3_fixy=ol_fixy;
	o3_relx=ol_relx;
	o3_rely=ol_rely;
	o3_fgbackground=ol_fgbackground;
	o3_bgbackground=ol_bgbackground;
	o3_padxl=ol_padxl;
	o3_padxr=ol_padxr;
	o3_padyt=ol_padyt;
	o3_padyb=ol_padyb;
	o3_fullhtml=ol_fullhtml;
	o3_vpos=ol_vpos;
	o3_aboveheight=ol_aboveheight;
	o3_capicon=ol_capicon;
	o3_textfont=ol_textfont;
	o3_captionfont=ol_captionfont;
	o3_closefont=ol_closefont;
	o3_textsize=ol_textsize;
	o3_captionsize=ol_captionsize;
	o3_closesize=ol_closesize;
	o3_timeout=ol_timeout;
	o3_function=ol_function;
	o3_delay=ol_delay;
	o3_hauto=ol_hauto;
	o3_vauto=ol_vauto;
	o3_closeclick=ol_closeclick;
	o3_wrap=ol_wrap;	
	o3_followmouse=ol_followmouse;
	o3_mouseoff=ol_mouseoff;
	o3_closetitle=ol_closetitle;
	o3_css=ol_css;
	o3_compatmode=ol_compatmode;
	o3_fgclass=ol_fgclass;
	o3_bgclass=ol_bgclass;
	o3_textfontclass=ol_textfontclass;
	o3_captionfontclass=ol_captionfontclass;
	o3_closefontclass=ol_closefontclass;
	setRunTimeVariables();
	fnRef='';
	// Special for frame support,over must be reset...
	o3_frame=ol_frame;
	if(!(over=createDivContainer())) return false;
	parseTokens('o3_',arguments);
	if (!postParseChecks('o3_',arguments)) return false;
	if (o3_delay==0) {
		return runHook("olMain",FREPLACE);
	} else {
		o3_delayid=window.setTimeout("runHook('olMain',FREPLACE)",o3_delay);
		return false;
	}
};
// Clears popups if appropriate
function nd(time) {
	if(over&&olLoaded&&!isExclusive()) {
    hideDelay(time);
		if ( o3_removecounter >= 1 ) { o3_showingsticky=0 };
		if ( o3_showingsticky==0 ) {
			o3_allowmove=0;
			if (over!=null&&(o3_compatmode ? 1 : o3_timerid==0)) runHook("hideObject",FREPLACE,over);
		} else o3_removecounter++;
	}
	return true;
};
// The Close onMouseOver function for stickies
function cClick() {
	if(olLoaded) {
		runHook("hideObject",FREPLACE,over);
		o3_showingsticky=0;
	}
	return false;
};
// Method for setting page specific defaults.
function overlib_pagedefaults() {
	parseTokens('ol_',arguments);
};
////////
// OVERLIB MAIN FUNCTION
////////
function olMain() {
	// Make layer content
	var layerhtml,styleType;
 	runHook("olMain",FBEFORE);
	if (o3_background!=""||o3_fullhtml) {
		// Use background instead of box.
		layerhtml=runHook('ol_content_background',FALTERNATE,o3_css,o3_text,o3_background,o3_fullhtml);
	} else {
		// They want a popup box.
		// Prepare popup background
		if (o3_fgbackground!="") o3_fgbackground="background=\""+o3_fgbackground+"\"";
  	styleType=(pms[o3_css-1-pmStart]=="cssoff"||pms[o3_css-1-pmStart]=="cssclass");
		if (o3_bgbackground!="") o3_bgbackground=( styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground);
		// Prepare popup colors
		if (o3_fgcolor!="") o3_fgcolor=(styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor);
		if (o3_bgcolor!="") o3_bgcolor=(styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor);
		// Prepare popup height
		if (o3_height > 0) o3_height=(styleType ? "height=\""+o3_height+"\"" : o3_height);
		else o3_height="";
		// Decide which kinda box.
		if (o3_cap=="") {
			// Plain
			layerhtml=runHook('ol_content_simple',FALTERNATE,o3_css,o3_text);
		} else {
			// With caption
			if (o3_sticky) {
				// Show close text
				layerhtml=runHook('ol_content_caption',FALTERNATE,o3_css,o3_text,o3_cap,o3_close);
			} else {
				// No close text
				layerhtml=runHook('ol_content_caption',FALTERNATE,o3_css,o3_text,o3_cap,"");
			}
		}
	}	
	// We want it to stick!
	if (o3_sticky) {
		if (o3_timerid > 0) {
   		clearTimeout(o3_timerid);
   		o3_timerid=0;
  	}
		o3_showingsticky=1;
		o3_removecounter=0;
	}
	// Created a separate routine to generate the popup to make it easier
	// to implement a plugin capability
	if(!runHook("olCreatePopup",FREPLACE,layerhtml)) return false;
	// Prepare status bar
	if (o3_autostatus > 0) {
		o3_status=o3_text;
		if (o3_autostatus > 1) o3_status=o3_cap;
		if (o3_wrap) o3_status=o3_status.replace(/&nbsp;/g,' ');
	}
	// When placing the layer the first time, even stickies may be moved.
	o3_allowmove = 0;
	// Initiate a timer for timeout
	if (o3_timeout > 0) {          
		if (o3_timerid > 0) clearTimeout(o3_timerid);
		o3_timerid=window.setTimeout("cClick()",o3_timeout);
	}
	// Show layer
	runHook("disp",FREPLACE,o3_status);
	runHook("olMain",FAFTER);
	return (olOp && event && event.type=='mouseover' && !o3_status) ? '' : (o3_status!='');
};
////////
// LAYER GENERATION FUNCTIONS
////////
// These functions just handle popup content with tags that should adhere to the W3C standards specification.
function ol_content_simple(text) {
	var cpIsMultiple=/,/.test(o3_cellpad);
	var txt='<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" '+((olNs4||!cpIsMultiple) ? 'cellpadding="'+o3_cellpad+'" ' : '')+'cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td align="left" valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' : ((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td></tr></table></td></tr></table>';
	set_background("");
	return txt;
};
// Makes table with caption and optional close link
function ol_content_caption(text,title,close) {
	var nameId, txt, cpIsMultiple=/,/.test(o3_cellpad);
	var closing="";
	var closeevent="onmouseover";
	if (o3_closeclick==1) closeevent= (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick";
	if (o3_capicon!="") {
	  nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';
	  if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
	  o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';
	}
	if (close!="")
		closing='<td align="left" '+(!o3_compatmode && o3_closefontclass ? 'class="'+o3_closefontclass : 'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();"'+((o3_compatmode && o3_closefontclass) ? ' class="' + o3_closefontclass + '" ' : ' ')+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+'</a></td>';
	txt='<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_bgbackground+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="2" cellspacing="0"><tr><td align="left"'+(o3_captionfontclass ? ' class="'+o3_captionfontclass+'">' : '>')+(o3_captionfontclass ? '' : '<b>'+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'</b>')+'</td>'+closing+'</tr></table><table width="100%" border="0" '+((olNs4||!cpIsMultiple) ? 'cellpadding="'+o3_cellpad+'" ' : '')+'cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td align="left" valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' :((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + '</td></tr></table></td></tr></table>';
	set_background("");
	return txt;
};
// Sets the background picture,padding and lots more. :)
function ol_content_background(text,picture,hasfullhtml) {
	var txt;
	if (hasfullhtml) {
		txt=text;
	} else {
		txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td align="left" colspan="3" height="'+o3_padyt+'"></td></tr><tr><td align="left" width="'+o3_padxl+'"></td><td align="left" valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+(o3_textfontclass ? '" class="'+o3_textfontclass : '')+'">'+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td><td align="left" width="'+o3_padxr+'"></td></tr><tr><td align="left" colspan="3" height="'+o3_padyb+'"></td></tr></table>';
	}
	set_background(picture);
	return txt;
};
// Loads a picture into the div.
function set_background(pic) {
	if (pic=="") {
	  if (olNs4) over.background.src=null; 
		else if (over.style) over.style.backgroundImage="none";
	} else {
		if (olNs4) {
			over.background.src=pic;
		} else if (over.style) {
			over.style.width=o3_width+'px';
			over.style.backgroundImage="url("+pic+")";
		}
	}
};
////////
// HANDLING FUNCTIONS
////////
var olShowId=-1;
// Displays the popup
function disp(statustext) {
  // call any routine needed before showing popup
  runHook("disp",FBEFORE,statustext);
	if (o3_allowmove==0) 	{
		runHook("placeLayer",FREPLACE);
		(olNs6&&olShowId<0) ? olShowId=window.setTimeout("runHook('showObject', FREPLACE, over)", 1) : runHook("showObject", FREPLACE, over);
		o3_allowmove=(o3_sticky||!o3_followmouse) ? 0 : 1;
	}
	runHook("disp",FAFTER,statustext);
	if (statustext!="") self.status=statustext;
};
// Creates the actual popup structure
function olCreatePopup(lyrContent){
	// Write layer
	runHook("olCreatePopup",FBEFORE,lyrContent);
	if (o3_wrap) {
		var wd,ww,theObj=(olNs4 ? over : over.style);
		theObj.top=theObj.left=((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
		layerWrite(lyrContent);
		wd = (olNs4 ? over.clip.width : over.offsetWidth);
		if (wd > (ww=windowWidth())) {
			lyrContent=lyrContent.replace(/\&nbsp;/g, ' ');
			o3_width=ww;
			o3_wrap=0;
		} 
	}
	layerWrite(lyrContent);
	// have to set o3_width for placeLayer() routine if o3_wrap is turned on
	if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth);
	runHook("olCreatePopup",FAFTER,lyrContent);
	return true;
};
// Decides where we want the popup.
function placeLayer() {
	var placeX,placeY,iwidth,iheight,widthFix,winoffset,scrolloffset;
	iwidth=iheight=widthFix=0;
	if (o3_frame.innerWidth) widthFix=18;
	iwidth = windowWidth(); 
	// Horizontal scroll offset
	winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
	placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
	if (o3_frame.innerHeight) iheight=o3_frame.innerHeight;
	else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) 
		iheight=eval('o3_frame.'+docRoot+'.clientHeight');			
	// Vertical scroll offset
	scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
	placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
	// Actually move the object.
	repositionTo(over,placeX,placeY);
};
// Moves the layer
function olMouseMove(e) {
	e=(e)? e : event;
	if (e.pageX) {o3_x=e.pageX; o3_y= e.pageY;}
	else if (e.clientX) { o3_x=eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft'); o3_y=eval('e.clientY+o3_frame.'+docRoot+'.scrollTop'); }
	if (o3_allowmove==1) runHook("placeLayer",FREPLACE);
  // MouseOut handler
	if (hoveringSwitch&&!olNs4&&runHook("cursorOff",FREPLACE)) {
	   (olHideDelay ? hideDelay(olHideDelay) : cClick());
	   hoveringSwitch=!hoveringSwitch;
	}
} ;
// Fake function for 3.0 users.
function no_overlib() { return ver3fix; };
// Capture the mouse and chain other scripts.
function olMouseCapture() {
	capExtent = document;
	var fN, str='', l, k, f, wMv, sS, mseHandler = olMouseMove;
	var re = /function[ ]*(\w*)\(/;
	
	wMv = (!olIe4 && window.onmousemove);
	if (document.onmousemove || wMv) {
		if (wMv) capExtent = window;
		f = capExtent.onmousemove.toString();
		fN = f.match(re);
		if (fN==null) {
			str=f+'(e); ';
		} else if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove' || (wMv && fN[1] == 'onmousemove')) {
			if (!olOp && wMv) {
				l=f.indexOf('{')+1;
				k=f.lastIndexOf('}');
				sS = f.substring(l,k);
				if ((l = sS.indexOf('(')) != -1) {
					sS = sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,'');
					if (eval("typeof " + sS + " == 'undefined'")) window.onmousemove = null;
					else str = sS + '(e);';
				}
			}
			if (!str) {
				olCheckMouseCapture = false;
				return;
			}
		} else {
			if (fN[1]) str = fN[1]+'(e); ';
			else {
				l=f.indexOf('{')+1;
				k=f.lastIndexOf('}');
				str=f.substring(l,k) + '\n';
			}
		}
		str += 'olMouseMove(e); ';
		mseHandler = new Function('e', str);
	}

	capExtent.onmousemove = mseHandler;
	if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);
};
////////
// PARSING FUNCTIONS
////////
// Does the actual command parsing.
function parseTokens(pf,ar) {
	// What the next argument is expected to be.
	var v,i,md=-1,par=(pf!='ol_');	
	var fnMark=(par&&!ar.length ? 1 : 0);
	for (i=0; i < ar.length; i++) {
		if (md < 0) {
			// Arg is maintext,unless its a number between pmStart and pmUpper
			// then its a command.
			if (typeof ar[i]=='number'&&ar[i]>pmStart&&ar[i]<pmUpper) {
				fnMark=(par ? 1 : 0);
				i--;   // backup one so that the next block can parse it
			} else {
				switch(pf) {
					case 'ol_':
						ol_text=ar[i].toString();
						break;
					default:
						o3_text=ar[i].toString();  
				}
			}
			md=0;
		} else {
			// Note: NS4 doesn't like switch cases with vars.
			if (ar[i]>=pmCount||ar[i]==DONOTHING) { continue; };
			if (ar[i]==INARRAY) { fnMark=0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; };
			if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; };
			if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; };
			if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; };
			if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; };
			if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==CENTER||ar[i]==LEFT||ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); if(pf!='ol_') olHautoFlag=1; continue; };
			if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; };
			if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; };
			if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; };
			if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; };
			if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; };
			if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; };
			if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; };
			if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; };
			if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; };
			if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; };
			if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus==1) ? 0 : 1'); continue; };
			if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus==2) ? 0 : 2'); continue; };
			if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; }; // Same param again.
			if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; };
			if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; };
			if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; };
			if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; };
			if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; };
			if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; };
			if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; };
			if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; };
			if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; };
			if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; };
			if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; };
			if (ar[i]==BELOW||ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); if (pf!='ol_') olVautoFlag=1; continue; };
			if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; };
			if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; };
			if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; };
			if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; };
			if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; };
			if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark=0; v=null; if (typeof ar[i+1]!='number') v=ar[++i];  opt_FUNCTION(v); } continue; };
			if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; };
			if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto==0) ? 1 : 0'); continue; };
			if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto==0) ? 1 : 0'); continue; };
			if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick==0) ? 1 : 0'); continue; };
			if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap==0) ? 1 : 0'); continue; };
			if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse==1) ? 0 : 1'); continue; };
			if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff==0) ? 1 : 0'); v=ar[i+1]; if (pf != 'ol_' && eval(pf+'mouseoff') && typeof v == 'number' && (v < pmStart || v > pmUpper)) olHideDelay=ar[++i]; continue; };
			if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; };
			if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; };
			if (ar[i]==COMPATMODE) { eval(pf+'compatmode=('+pf+'compatmode==0) ? 1 : 0'); continue; };
			if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; };
			if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; };
			if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; };
			if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; };
			if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; };
   		i=parseCmdLine(pf,i,ar);
		}
	};
	if (fnMark&&o3_function) o3_text=o3_function();
	if ((pf=='o3_')&&o3_wrap) {
		o3_width=0;
		var tReg=/<.*\n*>/ig;
		if(!tReg.test(o3_text)) o3_text=o3_text.replace(/[ ]+/g,'&nbsp;');
		if(!tReg.test(o3_cap))o3_cap=o3_cap.replace(/[ ]+/g,'&nbsp;');
	}
	if ((pf=='o3_')&&o3_sticky) {
		if(!o3_close&&(o3_frame!=ol_frame)) o3_close=ol_close;
		if (o3_mouseoff&&(o3_frame==ol_frame)) opt_NOCLOSE(' ');
	}
};
////////
// LAYER FUNCTIONS
////////
// Writes to a layer
function layerWrite(txt) {
	txt += "\n";
	if (olNs4) {
		var lyr=o3_frame.document.layers['overDiv'].document;
		lyr.write(txt);
		lyr.close();
	} else if (typeof over.innerHTML != 'undefined') {
		if(olIe5&&isMac) over.innerHTML='';
		over.innerHTML=txt;
	} else {
		range=o3_frame.document.createRange();
		range.setStartAfter(over);
		domfrag=range.createContextualFragment(txt);
		while (over.hasChildNodes()) {over.removeChild(over.lastChild);};
		over.appendChild(domfrag);
	}
};
// Make an object visible
function showObject(obj) {
	runHook("showObject",FBEFORE,obj);
	var theObj=(olNs4 ? obj : obj.style);
	//theObj.visibility='visible';
	document.helper.fadeIn(obj);
	runHook("showObject",FAFTER,obj);
};
// Hides an object
function hideObject(obj) {
  runHook("hideObject",FBEFORE,obj);
	var theObj=(olNs4 ? obj : obj.style);
	if (olNs6 && olShowId>0) { clearTimeout(olShowId); olShowId=0; }
	theObj.visibility='hidden';
	theObj.top=theObj.left=((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
	if (o3_timerid > 0) clearTimeout(o3_timerid);
	if (o3_delayid > 0) clearTimeout(o3_delayid);
	o3_timerid=0;
	o3_delayid=0;
	self.status="";
	if (obj.onmouseout||obj.onmouseover) {
		if(olNs4) obj.releaseEvents(Event.MOUSEOUT||Event.MOUSEOVER);
		obj.onmouseout=obj.onmouseover=null;
	}
	runHook("hideObject",FAFTER,obj);
};
// Move a layer
function repositionTo(obj,xL,yL) {
	var theObj=(olNs4 ? obj : obj.style);
	theObj.left=xL + (!olNs4 ? 'px' : 0);
	theObj.top=yL + (!olNs4 ? 'px' : 0);
};
// Check position of cursor relative to overDiv DIVision; mouseOut function
function cursorOff() {
	var left= parseInt(over.style.left);
	var top=parseInt(over.style.top);
	var right=left+(over.offsetWidth>=parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width));
	var bottom=top+(over.offsetHeight>=o3_aboveheight ? over.offsetHeight : o3_aboveheight);
	if (o3_x < left||o3_x > right||o3_y < top||o3_y > bottom) return true;
	return false;
};
////////
// COMMAND FUNCTIONS
////////
// Calls callme or the default function.
function opt_FUNCTION(callme) {
	o3_text=(callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function'));
	return 0;
};
// Handle hovering
function opt_NOCLOSE(unused) {
	if(!unused) o3_close="";
	if (olNs4) {
	  over.captureEvents(Event.MOUSEOUT||Event.MOUSEOVER);
	  over.onmouseover=function () {if(o3_timerid > 0) {clearTimeout(o3_timerid); o3_timerid=0;}};
	  over.onmouseout=function (e) { if (olHideDelay) hideDelay(olHideDelay); else cClick(e); };
	} else 
		over.onmouseover=function () {hoveringSwitch=true; if(o3_timerid > 0) {clearTimeout(o3_timerid); o3_timerid=0;}};
	return 0;
};
// Function to scan command line arguments for multiples
function opt_MULTIPLEARGS(i, args, parameter) {
  var k=i,re,pV,str='';
  for(k=i; k<args.length; k++) {
		if(typeof args[k]=='number'&&args[k]>pmStart) break;
		str += args[k] + ',';
	}
	if (str) str=str.substring(0,--str.length);
	k--;  // reduce by one so the for loop this is in works correctly
	pV=(olNs4&&/cellpad/i.test(parameter)) ? str.split(',')[0] : str;
	eval(parameter+'="' + pV + '"');
	return k;
};
// Remove &nbsp; in texts when done.
function nbspCleanup() {
	if (o3_wrap) {
		o3_text=o3_text.replace(/\&nbsp;/g,' ');
		o3_cap=o3_cap.replace(/\&nbsp;/g,' ');
	}
};
// Escape embedded single quotes in text strings
function escSglQuote(str) {
  return str.toString().replace(/'/g,"\\'");
};

// Onload handler for window onload event
function OLonLoad_handler(e) {
	var re = /\w+\(.*\)[;\s]+/g, olre = /overlib\(|nd\(|cClick\(/, fn, l, i;
	if(!olLoaded) olLoaded=1;
	if(window.removeEventListener && e.eventPhase == 3) window.removeEventListener("load",OLonLoad_handler,false);
	else if(window.detachEvent) {
		window.detachEvent("onload",OLonLoad_handler);
		var fN = document.body.getAttribute('onload');
		if (fN) {
			fN=fN.toString().match(re);
			if (fN && fN.length) {
				for (i=0; i<fN.length; i++) {
					if (/anonymous/.test(fN[i])) continue;
					while((l=fN[i].search(/\)[;\s]+/)) != -1) {
						fn=fN[i].substring(0,l+1);
						fN[i] = fN[i].substring(l+2);
						if (olre.test(fn)) eval(fn);
					}
				}
			}
		}
	}
};
// Wraps strings in Layer Generation Functions with the correct tags
function wrapStr(endWrap,fontSizeStr,whichString) {
	var fontStr, fontColor, isClose=((whichString=='close') ? 1 : 0), hasDims=/[%\-a-z]+$/.test(fontSizeStr);
  fontSizeStr=(olNs4) ? (!hasDims ? fontSizeStr : '1') : fontSizeStr;
	if(endWrap) return (hasDims&&!olNs4) ? (isClose ? '</span>' : '</div>') : '</font>';
	else {
		fontStr='o3_'+whichString+'font';
		fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color';
		return (hasDims&&!olNs4) ? (isClose ? '<span style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">' : '<div style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">') : '<font face="'+eval(fontStr)+'" color="'+eval(fontColor)+'" size="'+(parseInt(fontSizeStr)>7 ? '7' : fontSizeStr)+'">';
	};
};
// Quotes Multi word font names; needed for CSS Standards adherence in font-family
// This is suggested but not required, multi-word font names can be kept unquoted
function quoteMultiNameFonts(theFont) {
	var v, pM=theFont.split(',');
	for (var i=0; i<pM.length; i++) {
		v=pM[i];
		v=v.replace(/^\s+/,'').replace(/\s+$/,'');
		if(/\s/.test(v) && !/['"]/.test(v)) {
			eval('v="\'"+v+"\'";');
			pM[i]=v;
		};
	};
	return pM.join();
};
// dummy function which will be overridden 
function isExclusive(args) {
	return false;
}
// Sets cellpadding style string value
function setCellPadStr(parameter) {
	var Str='', j=0, ary=new Array(), top, bottom, left, right;
	Str+='padding: ';
	ary=parameter.replace(/\s+/g,'').split(',');
	switch(ary.length) {
		case 2:
			top=bottom=ary[j];
			left=right=ary[++j];
			break;
		case 3:
			top=ary[j];
			left=right=ary[++j];
			bottom=ary[++j];
			break;
		case 4:
			top=ary[j];
			right=ary[++j];
			bottom=ary[++j];
			left=ary[++j];
			break;
	}
	Str+= ((ary.length==1) ? ary[0] + 'px;' : top + 'px ' + right + 'px ' + bottom + 'px ' + left + 'px;');
	return Str;
};
// function will delay close by time milliseconds
function hideDelay(time) {
	if (time&&!o3_delay) {
		if (o3_timerid > 0) clearTimeout(o3_timerid);
		o3_timerid=window.setTimeout("cClick()",(o3_timeout=time));
	}
};
// Was originally in the placeLayer() routine; separated out for future ease
function horizontalPlacement(browserWidth, horizontalScrollAmount, widthFix) {
	var placeX, iwidth=browserWidth, winoffset=horizontalScrollAmount;
	// HORIZONTAL PLACEMENT
	var parsedWidth=parseInt(o3_width);
	if (o3_fixx > -1||o3_relx!=null) {
		// Fixed position
		placeX=(o3_relx!=null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
	} else {  
		// If HAUTO,decide what to use.
		if (o3_hauto==1) {
			if ((o3_x-winoffset)>(iwidth/2)&&o3_hpos==RIGHT&&((o3_x-winoffset)-(parsedWidth+o3_offsetx-iwidth>(iwidth-widthFix)))) {
				o3_hpos=LEFT;
			} else if (o3_hpos==LEFT&&((o3_x-o3_offsetx-parsedWidth)<winoffset)) {
				o3_hpos=RIGHT;
			}
		}  		
		// From mouse
		if (o3_hpos==CENTER) { // Center
			placeX=o3_x+o3_offsetx-(parsedWidth/2);
			if (placeX < winoffset) placeX=winoffset;
		}
		if (o3_hpos==RIGHT) { // Right
			placeX=o3_x+o3_offsetx;
			if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
				placeX=iwidth+winoffset - parsedWidth - widthFix;
				if (placeX < 0) placeX=0;
			}
		}
		if (o3_hpos==LEFT) { // Left
			placeX=o3_x-o3_offsetx-parsedWidth;
			if (placeX < winoffset) placeX=winoffset;
		}
		// Snapping!
		if (o3_snapx > 1) {
			var snapping=placeX % o3_snapx;
			if (o3_hpos==LEFT) {
				placeX=placeX - (o3_snapx+snapping);
			} else {
				// CENTER and RIGHT
				placeX=placeX+(o3_snapx - snapping);
			}
			if (placeX < winoffset) placeX=winoffset;
		}
	}	
  return placeX;
};
// was originally in the placeLayer() routine; separated out for future ease
function verticalPlacement(browserHeight,verticalScrollAmount) {
	var placeY, iheight=browserHeight, scrolloffset=verticalScrollAmount;
	// VERTICAL PLACEMENT
	var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
	if (o3_fixy > -1||o3_rely!=null) {
		// Fixed position
		placeY=(o3_rely!=null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
	} else {
		// If VAUTO,decide what to use.
		if (o3_vauto==1) {
			if ((o3_y-scrolloffset)>(iheight/2)&&o3_vpos==BELOW&&(o3_y+parsedHeight+o3_offsety-(scrolloffset+iheight)>0)) {
				o3_vpos=ABOVE;
			} else if (o3_vpos==ABOVE&&(o3_y-(parsedHeight+o3_offsety)-scrolloffset<0)) {
				o3_vpos=BELOW;
			}
		}
		// From mouse
		if (o3_vpos==ABOVE) {
			if (o3_aboveheight==0) o3_aboveheight=parsedHeight; 
			placeY=o3_y - (o3_aboveheight+o3_offsety);
			if (placeY < scrolloffset) placeY=scrolloffset;
		} else {
			// BELOW
			placeY=o3_y+o3_offsety;
		} 
		// Snapping!
		if (o3_snapy > 1) {
			var snapping=placeY % o3_snapy;  			
			if (o3_aboveheight > 0&&o3_vpos==ABOVE) {
				placeY=placeY - (o3_snapy+snapping);
			} else {
				placeY=placeY+(o3_snapy - snapping);
			} 			
			if (placeY < scrolloffset) placeY=scrolloffset;
		}
	}
  return placeY;
};
// checks positioning flags
function checkPositionFlags() {
	if (olHautoFlag) olHautoFlag = o3_hauto=0;
	if (olVautoFlag) olVautoFlag = o3_vauto=0;
	return true;
};
// get Browser window width
function windowWidth() {
	var w;
	if (o3_frame.innerWidth) w=o3_frame.innerWidth;
	else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) 
		w=eval('o3_frame.'+docRoot+'.clientWidth');
	return w;			
};
// create the div container for popup content if it doesn't exist
function createDivContainer(id,frm,zVal) {
	id=(id||'overDiv'), frm=(frm||o3_frame), zVal=(zVal||1000);
	var objRef, divContainer = layerReference(id);
	if (divContainer==null) {
		if (olNs4) {
			divContainer=frm.document.layers[id]=new Layer(window.innerWidth,frm);
			objRef=divContainer;
		} else {
			var body = (olIe4 ? frm.document.all.tags('BODY')[0] : frm.document.getElementsByTagName("BODY")[0]);
			if (olIe4&&!document.getElementById) {
				body.insertAdjacentHTML("beforeEnd",'<div id="'+id+'"></div>');
				divContainer=layerReference(id);
			} else {
				divContainer=frm.document.createElement("DIV");
				divContainer.id = id;
				body.appendChild(divContainer);
			}
			objRef=divContainer.style;
		}
		objRef.position='absolute';
		objRef.visibility='hidden';
		objRef.zIndex=zVal;
		if (olIe4&&!olOp) objRef.left = objRef.top = '0px';
		else objRef.left = objRef.top =  -10000 + (!olNs4 ? 'px' : 0);
	}
	return divContainer;
};

// get reference to a layer of ID=id
function layerReference(id) {
	return (olNs4 ? o3_frame.document.layers[id] : (document.all ? o3_frame.document.all[id] : o3_frame.document.getElementById(id)));
};
////////
//  PLUGIN ACTIVATION FUNCTIONS
////////
// Runs plugin functions to set runtime variables.
function setRunTimeVariables(){
	if(typeof runTime!='undefined'&&runTime.length) 
		for (var k=0; k<runTime.length; k++) runTime[k]();
};
// Runs plugin functions to parse commands.
function parseCmdLine(pf,i,args) {
	if(typeof cmdLine!='undefined'&&cmdLine.length) { 
		for(var k=0; k<cmdLine.length; k++) { 
			var j=cmdLine[k](pf,i,args);
			if(j>-1) {i=j; break;}
		}
	}
	return i;
};
// Runs plugin functions to do things after parse.
function postParseChecks(pf,args){
	if (typeof postParse!='undefined'&&postParse.length) {
		for (var k=0; k<postParse.length; k++) {
			if (postParse[k](pf,args)) continue;
			return false;  // end now since have an error
		}
	}
	return true;
};
////////
//  UTILITY FUNCTIONS
////////
// Checks if something is a function.
function isFunction(fnRef) {
	var rtn=true;
	if (typeof fnRef=='object') {
		for(var i=0; i<fnRef.length; i++) {
			if (typeof fnRef[i]=='function') continue;
			rtn=false;
			break;
		}
	} else if (typeof fnRef!='function') rtn=false;
	return rtn;
};
// Converts an array into an argument string for use in eval.
function argToString(array,strtInd,argName) {
  var jS=strtInd,aS='',ar=array;
  argName=(argName ? argName : 'ar');
  if (ar.length > jS) {
    for (var k=jS; k<ar.length; k++) aS+=argName+'['+k+'], ';
    aS=aS.substring(0,aS.length-2);
  }
  return aS;
};
// Places a hook in the correct position in a hook point.
function reOrder(hookPt,fnRef,order) {
	var newPt=new Array(),match,i,j;
	if (!order||typeof order=='undefined'||typeof order=='number') return hookPt;
	if (typeof order=='function') {
		if (typeof fnRef=='object') newPt=newPt.concat(fnRef);
		else newPt[newPt.length++]=fnRef;
		for (i=0; i<hookPt.length; i++) {
			match=false;
			if (typeof fnRef=='function'&&hookPt[i]==fnRef) continue;
			else {
				for(j=0; j<fnRef.length; j++) if (hookPt[i]==fnRef[j]) {
					match=true;
					break;
				}
			}
			if(!match) newPt[newPt.length++]=hookPt[i];
		}
		newPt[newPt.length++]=order;
	} else if (typeof order=='object') {
		if (typeof fnRef=='object') newPt=newPt.concat(fnRef);
		else newPt[newPt.length++]=fnRef;
		for (j=0; j<hookPt.length; j++) {
			match=false;
			if (typeof fnRef=='function'&&hookPt[j]==fnRef) continue;
			else {
				for(i=0; i<fnRef.length; i++) if (hookPt[j]==fnRef[i]) {
					match=true;
					break;
				}
			}
			if(!match) newPt[newPt.length++]=hookPt[j];
		}
		hookPt=newPt;
		newPt.length=0;
		for (j=0; j<hookPt.length; j++) {
			match=false;
			for (i=0; i<order.length; i++) {
				if (hookPt[j]==order[i]) {
					match=true;
					break;
				}
			}
			if (!match) newPt[newPt.length++]=hookPt[j];
		}
		newPt=newPt.concat(order);
	}
	hookPt=newPt;
	return hookPt;
};
////////
//  PLUGIN REGISTRATION FUNCTIONS
////////
// Registers commands and creates constants.
function registerCommands(cmdStr) {
	if (typeof cmdStr!='string') return;
	var pM=cmdStr.split(',');
	pms=pms.concat(pM);
	for (var i=0; i< pM.length; i++) 
		eval(pM[i].toUpperCase()+'='+pmCount++);
};
// Registers no-parameter commands
function registerNoParameterCommands(cmdStr) {
	if (!cmdStr && typeof cmdStr!='string') return;
	pmt=(!pmt) ? cmdStr : pmt + ',' + cmdStr;
};
// Register a function to hook at a certain point.
function registerHook(fnHookTo,fnRef,hookType,optPm) {
	var hookPt,last=typeof optPm;
	if (fnHookTo=='plgIn'||fnHookTo=='postParse') return;
	if (typeof hookPts[fnHookTo]=='undefined') hookPts[fnHookTo]=new FunctionReference();
	hookPt=hookPts[fnHookTo];
	if (hookType!=null) {
		if (hookType == FREPLACE) {
			hookPt.ovload=fnRef;  // replace normal overlib routine
			if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef; 
		} else if (hookType == FBEFORE || hookType == FAFTER) {
			hookPt=(hookType==1 ? hookPt.before : hookPt.after);
			if (typeof fnRef=='object') hookPt=hookPt.concat(fnRef);
			else hookPt[hookPt.length++]=fnRef;
			if (optPm) hookPt=reOrder(hookPt,fnRef,optPm);
		} else if (hookType == FALTERNATE) {
			if (last=='number') hookPt.alt[pms[optPm-1-pmStart]]=fnRef;
		} else if (hookType == FCHAIN) {
			hookPt = hookPt.chain; 
			if (typeof fnRef=='object') hookPt=hookPt.concat(fnRef); // add other functions 
			else hookPt[hookPt.length++]=fnRef;
		}
		return;
	}
};
// Register a function that will set runtime variables.
function registerRunTimeFunction(fn) {
	if (isFunction(fn)) {
		if (typeof fn=='object') runTime=runTime.concat(fn);
		else runTime[runTime.length++]=fn;
	}
};
// Register a function that will handle command parsing.
function registerCmdLineFunction(fn){
	if (isFunction(fn)) {
		if (typeof fn=='object') cmdLine=cmdLine.concat(fn);
		else cmdLine[cmdLine.length++]=fn;
	}
};
// Register a function that does things after command parsing. 
function registerPostParseFunction(fn){
	if (isFunction(fn)) {
		if (typeof fn=='object') postParse=postParse.concat(fn);
		else postParse[postParse.length++]=fn;
	}
};
////////
//  PLUGIN REGISTRATION FUNCTIONS
////////
// Runs any hooks registered.
function runHook(fnHookTo,hookType) {
	var l,k,rtnVal=null,optPm,arS,ar=arguments;
	l = hookPts[fnHookTo];
	if (hookType == FREPLACE) {
		arS=argToString(ar,2);
		if (typeof l=='undefined'||!(l=l.ovload)) rtnVal=eval(fnHookTo+'('+arS+')');
		else rtnVal=eval('l('+arS+')');
	} else if (hookType == FBEFORE || hookType == FAFTER) {
		if (typeof l!='undefined') {
			l=(hookType==1 ? l.before : l.after);
			if (l.length) { 
				arS=argToString(ar,2);
				for (k=0; k < l.length; k++) eval('l[k]('+arS+')');
			}
		}
	} else if (hookType == FALTERNATE) {
		optPm=ar[2];
		arS=argToString(ar,3);
		if(typeof l=='undefined'||(l=l.alt[pms[optPm-1-pmStart]])=='undefined') rtnVal=eval(fnHookTo+'('+arS+')');
		else rtnVal=eval('l('+arS+')');
	} else if (hookType == FCHAIN) {
		arS=argToString(ar,2);
		l=l.chain;
		for (k=l.length; k > 0; k--) if((rtnVal=eval('l[k-1]('+arS+')'))!=void(0)) break;
	}
	return rtnVal;
};
////////
// OBJECT CONSTRUCTORS
////////
// Object for handling hooks.
function FunctionReference() {
	this.ovload=null;
	this.before=new Array();
	this.after=new Array();
	this.alt=new Array();
	this.chain=new Array();
};
// checks for Core Version required
function meets(reqdVersion) {
	return (!reqdVersion) ? false : this.simpleversion >= Math.round(100*parseFloat(reqdVersion));
};
// Object for simple access to the overLIB version used.
// Examples: simpleversion:351 major:3 minor:5 revision:1
function Info(version, prerelease) {
	this.version = version;
	this.prerelease = prerelease;

	this.simpleversion = Math.round(this.version*100);
	this.major = parseInt(this.simpleversion / 100);
	this.minor = parseInt(this.simpleversion / 10) - this.major * 10;
	this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10;
	this.meets = meets;
};
////////
// STANDARD REGISTRATIONS
////////
registerHook("ol_content_simple",ol_content_simple,FALTERNATE,CSSOFF);
registerHook("ol_content_caption",ol_content_caption,FALTERNATE,CSSOFF);
registerHook("ol_content_background",ol_content_background,FALTERNATE,CSSOFF);
registerHook("ol_content_simple",ol_content_simple,FALTERNATE,CSSCLASS);
registerHook("ol_content_caption",ol_content_caption,FALTERNATE,CSSCLASS);
registerHook("ol_content_background",ol_content_background,FALTERNATE,CSSCLASS);
registerPostParseFunction(checkPositionFlags);
registerHook("hideObject",nbspCleanup,FAFTER);
registerHook("horizontalPlacement", horizontalPlacement, FCHAIN);
registerHook("verticalPlacement", verticalPlacement, FCHAIN);
if(olNs4||(olIe5&&isMac)||olKq) olLoaded=1;
registerNoParameterCommands('sticky,autostatus,autostatuscap,fullhtml,hauto,vauto,closeclick,wrap,followmouse,mouseoff,compatmode');
//////
// ESTABLISH MOUSECAPTURING
//////
var olCheckMouseCapture=true;
if ((olNs4||olNs6||olIe4)) olMouseCapture();
else {
	overlib=no_overlib;
	nd=no_overlib;
	ver3fix=true;
};;
//\/////
//\  overLIB Speech Bubble Plugin
//\    Modified August 21, 2006 to reflect name change for 'createPopup' routine
//\	 Modified August 31, 2006 added the IMAGEPATH command to specify the directory where images are
//\
//\  You may not remove or change this notice.
//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
//\  Contributors are listed on the homepage.
//\  See http://www.bosrup.com/web/overlib/ for details.
//\/////
////////
// PRE-INIT
// Ignore these lines, configuration is below.
////////
if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.23)) alert('overLIB 4.23 or later is required for the Speech Bubble Plugin.');
else {
registerCommands('bubble,bubbletype,adjbubble,imagepath');
var imgWidth=[250,330,144,202,200];					 // image width in pixels
var imgHeight=[150,160,190,221,66];					 // image height in pixels
var contentWidth=[200,250,130,184,190];			 // image content width in pixels
var contentHeight=[80,85,150,176,46];				 // image content height in pixels
var padLeft=[30,40,7,9,5];								 // X displacement of content from image upper left corner
var padTop=[25,48,10,34,4];							 // Y displacement of content from image upper left corner
var arwTipX=[180,50,51,9,19];                    // x location of tip from image upper left corner
var arwTipY=[148,5,180,221,64];                  // y location of tip from image upper left corner
////////
// DEFAULT CONFIGURATION
// Settings you want everywhere are set here. All of this can also be
// changed on your html page or through an overLIB call.
////////
if (typeof ol_bubble=='undefined') var ol_bubble=0;
if (typeof ol_bubbletype=='undefined') var ol_bubbletype='';
if (typeof ol_adjbubble=='undefined') var ol_adjbubble=0;
if (typeof ol_imagepath=='undefined') var ol_imagepath='/media/images/bubble';  // images subdirectory
var olBId, olBContentWd=contentWidth;
////////
// END OF CONFIGURATION
// Don't change anything below this line, all configuration is above.
////////
////////
// INIT
////////
// Runtime variables init. Don't change for config!
var o3_bubble=0;
var o3_bubbletype='';
var o3_adjbubble=0;
var o3_imagepath='';
////////
// PLUGIN FUNCTIONS
////////
function setBubbleVariables() {
	o3_bubble=ol_bubble;
	o3_bubbletype=ol_bubbletype;
	o3_adjbubble=ol_adjbubble;
	o3_imagepath=ol_imagepath;
}
// Parses Speech Bubble commands
function parseBubbleExtras(pf,i,ar) {
	var k=i;
	if (k < ar.length) {
		if (ar[k]==BUBBLE) { eval(pf +'bubble=('+pf+'bubble==0) ? 1 : 0'); return k; }
		if (ar[k]==BUBBLETYPE) { eval(pf+'bubbletype="'+ar[++k]+'"'); return k; }
		if (ar[k]==ADJBUBBLE) { eval(pf +'adjbubble=('+pf+'adjbubble==0) ? 1 : 0'); return k; }
		if (ar[k]==IMAGEPATH) { eval(pf+'imagepath="'+ar[++k]+'"'); return k; }
	}
	return -1;
};
////////
// CHECKS FOR BUBBLE EFFECT
////////
function chkForBubbleEffect() {
	if(o3_bubble) {
		o3_bubbletype=(o3_bubbletype) ? o3_bubbletype : 'flower';
		registerImages('flower,oval,square,pushpin,quotation,roundcorners',o3_imagepath); // root names given to images (should be gif file)
		for (var i=0; i<olBTypes.length; i++) {
			if(olBTypes[i]==o3_bubbletype) {
				olBId=i;
				break;
			}
		}
		// disable inappropriate parameters
		o3_bgcolor=o3_fgcolor='';
		o3_border=0;
		if(o3_fgbackground||o3_bgbackground) o3_fgbackground=o3_bgbackground='';
		if(o3_cap) o3_cap='';
		if(o3_sticky) opt_NOCLOSE();
		if(o3_fullhtml) o3_fullhtml=0;
		if(o3_fixx>0||o3_fixy>0) o3_fixx=o3_fixy=-1;
		if(o3_relx||o3_rely) o3_relx=o3_rely=null;
		if(typeof o3_shadow!='undefined'&&o3_shadow) o3_shadow=0;
		if(o3_bubbletype!='roundcorners') {
			o3_width=olBContentWd[olBId];
			if(o3_hpos==CENTER||o3_hpos==LEFT) o3_hpos=RIGHT;
			if(o3_vpos==ABOVE) o3_vpos=BELOW;
			if(o3_vauto) o3_vauto=0;
			if(o3_hauto) o3_hauto=0;
			if(o3_wrap) o3_wrap=0;
		}
	}
	return true;
};
////////
// BUBBLE EFFECT SUPPORTING ROUTINES
////////
function registerImages(imgStr,path) {
	if(typeof imgStr!='string') return;
	if (/\/$/.test(path)) path=path.replace(/\/$/,'');
	if(typeof olBTypes=='undefined') olBTypes=imgStr.split(',');
	if(typeof olBubbleImg=='undefined') {
		olBubbleImg=new Array();
		for (var i=0; i<olBTypes.length; i++) {
			if(olBTypes[i]=='roundcorners') {
				olBubbleImg[i]=new Array();
				var o=olBubbleImg[i];
				o[0]=new Image();
				o[0].src=path+'/cornerTL.gif';
				o[1]=new Image();
				o[1].src=path+'/edgeT.gif';
				o[2]=new Image();
				o[2].src=path+'/cornerTR.gif';
				o[3]=new Image();
				o[3].src=path+'/edgeL.gif';
				o[4]=new Image();
				o[4].src=path+'/edgeR.gif';
				o[5]=new Image();
				o[5].src=path+'/cornerBL.gif';
				o[6]=new Image();
				o[6].src=path+'/edgeB.gif';
				o[7]=new Image();
				o[7].src=path+'/cornerBR.gif';
			} else {
				olBubbleImg[i]=new Image();
				olBubbleImg[i].src=path+'/'+olBTypes[i]+'.gif';
			}
		}
	}
};
function generateBubble(content) {
	if(!o3_bubble) return;
	if(o3_bubbletype=='roundcorners') return doRoundCorners(content);
	var ar,X,Y,fc=1.0,txt,sY,bHtDiff, bPadDiff=0,zIdx=0;
	var bTopPad=padTop,bLeftPad=padLeft;
	var bContentHt=contentHeight, bHt=imgHeight;
	var bWd=imgWidth, bArwTipX=arwTipX, bArwTipY=arwTipY;
//
	bHtDiff=fc*bContentHt[olBId]-(olNs4 ? over.clip.height : over.offsetHeight);
	if (o3_adjbubble) {
		fc=resizeBubble(bHtDiff, 0.5, fc);
		ar=getHeightDiff(fc);
		bHtDiff=ar[0];
		content=ar[1];
	}
	if(bHtDiff>0) bPadDiff=parseInt(0.5*bHtDiff);
	Y=(bHtDiff<0) ? fc*bTopPad[olBId] : fc*bTopPad[olBId]+bPadDiff;
	X=fc*bLeftPad[olBId];
	Y=Math.round(Y);
	X=Math.round(X);
//
	txt=(olNs4) ? '<div id="bLayer">' : ((olIe55&&olHideForm) ? backDropSource(Math.round(fc*bWd[olBId]),Math.round((bHtDiff<0 ? fc*bHt[olBId]-bHtDiff : fc*bHt[olBId])),zIdx++) : '') + '<div id="bLayer" style="position: absolute; top:0; left:0; width: '+ Math.round(fc*bWd[olBId]) +'px; z-index: '+(zIdx++)+';">';
	txt += '<img src="'+olBubbleImg[olBId].src+'" width="'+Math.round(fc*bWd[olBId])+'" height="'+Math.round((bHtDiff<0 ? fc*bHt[olBId]-bHtDiff : fc*bHt[olBId]))+'" /></div>';
	txt += (olNs4 ? '<div id="bContent">' : '<div id="bContent" style="position: absolute; top:'+Y+'px; left:'+X+'px; width: '+ Math.round(fc*olBContentWd[olBId])+'px; z-index: '+(zIdx++)+';">')+content+'</div>';
//
	layerWrite(txt);
	if(olNs4) {
		var imgLyr=over.document.layers['bLayer'];
		var cLyr=over.document.layers['bContent'];
		imgLyr.zIndex=0;
		cLyr.zIndex=1;
		cLyr.top=Y;
		cLyr.left=X;
	}
	// Set popup's new width and height values here so they are available in placeLayer()
	o3_width=Math.round(fc*bWd[olBId]);
	o3_aboveheight=Math.round(fc*bHt[olBId]);
	if(fc*bArwTipY[olBId] < 0.5*fc*bHt[olBId]) {
		sY = fc*bArwTipY[olBId]; 
	} else {
		sY = -(fc*bHt[olBId]+20);
	}
	o3_offsetx-=Math.round(fc*bArwTipX[olBId]);
	o3_offsety+=Math.round(sY);
};
function doRoundCorners(content) {
	var txt='', wd,ht, zIdx=0, o=olBubbleImg[olBId];
	wd=(olNs4) ? over.clip.width : over.offsetWidth;
	ht=(olNs4) ? over.clip.height : over.offsetHeight;
	txt = (olIe55&&olHideForm) ? backDropSource(wd+28,ht+28,zIdx++) + '<div style="position:absolute; top: 0; left: 0; z-index: '+(zIdx++)+';">' : '';
	txt+= '<table cellpadding="0" cellspacing="0" border="0">'+
				'<tr><td align="right" valign="bottom"><img src="'+o[0].src+'" width="14" height="14"'+(olNs6 ? ' style="display: block;"' : '')+' /></td><td valign="bottom"><img src="'+o[1].src+'" height="14" width="'+wd+'"'+(olNs6 ? ' style="display: block;"' : '')+' /></td><td align="left" valign="bottom"><img src="'+o[2].src+'" width="14" height="14"'+(olNs6 ? ' style="display: block;"' : '')+' /></td></tr>'+
				'<tr><td align="right"><img src="'+o[3].src+'" width="14" height="'+ht+'"'+(olNs6 ? ' style="display: block;"' : '')+' /></td><td bgcolor="#F9F9F9">'+content+'</td><td align="left"><img src="'+o[4].src+'" width="14" height="'+ht+'"'+(olNs6 ? ' style="display: block;"' : '')+' /></td></tr>'+
				'<tr><td align="right" valign="top"><img src="'+o[5].src+'" width="14" height="14" /></td><td valign="top"><img src="'+o[6].src+'" height="14" width="'+wd+'" /></td><td align="left" valign="top"><img src="'+o[7].src+'" width="14" height="14" /></td></tr></table>';
	txt += (olIe55&&olHideForm) ? '</div>' : '';
	layerWrite(txt);
	o3_width=wd+28;
	o3_aboveheight=ht+28;
};
function resizeBubble(h1, dF, fold) {
	var df,h2,fnew,alpha,cnt=0;
	while(cnt<2) {
		df=-signOf(h1)*dF;
		fnew=fold+df;
		h2=getHeightDiff(fnew)[0];
		if(Math.abs(h2)<o3_textsize) break;
		if (signOf(h1)!=signOf(h2)) {
			alpha=Math.abs(h1)/(Math.abs(h1)+Math.abs(h2));
			if(h1<0) fnew=alpha*fnew+(1.0-alpha)*fold;
			else fnew=(1.0-alpha)*fnew+alpha*fold;
		} else {
			alpha=Math.abs(h1)/(Math.abs(h2)-Math.abs(h1));
			if(h1<0) fnew=(1.0+alpha)*fold-alpha*fnew;
			else fnew=(1.0+alpha)*fnew-alpha*fold;
		}
		fold=fnew;
		h1=h2;
		dF*=0.5;
		cnt++;
	}
	return fnew;
};
function getHeightDiff(f) {
	var lyrhtml;
	o3_width=Math.round(f*contentWidth[olBId]);
	lyrhtml=runHook('ol_content_simple',FALTERNATE,o3_css,o3_text);
	layerWrite(lyrhtml);
	return [Math.round(f*contentHeight[olBId])-((olNs4) ? over.clip.height : over.offsetHeight),lyrhtml];
};
function signOf(x) {
	return (x<0) ? -1 : 1;
};
////////
// PLUGIN REGISTRATIONS
////////
registerRunTimeFunction(setBubbleVariables);
registerCmdLineFunction(parseBubbleExtras);
registerPostParseFunction(chkForBubbleEffect);
registerHook("olCreatePopup",generateBubble,FAFTER);
if(olInfo.meets(4.14)) registerNoParameterCommands('bubble,adjbubble');
if(olNs4) document.write('<style type="text/css">\n<!--\n#bLayer, #bContent {position: absolute;}\n-->\n<'+'\/style>');
};
//end 
;
function tagging_open_tagform (div_container, form) {
	if (div_container && document.getElementById("tagging_"+div_container+"_tagshow") && document.getElementById("tagging_"+div_container+"_tagform")) {
		if ((document.getElementById("tagging_"+div_container+"_tagshow").style.display != "none") ||
			(document.getElementById("tagging_"+div_container+"_tagshow_inactive").style.display != "none")) {
			document.getElementById("tagging_"+div_container+"_tagshow").style.display			= "none";
			document.getElementById("tagging_"+div_container+"_tagshow_inactive").style.display	= "none";
			document.getElementById("tagging_"+div_container+"_tagform").style.display			= "block";
			form.tags.focus();
		}
	}
	return false;
}


function tagging_save_tags (div_container, form) {
	var src_file	 = "ajax/tagging.ajax.php";
	if (document.relative_path)
		src_file	= document.relative_path + src_file;
	var params		 = "?tags="+escape(form.tags.value)+"&action="+form.action.value+"&related_id="+form.related_id.value+"&related_link="+escape(form.related_link.value);
	params			+= "&related_title="+escape(form.related_title.value)+"&type="+form.type.value;
	func_param		 = new Array ("save_tags", form, div_container);
	document.tagging_ajax.request_post(src_file, params, tagging_callback, func_param, false, false);
	return false;
}


function tagging_search_tags (form) {
	if (form.tags.value.length < 1) {
		document.tagging_helper.fadeOut(document.tagging_quicksearch_div, true);
		if (document.tagging_helper.isIE())
			document.tagging_quicksearch_iframe.style.display = "none";
		return false;
	}
	if (document.tagging_timer) {
		clearTimeout(document.tagging_timer);
	}
	document.tagging_timer = window.setTimeout(function () { tagging_search(form); }, 50);
	return false;
}


function tagging_search (form) {
	var src_file	= "ajax/tagging.ajax.php";
	if (document.relative_path)
		src_fil		 = document.relative_path + src_file;
	var params		= "?action="+form.action.value+"&tags="+escape(form.tags.value)+"&type="+form.type.value;
	func_param		= new Array ("search_tags", form);
	document.tagging_ajax.request_post(src_file, params, tagging_callback, func_param, false, false);
	return false;
}

function tagging_callback (answer, params) {
	var form			= params[1];
	var div_container	= params[2];
	switch (params[0]) {
	
		/* we tried to save some tags, let's see if everything was done */
		case "save_tags":
			if (answer) {
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				switch (splittet[0]) {
				
					/* success answer, so lets hide the input-form and show the tags we got by the server */
					case "SUCCESSFUL":
						var tags	= splittet[1].split(",");
						var tags	= new Array (splittet[1].substring(0, splittet[1].indexOf(",")), splittet[1].substring(splittet[1].indexOf(",")+1));
						/*alert(tags[0]);
						alert(tags[1]);
						return;*/
						var alltags	= tags[0];
						var mytags	= new Array (tags[1].substring(0, tags[1].indexOf(",")), tags[1].substring(tags[1].indexOf(",")+1));
						var itags	= mytags[1];
						var mytags	= mytags[0];
						var value	= "";
						if (mytags.length < 2)	
							value	= document.tagging_lang_notagmsg;
						else					
							value	= mytags;
						
						document.getElementById("tagging_"+div_container+"_alltags").innerHTML				= alltags;
						
						document.getElementById("tagging_"+div_container+"_tagshow").innerHTML				= value;
						document.getElementById("tagging_"+div_container+"_tagshow_inactive").innerHTML		= "("+itags+")";
						document.getElementById("tagging_"+div_container+"_tagform").style.display			= "none";
						var display_active		= ((mytags.length <= 0 && itags.length <= 0) || mytags.length > 0) ? "block":"none";
						var display_inactive	= (itags.length < 1) ? "none":"block";
						document.getElementById("tagging_"+div_container+"_tagshow").style.display			= display_active;
						document.getElementById("tagging_"+div_container+"_tagshow_inactive").style.display	= display_inactive;
						break;
						
					/* hmm, something was wrong, lets show error message */
					case "ERROR":
						alert(splittet[1]);
						break;
				}
			}
			break;
			
		/* we searched for tags */
		case "search_tags":
				if (answer) {

					if (document.tagging_quicksearch_div.innerHTML != answer) {
						document.tagging_quicksearch_div.innerHTML	= answer;
					}
					
					if (document.tagging_quicksearch_div.style.display != "block") {
						document.tagging_quicksearch_div.style.display	= "block";
						document.tagging_helper.fadeIn(document.tagging_quicksearch_div);
					}
					
					
					/* move result container under the form */
					var qs_dim		= document.tagging_helper.getRealDimension(document.tagging_quicksearch_div);
					var form_dim	= document.tagging_helper.getRealDimension(form);
					var qs_pos		= document.tagging_helper.getRealCoordinates(document.tagging_quicksearch_div);
					var form_pos	= document.tagging_helper.getAbsoluteCoordinates(form);
					document.tagging_helper.moveTo(document.tagging_quicksearch_div, form_pos[0]-qs_dim[0]+form_dim[0]-3, form_pos[1]+form_dim[1]+3);
					
					var qs_real_dim	= document.tagging_helper.getRealDimension("tagging_quicksearch_results");
					var qs_real_pos	= document.tagging_helper.getAbsoluteCoordinates("tagging_quicksearch_results");
										
					/* fucking IE workaround */
					if (document.tagging_helper.isIE()) {
						/*if (qs_dim[1] > 420)
							document.tagging_helper.resizeTo(document.tagging_quicksearch_div, null, 420);
						if (qs_dim[0] > 420)
							document.tagging_helper.resizeTo(document.tagging_quicksearch_div, 420, null);*/
						//document.tagging_helper.resizeTo(document.tagging_quicksearch_div, 420, 420);
						document.tagging_helper.resizeTo(document.tagging_quicksearch_iframe, qs_real_dim[0], qs_real_dim[1]);
						document.tagging_helper.moveTo(document.tagging_quicksearch_iframe, qs_real_pos[0], qs_real_pos[1]);
						document.tagging_quicksearch_iframe.style.display = "block";
					}
					
				}
			break;
	}
}


function tagging_onclick () {
	if (document.tagging_quicksearch_div.style.display != "none") {
		document.tagging_helper.fadeOut(document.tagging_quicksearch_div, true);
		if (document.tagging_helper.isIE())
			document.tagging_quicksearch_iframe.style.display = "none";
	}
}



function tagging_finish () {
	document.body.appendChild(document.tagging_quicksearch_div);
	document.tagging_helper.addEvent(document.body, "click", tagging_onclick, false);
	if (document.tagging_helper.isIE())
		document.body.appendChild(document.tagging_quicksearch_iframe);
}




document.tagging_ajax		= new Ajax(5);
document.tagging_helper		= new Helper;


document.tagging_quicksearch_div	= document.createElement("div");
document.tagging_quicksearch_div.setAttribute("id", "tagging_quicksearch_div");
document.tagging_quicksearch_div.setAttribute("class", "tagging_quicksearch_div");
document.tagging_quicksearch_div.style.display		= "none";
document.tagging_quicksearch_div.style.position		= "absolute";
document.tagging_quicksearch_div.style.width		= "420px";
document.tagging_quicksearch_div.style.height		= "520px";
document.tagging_quicksearch_div.style.maxWidth		= "420px";
document.tagging_quicksearch_div.style.maxHeight	= "520px";
document.tagging_quicksearch_div.style.bottom		= "0";
document.tagging_quicksearch_div.style.right		= "0";
document.tagging_quicksearch_div.style.overflow		= "auto";
document.tagging_quicksearch_div.style.zIndex		= "12000";
document.tagging_helper.setOpacity(document.tagging_quicksearch_div, 0);

/* fucking IE workaround */

if (document.tagging_helper.isIE()) {
	document.tagging_quicksearch_iframe	= document.createElement("div");
	document.tagging_quicksearch_iframe.setAttribute("id", "tagging_quicksearch_iframe");
	document.tagging_quicksearch_iframe.setAttribute("src", "");
	document.tagging_quicksearch_iframe.setAttribute("frameborder", "0");
	document.tagging_quicksearch_iframe.setAttribute("marginwidth", "0");
	document.tagging_quicksearch_iframe.setAttribute("scrolling", "no");
	document.tagging_quicksearch_iframe.style.display	= "none";
	document.tagging_quicksearch_iframe.style.position	= "absolute";
	document.tagging_quicksearch_iframe.style.width		= "420px";
	document.tagging_quicksearch_iframe.style.height	= "520px";
	document.tagging_quicksearch_iframe.style.border	= "0px";
	document.tagging_quicksearch_iframe.zIndex			= "11999";
}

document.tagging_helper.waitForBody(tagging_finish);
;
function member_search_member (form) {
	if (form.searchString.value.length < 1) {
		document.search_helper.fadeOut(document.search_quicksearch_div, true);
		if (document.search_helper.isIE())
			document.search_quicksearch_iframe.style.display = "none";
		return false;
	}
	if (document.search_timer) {
		clearTimeout(document.search_timer);
	}
	document.search_timer = window.setTimeout(function () { member_search(form); }, 750);
	return false;
}


function member_search (form) {
	var src_file	= "ajax/membersearch.ajax.php";
	if (document.relative_path)
		src_fil		 = document.relative_path + src_file;
	var params		= "?action="+form.action.value+"&searchString="+escape(form.searchString.value);
	func_param		= new Array ("quicksearch", form);
	document.search_ajax.request_post(src_file, params, search_callback, func_param, false, false);
	return false;
}

function search_callback (answer, params) {
	var form			= params[1];
	var div_container	= params[2];
	switch (params[0]) {
	
		/* we searched for member */
		case "quicksearch":
				if (answer) {

					if (document.search_quicksearch_div.innerHTML != answer) {
						document.search_quicksearch_div.innerHTML	= answer;
					}
					
					if (document.search_quicksearch_div.style.display != "block") {
						document.search_quicksearch_div.style.display	= "block";
						document.search_helper.fadeIn(document.search_quicksearch_div);
					}
					
					
					/* move result container under the form */
					var qs_dim		= document.search_helper.getRealDimension(document.search_quicksearch_div);
					var form_dim	= document.search_helper.getRealDimension(form);
					var qs_pos		= document.search_helper.getRealCoordinates(document.search_quicksearch_div);
					var form_pos	= document.search_helper.getAbsoluteCoordinates(form);
					document.search_helper.moveTo(document.search_quicksearch_div, form_pos[0]-qs_dim[0]+form_dim[0]-3, form_pos[1]+form_dim[1]+3);
					
					var qs_real_dim	= document.search_helper.getRealDimension("search_quicksearch_results");
					var qs_real_pos	= document.search_helper.getAbsoluteCoordinates("search_quicksearch_results");
										
					/* fucking IE workaround */
					if (document.search_helper.isIE()) {
						/*if (qs_dim[1] > 420)
							document.search_helper.resizeTo(document.search_quicksearch_div, null, 420);
						if (qs_dim[0] > 420)
							document.search_helper.resizeTo(document.search_quicksearch_div, 420, null);*/
						//document.search_helper.resizeTo(document.search_quicksearch_div, 420, 420);
						document.search_helper.resizeTo(document.search_quicksearch_iframe, qs_real_dim[0], qs_real_dim[1]);
						document.search_helper.moveTo(document.search_quicksearch_iframe, qs_real_pos[0], qs_real_pos[1]);
						document.search_quicksearch_iframe.style.display = "block";
					}

				}
			break;
	}
}

function search_onclick () {
	if (document.search_quicksearch_div.style.display != "none") {
		document.search_helper.fadeOut(document.search_quicksearch_div, true);
		if (document.search_helper.isIE())
			document.search_quicksearch_iframe.style.display = "none";
	}
}

function search_finish () {
	document.body.appendChild(document.search_quicksearch_div);
	document.search_helper.addEvent(document.body, "click", search_onclick, false);
	if (document.search_helper.isIE())
		document.body.appendChild(document.search_quicksearch_iframe);
}

function send_search(element, what) {
	if (element.choice.value == 1) {
		if (what == 0) {
			tagging_search_tags(element);
		} else {
			if (element.tags.value.length > 0)	{
				document.search_quicksearch_div.style.display = "none";
				tagging_search(element);
			}
		}
		return;
	}
	if (element.choice.value == 2) {
		var zw = element.tags.value;
		element.searchString.value = zw;
		if (what == 0) {
			member_search_member(element);
		} else {
			if (element.tags.value.length > 0)	{
				document.tagging_quicksearch_div.style.display = "none";
				member_search(element);
			}
		}
		return;
	}
}

function submit_search(element) {
	if (element.choice.value == 1) {
		element.setAttribute("action","?ext=tagging&task=search");
		return;
	}
	if (element.choice.value == 2) {
		var zw = element.tags.value;
		element.searchString.value = zw;
		element.setAttribute("action","?ext=membersearch&task=search");
		return;
	}
}

document.search_ajax		= new Ajax(5);
document.search_helper		= new Helper;


document.search_quicksearch_div	= document.createElement("div");
document.search_quicksearch_div.setAttribute("id", "search_quicksearch_div");
document.search_quicksearch_div.setAttribute("class", "search_quicksearch_div");
document.search_quicksearch_div.style.display		= "none";
document.search_quicksearch_div.style.position		= "absolute";
document.search_quicksearch_div.style.width		= "420px";
document.search_quicksearch_div.style.height		= "520px";
document.search_quicksearch_div.style.maxWidth		= "420px";
document.search_quicksearch_div.style.maxHeight	= "520px";
document.search_quicksearch_div.style.bottom		= "0";
document.search_quicksearch_div.style.right		= "0";
document.search_quicksearch_div.style.overflow		= "auto";
document.search_quicksearch_div.style.zIndex		= "12000";
document.search_helper.setOpacity(document.search_quicksearch_div, 0);

/* fucking IE workaround */

if (document.search_helper.isIE()) {
	document.search_quicksearch_iframe	= document.createElement("div");
	document.search_quicksearch_iframe.setAttribute("id", "search_quicksearch_iframe");
	document.search_quicksearch_iframe.setAttribute("src", "");
	document.search_quicksearch_iframe.setAttribute("frameborder", "0");
	document.search_quicksearch_iframe.setAttribute("marginwidth", "0");
	document.search_quicksearch_iframe.setAttribute("scrolling", "no");
	document.search_quicksearch_iframe.style.display	= "none";
	document.search_quicksearch_iframe.style.position	= "absolute";
	document.search_quicksearch_iframe.style.width		= "420px";
	document.search_quicksearch_iframe.style.height	= "520px";
	document.search_quicksearch_iframe.style.border	= "0px";
	document.search_quicksearch_iframe.zIndex			= "11999";
}

document.search_helper.waitForBody(search_finish);
;
function poll_open (id, openlink) {
	document.helper.fadeIn("poll_"+id);
	document.helper.fadeOut(openlink);
	poll_getAnswers (id);
	
	if (document.poll_active_id && document.poll_active_openlink) {
		document.helper.fadeOut("poll_"+document.poll_active_id, true);
		document.helper.fadeIn(document.poll_active_openlink);
	}
	
	document.poll_active_id			= id;
	document.poll_active_openlink	= openlink;
}

function poll_getAnswers (id, is_module) {
	var is_mod		= (is_module) ? 1:0;
	var src_file	= "ajax/poll.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params			= "?action=getPoll&id="+id+"&is_module="+is_mod;
	func_param		= new Array ("getPoll", id, is_mod);
	document.poll_ajax.request_post(src_file, params, poll_callback, func_param, false, false);	
}

function poll_addAnswer (id, answerid, is_module) {
	if (answerid == -1)
		return;

	var is_mod		= (is_module) ? 1:0;
	var src_file	= "ajax/poll.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params			= "?action=addAnswer&id="+id+"&answerid="+answerid+"&is_module="+is_mod;
	func_param		 = new Array ("addAnswer", id, is_mod);
	document.poll_ajax.request_post(src_file, params, poll_callback, func_param, false, false);	
}

function poll_addOwnAnswer (id, value) {
	var src_file	 = "ajax/poll.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params			= "?action=addOwnAnswer&id="+id+"&value="+encodeURIComponent(value);
	func_param		 = new Array ("addOwnAnswer", id);
	document.poll_ajax.request_post(src_file, params, poll_callback, func_param, false, false);	
}


function poll_showResults (id, is_module) {
	var is_mod		= (is_module) ? 1:0;
	var src_file	= "ajax/poll.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params			= "?action=showResults&id="+id+"&is_module="+is_mod;
	func_param		 = new Array ("showResults", id, is_mod);
	document.poll_ajax.request_post(src_file, params, poll_callback, func_param, false, false);	
}


function poll_callback (answer, params) {
	var action		= params[0];
	if (answer) {
		switch (action) {
			case "getPoll":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						if (params[2] == 0)
							document.getElementById("poll_"+params[1]).innerHTML = splittet[1];
						else if (params[2] == 1)
							document.getElementById("mod_poll_"+params[1]).innerHTML = splittet[1];
						break;
					
					case "ERROR":
						if (splittet[1] == "Not logged in")
							top.location = "?ext=poll";
						else
							alert(splittet[1]);
						break;
				}
				break;


			case "addAnswer":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						if (params[2] == 0)
							document.getElementById("poll_"+params[1]).innerHTML = splittet[1];
						else if (params[2] == 1)
							document.getElementById("mod_poll_"+params[1]).innerHTML = splittet[1];
						break;
					
					case "ERROR":
						if (splittet[1] == "Not logged in")
							top.location = "?ext=poll";
						else
							alert(splittet[1]);
						break;
				}
				break;


			case "addOwnAnswer":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						document.getElementById("poll_"+params[1]).innerHTML = splittet[1];
						break;
					
					case "ERROR":
						if (splittet[1] == "Not logged in")
							top.location = "?ext=poll";
						else
							alert(splittet[1]);
						break;
				}
				break;


			case "showResults":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						if (params[2] == 0)
							document.getElementById("poll_"+params[1]).innerHTML = splittet[1];
						else if (params[2] == 1)
							document.getElementById("mod_poll_"+params[1]).innerHTML = splittet[1];
						break;
					
					case "ERROR":
						/*if (splittet[1] == "Not logged in")
							top.location = "?ext=poll";
						else*/
							alert(splittet[1]);
						break;
				}
				break;

		}
	}
}


document.poll_ajax = new Ajax (5);;
function FunctionQueue () {
	var waiting		= true;
	var queue		= new Array ();
	var self		= this;
	var interval	= null;
	
	this.appendFunction = function (func) {
		queue.push(func);
	};
	
	this.perform = function () {
		if (queue.length > 0 && waiting) {
			waiting = false;
			queue[0]();
			queue.shift();
		}
	};
	
	this.callback = function () {
		waiting = true;
	};
	
	//interval = setInterval(self.perform, 20);
};;
;function GalleryViewer () {
	var helper			= new Helper();
	var ajax			= new Ajax(5);
	var self			= this;
	var ajax_basedir	= "/ajax/";
	
	var container			= document.createElement("div");
	var shadow				= document.createElement("div");
	var comments			= document.createElement("div");
	var bottom				= document.createElement("div");
	var closer				= document.createElement("div");
	var tn_image			= document.createElement("img");
	var image				= document.createElement("img");
	var loading				= document.createElement("img");
	var image_src			= "";
	var tn_dimension		= new Array ();
	var tn_targetdim		= new Array ();
	
	var dimension			= new Array (500, 540);
	var border_width		= 0;
	var shadow_width		= 6;
	var coordinates;
	var centerpoint;
	
	with (container.style) {
		width				= dimension[0]+"px";
		height				= dimension[1]+"px";
		backgroundColor		= "#FFF";
		position			= "absolute";
		display				= "none";
		border				= border_width+"px solid #000";
		zIndex				= "20000";
		overflow			= "hidden";
	}
	
	with (shadow.style) {
		width				= dimension[0]+"px";
		height				= dimension[1]+"px";
		backgroundColor		= "#000";
		position			= "absolute";
		display				= "none";
		border				= border_width+"px solid #000";
		zIndex				= "19999";
	}
	
	with (comments.style) {
		width				= dimension[0]+"px";
		height				= dimension[1]+"px";
		backgroundColor		= "#FFF";
		position			= "absolute";
		display				= "none";
		border				= border_width+"px solid #000";
		zIndex				= "3";
		top					= "0px";
		left				= "0px";
		overflow			= "hidden";
		opacity				= "0.9";
		MozOpacity			= "0.9";
		filter				= "alpha(opacity=90)"
	}
	
	with (bottom.style) {
		width				= "100%";
		textAlign			= "center";
		display				= "none";
		bottom				= "5px";
		fontSize			= "16px";
		position			= "absolute";
	}
	var txt					 = "<nobr><a href=\"javascript:void(0);\" id=\"galleryviewer_previous_link\">&lt;&lt; Vorheriges</a>&nbsp;&nbsp;";
	txt						+= "<a href=\"javascript:void(0);\" id=\"galleryviewer_comments_link\">Kommentare</a>&nbsp;&nbsp;";
	txt						+= "<a href=\"javascript:void(0);\" id=\"galleryviewer_next_link\">N&auml;chstes &gt;&gt;</a></nobr>";
	bottom.innerHTML		 = txt;
	
	
	with (closer.style) {
		textAlign			= "center";
		display				= "none";
		top					= "1px";
		right				= "1px";
		fontSize			= "11px";
		position			= "absolute";
		zIndex				= "5";
	}
	closer.innerHTML		= "<a href=\"javascript:void(0);\"><img src=\"media/images/close.gif\" width=\"25\" height=\"25\" border=\"0\" alt=\"Schliesen\" title=\"Schliessen\" /></a>";


	with (tn_image.style) {
		position			= "absolute";
		top					= "0px";
		left				= "0px";
		zIndex				= "1";
	}
	tn_image.alt			= "";
	
	with (image.style) {
		position			= "absolute";
		top					= "0px";
		left				= "0px";
		zIndex				= "2";
	}
	image.alt				= "";
	image.onload			= function () { helper.fadeOut(loading); image.style.display="block"; };
	
	with (loading.style) {
		position			= "absolute";
		top					= "2px";
		left				= "2px";
		zIndex				= "5";
		width				= "32px";
		height				= "32px";
		display				= "none";
	}
	loading.alt				= "Loading";
	loading.src				= "/media/images/loading.gif";
	loading.width			= "32";
	loading.height			= "32";
	
	
	this.display = function (picture, thumbnail, userid, albumid, picid, lastpicid, imageid) {
		if (container.style.display != "none")
			return;
				
		var pDim				= helper.getInnerDimension();
		var new_x				= (pDim[0])/2;
		var new_y				= (pDim[1])/2;
		var scrolling			= helper.getBodyScrollPosition();
		image.src				= "";
		image.style.display		= "none";
		image_src				= picture;
		tn_dimension			= helper.getRealDimension(thumbnail);
		tn_targetdim			= new Array ( tn_dimension[0]/tn_dimension[1]*500, 500);
		dimension[0]			= tn_targetdim[0];
		centerpoint				= new Array (new_x + scrolling[0], new_y + scrolling[1]);
		coordinates				= new Array (new_x - dimension[0]/2  + scrolling[0], new_y - dimension[1]/2 + scrolling[1]);
		
		self.setLinks(userid, albumid, picid, lastpicid, imageid);
		
		/*tn_image.onload			= function () { self.blendIn(); }
		tn_image.src			= thumbnail.src;*/
		tn_image.src			= thumbnail.src;	
		self.blendIn();
	};
	
	
	this.setLinks = function (userid, albumid, picid, lastpicid, imageid) {
		document.getElementById("galleryviewer_next_link").onclick = function () { self.switchImage(userid, albumid, picid, lastpicid, "next", imageid);};
		document.getElementById("galleryviewer_previous_link").onclick = function () { self.switchImage(userid, albumid, picid, lastpicid, "previous", imageid);};
		document.getElementById("galleryviewer_comments_link").onclick = function () { self.showComments(imageid); };
	};
	
	
	this.switchImage = function (userid, albumid, picid, lastpicid, direction, imageid) {
		//helper.fadeOut(comments, true, function () { self.requestNewImage(userid, albumid, picid, lastpicid, direction, imageid); });
		if (comments.style.display != "none")
			self.slideComments(1, null, function () { self.requestNewImage(userid, albumid, picid, lastpicid, direction, imageid); });
		else
			self.requestNewImage(userid, albumid, picid, lastpicid, direction, imageid);
	};
	
	this.requestNewImage = function (userid, albumid, picid, lastpicid, direction, imageid) {
		//helper.setOpacity(comments, 0.7);
		var src_file	= ajax_basedir+"gallery.ajax.php";
		var params		= "?action=switch&direction="+direction+"&userid="+userid+"&albumid="+albumid+"&picid="+picid+"&lastpicid="+lastpicid+"&imageid="+imageid;
		var func_param	= new Array ("switch", direction);

		ajax.request_post(src_file, params, self.ajaxCallback, func_param, false, false);
	};
	
	this.showComments = function (imageid) {
		if (comments.style.display == "none") {
			self.showLoading();
			var src_file	= ajax_basedir+"gallery.ajax.php";
			var params		="?action=getComments&imageid="+imageid;
			var func_param	= new Array ("getComments");

			ajax.request_post(src_file, params, self.ajaxCallback, func_param, false, false);
		} else {
			//helper.fadeOut(comments, true);
			//comments.style.display	= "none";
			self.slideComments(1);
		}
	};
	
	
	this.sendComment = function (form) {
		var	imageid	= form.imageid.value;
		var comment	= form.comment.value;

		if (imageid && imageid > 0 && comment && comment.length > 2) {
			self.showLoading();
			var src_file	= ajax_basedir+"gallery.ajax.php";
			var params		="?action=saveComment&imageid="+imageid+"&comment="+encodeURIComponent(comment);
			var func_param	= new Array ("saveComment");

			ajax.request_post(src_file, params, self.ajaxCallback, func_param, false, false);
		}
	};
	
	
	this.deleteComment = function (commentid, imageid) {
		self.showLoading();
		var src_file	= ajax_basedir+"gallery.ajax.php";
		var params		="?action=deleteComment&imageid="+imageid+"&commentid="+commentid;
		var func_param	= new Array ("deleteComment");
			
		ajax.request_post(src_file, params, self.ajaxCallback, func_param, false, false);
	};
	
	this.ajaxCallback = function (answer, params) {
		if (answer) switch (params[0]) {
			case "switch":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				switch (splittet[0]) {
				
					/* success answer */
					case "SUCCESSFUL":
						eval(splittet[1]);
						tn_image.src	= newtnpic;
						//tn_image.onload	= function () { self.resize(newuserid, newalbumid, newpicid, newlastpicid, newpic, newimageid); };
						self.resize(newuserid, newalbumid, newpicid, newlastpicid, newpic, newimageid);
						tn_targetdim	= new Array ( newtnsize[0]/newtnsize[1]*500, 500);
						dimension[0]	= tn_targetdim[0];
						break;

				}
				break;
				
			case "getComments":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				switch (splittet[0]) {
				
					/* success answer */
					case "SUCCESSFUL":
						helper.fadeOut(loading, true, function () { self.gotComments(splittet[1], true); });
						break;
					
					case "ERROR":
						alert(splittet[1]);
						helper.fadeOut(loading);
						break;

				}
				
				break;
				
			case "saveComment":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				switch (splittet[0]) {
				
					/* success answer */
					case "SUCCESSFUL":
						helper.fadeOut(loading, true, function () { self.gotComments(splittet[1], false); });
						break;
					
					case "ERROR":
						alert(splittet[1]);
						helper.fadeOut(loading);
						break;
				}

			case "deleteComment":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				switch (splittet[0]) {
				
					/* success answer */
					case "SUCCESSFUL":
						helper.fadeOut(loading, true, function () { self.gotComments(splittet[1], false); });
						break;
					
					case "ERROR":
						alert(splittet[1]);
						helper.fadeOut(loading);
						break;
				}
		}
	};
	
	
	this.gotComments = function (html, fadein) {
		comments.innerHTML = html;
		if (fadein) {
			comments.style.display	= "block";
			self.fitCommentContainerSize();
			helper.fadeOut(loading);
		}
	};
	
	this.resize = function (newuserid, newalbumid, newpicid, newlastpicid, newpic, newimageid) {
		//helper.resizeTo(tn_image, tn_targetdim[0], tn_targetdim[1]);
		//helper.resizeTo(image, tn_targetdim[0], tn_targetdim[1]);
		self.setLinks(newuserid, newalbumid, newpicid, newlastpicid, newimageid);
		image.src			= "";
		image.style.display	= "none";
		setTimeout(function () { self.fitSize(newpic); }, 10);

	};
	
	this.fitSize = function (newpic, pixelstepsize) {
		var currentDimension	= helper.getRealDimension(container);
		var currentPosition		= helper.getRealCoordinates(container);
		var pixelstepsize;
		var difference			= tn_targetdim[0]-currentDimension[0];
		
		if (difference > 0) {
			if (difference < 10)
				pixelstepsize	= (difference > 1) ? 2:1;
			else
				pixelstepsize	= 20;
		} else {
			if (difference > 10)
				pixelstepsize	= (difference < 1) ? -2:-1;
			else
				pixelstepsize	= -20;
		}
		
		helper.resizeTo(container, currentDimension[0] + pixelstepsize, null );
		helper.moveTo(container, currentPosition[0] - pixelstepsize/2, null);
		
		helper.resizeTo(shadow, currentDimension[0] + pixelstepsize - shadow_width, null);
		helper.moveTo(shadow, currentPosition[0] - pixelstepsize/2 + shadow_width/2 + shadow_width, null);

		helper.resizeTo(tn_image, currentDimension[0] + pixelstepsize, null);
		helper.resizeTo(image, currentDimension[0] + pixelstepsize, null);
							
		if ((currentDimension[0] + pixelstepsize > tn_targetdim[0] && pixelstepsize > 0) || (currentDimension[0] + pixelstepsize < tn_targetdim[0] && pixelstepsize < 0)) {
			/*var diff = currentDimension[0] + pixelstepsize - tn_targetdim[0];
			helper.resizeTo(container, tn_targetdim[0], null );
			helper.moveTo(container, currentPosition[0] - pixelstepsize/2 - diff/2, null);
		
			helper.resizeTo(shadow, tn_targetdim[0] - shadow_width, null);
			helper.moveTo(shadow, currentPosition[0] - pixelstepsize/2 - diff/2 + shadow_width/2 + shadow_width, null);*/
			
			//helper.resizeTo(tn_image, currentDimension[0] + pixelstepsize, null);
			//helper.resizeTo(image, currentDimension[0] + pixelstepsize, null);
		
			self.showLoading();
			image.src				= newpic;
			//image.onload		= function () { image.style.display = "block"; };
		} else {
			setTimeout(function() { self.fitSize(newpic, pixelstepsize); }, 10);
		}
	};
	
	
	this.fitCommentContainerSize = function () {
		var pos	= helper.getRealCoordinates(container);
		var dim	= helper.getRealDimension(container);
		//helper.moveTo(comments, pos[0], pos[1]);
		helper.moveTo(comments, -tn_targetdim[0], 0);
		helper.resizeTo(comments, dim[0], tn_targetdim[1]);
		self.slideComments(-1);
	};
	
	
	this.slideComments = function (direction, step, callbackFunc) {
		if (!step) {
			step = 0;
			comments.style.overflow	= "hidden";
		}
	
		var pos					= helper.getRealCoordinates(comments);
		var difference			= direction*pos[0];
		
		if (difference > 0) {
			if (difference < 10)
				pixelstepsize	= (difference > 1) ? 2:1;
			else
				pixelstepsize	= tn_targetdim[0]/20;
		} else {
			if (difference > 10)
				pixelstepsize	= (difference < 1) ? -2:-1;
			else
				pixelstepsize	= -tn_targetdim[0]/20;
		}

		if (step < 20) {
			helper.moveTo(comments, pos[0]+pixelstepsize, null);
			setTimeout(function () {self.slideComments(direction, ++step, callbackFunc);}, 10);
		} else {
			if (direction == -1) {
				helper.moveTo(comments, 0, 0);
				comments.style.overflow	= "auto";
			}
			else
				comments.style.display	= "none";
				
			if (callbackFunc)
				callbackFunc();
		}
	};
	
	self.blendIn = function (step) {
		if (!step) {
			step = 0;
			container.style.display		= "block";
			shadow.style.display		= "block";
			
			helper.moveTo(container, centerpoint[0]-5 - shadow_width/2, centerpoint[1]-5 - shadow_width/2);
			helper.resizeTo(container, 10, 10);
		
			helper.moveTo(shadow, centerpoint[0]-5  + shadow_width/2 + shadow_width, centerpoint[1]-5 + shadow_width/2 + shadow_width);
			helper.resizeTo(shadow, 10 - shadow_width, 10 - shadow_width);
			
			helper.resizeTo(tn_image, 10, 10);
			
			helper.resizeTo(image, 10, 10);
		}
		
		var stepsize;
		var speed;

		var current_dimension	= helper.getRealDimension(container);
		var current_coordinates	= helper.getRealCoordinates(container);
		
		if (step < 10) {
			stepsize	= Math.floor(((dimension[1]-10)/100*5)/10);
			new_w		= null;
			new_h		= current_dimension[1]+stepsize-2*border_width;
			new_x		= null;
			new_y		= current_coordinates[1]-stepsize/2;
			speed		= 5;
		} else 	if (step < 30) {
			stepsize	= Math.floor((dimension[0]-10)/20);
			new_w		= current_dimension[0]+stepsize-2*border_width;
			new_h		= null;
			new_x		= current_coordinates[0]-stepsize/2;
			new_y		= null;
			speed		= 3;		
		} else if (step < 50) {
			stepsize	= Math.floor(((dimension[1]-10)/100*95)/20);
			new_w		= null;
			new_h		= current_dimension[1]+stepsize-2*border_width;
			new_x		= null;
			new_y		= current_coordinates[1]-stepsize/2;
			speed		= 5;

		}
		
		if (step < 50) {
			
			var new_x_c		= (new_x) ? new_x:null;
			var new_y_c		= (new_y) ? new_y:null;
			
			var new_x_s		= (new_x) ? new_x  + shadow_width/2 + shadow_width:null;
			var new_y_s		= (new_y) ? new_y  + shadow_width/2 + shadow_width:null;
			
			var new_w_c		= (new_w) ? new_w:null;
			var new_h_c		= (new_h) ? new_h:null;
			
			var new_w_s		= (new_w) ? new_w - shadow_width:null;
			var new_h_s		= (new_h) ? new_h - shadow_width:null;
			
			var new_w_tn	= (new_w_c > tn_targetdim[0]) ? tn_targetdim[0]:new_w_c;
			var new_h_tn	= (new_h_c > tn_targetdim[1]) ? tn_targetdim[1]:new_h_c;
			
			helper.resizeTo(container, new_w_c, new_h_c );
			helper.moveTo(container, new_x_c, new_y_c);
		
			helper.resizeTo(shadow, new_w_s, new_h_s);
			helper.moveTo(shadow, new_x_s, new_y_s);
		
			helper.resizeTo(tn_image, new_w_tn, new_h_tn);
			helper.resizeTo(image, new_w_tn, new_h_tn);
			//helper.resizeTo(tn_image, tn_targetdim[0], tn_targetdim[1]);
			//helper.resizeTo(image, tn_targetdim[0], tn_targetdim[1]);
			setTimeout(function() { self.blendIn(++step); }, speed);
		} else {
			/*helper.resizeTo(container, dimension[0], dimension[1]);
			helper.moveTo(container, coordinates[0] - shadow_width/2, coordinates[1] - shadow_width/2);
			helper.resizeTo(shadow, dimension[0] - shadow_width, dimension[1] - shadow_width);
			helper.moveTo(shadow, coordinates[0] + shadow_width/2 + shadow_width, coordinates[1] + shadow_width/2 + shadow_width);*/
			//self.fitSize(image_src);
			self.showLoading();
			image.src				= image_src;
			/*image.style.display		= "block";*/
			bottom.style.display	= "block";
			closer.style.display	= "block";
			tn_image.onload			= null;
		}
	};
	
	this.showLoading = function () {
		helper.moveTo(loading, tn_targetdim[0]/2-16, tn_targetdim[1]/2-16);
		//loading.style.display = "block";
		helper.fadeIn(loading);
	};
	
	this.close = function () {
		container.style.display	= "none";
		bottom.style.display	= "none";
		closer.style.display	= "none";
		shadow.style.display	= "none";
		image.src				= "";
		image.style.display		= "none";
		comments.style.display	= "none";
	};
	
	this.finish = function () {
		container.appendChild(tn_image);
		container.appendChild(image);
		container.appendChild(loading);
		container.appendChild(bottom);
		container.appendChild(closer);
		container.appendChild(comments);
		document.body.appendChild(shadow);
		document.body.appendChild(container);
		//document.body.appendChild(comments);
		closer.onclick = self.close;
	}	;
	
	helper.waitForBody(self.finish);
};






function ImagePreview (container_, height_) {
	var helper		= new Helper();
	var elements	= new Array ();
	var cheight		= height_;
	var self		= this;
	var container	= (document.getElementById(container_)) ? document.getElementById(container_):container_;
	var table		= document.createElement("table");
	var tbody		= document.createElement("tbody");
	var tr			= document.createElement("tr");
	var td1			= document.createElement("td");
	var td2			= document.createElement("td");
	var td3			= document.createElement("td");
	var div1		= document.createElement("div");
	var div2		= document.createElement("div");
	var left_img	= new Image();
	var left_img_o	= new Image();
	var right_img	= new Image();
	var right_img_o	= new Image();
	var left		= 0;
	var stopfade	= true;
	var loaded		= false;
	var display		= false;
	var imgLoaded	= 0;
	var active		= false;
	
	this.add		= function (image, link, text, width) {
	
		if (!loaded) {
			setTimeout(function() {self.add(image, link, text, width);}, 100);
			return;
		}
		
		left					= (left == 0) ? 10:left;

		var imageObj;
		if (helper.isSafari())
			imageObj			= document.createElement("image");
		else
			imageObj			= new Image();
		var divObj				= document.createElement("div");
		var txtDiv				= document.createElement("div");
		var linkObj				= document.createElement("a");
		linkObj.onclick			= function(event) {if (self.mouse_inside(event)) top.location = link;};
		txtDiv.innerHTML		= text;
		txtDiv.style.display	= "none";
		txtDiv.style.position	= "absolute";
		txtDiv.style.textAlign	= "center";
		
		//imageObj.width			= width;
		imageObj.border				= "0";
		imageObj.name				= elements.length;
		imageObj.onload				= self.repaint;
		imageObj.src				= image;
		imageObj.style.visibility	= "hidden";
		eval("imageObj.onmouseover	= function (event) {self.mouseover("+elements.length+", event);};");
		eval("imageObj.onmouseout	= function (event) {self.mouseout("+elements.length+", event);};");
		
		divObj.style.width		= width+"px";
		divObj.style.position	= "absolute";
		divObj.style.left		= left+"px";
		
		left					= left + width + 20;
						
		linkObj.appendChild(imageObj);
		divObj.appendChild(linkObj);
		
		helper.setOpacity(divObj, 0.8);

		elements.push(new Array (image, link, text, width, imageObj, divObj, txtDiv, false, false));
	};
	
	
	this.display	= function () {
		if (!loaded) {
			setTimeout(self.display, 100);
			return;
		}
		
		table.width			= "100%";
		table.height		= cheight;
		table.cellspacing	= "0";
		table.cellpadding	= "0";
		
		td1.width			= "30";
		td1.style.cursor	= "pointer";
		td1.onmousedown		= function () {self.startFade(); self.fade(1);};
		td1.onmouseup		= function () {self.stopFade();};
		td1.onmouseover		= function () {td1.style.backgroundColor='#FFF';};
		td1.onmouseout		= function () {td1.style.backgroundColor='#FFF';};
		
		td2.width			= "100%";
		td2.style.position	= "relative";
		
		td3.width			= "30";
		td3.style.cursor	= "pointer";
		td3.onmousedown		= function () {self.startFade(); self.fade(-1);};
		td3.onmouseup		= function () {self.stopFade();};
		/*td3.onmouseover		= function () { 
			// td3.innerHTML	= "<img src=\"media/images/arrow_right_active.gif\" width=\"15\" height=\"60\" border=\"0\" />"
			};
		td3.onmouseout		= function () {
			// td3.innerHTML	= "<img src=\"media/images/arrow_right.gif\" width=\"15\" height=\"60\" border=\"0\" />"};
		}*/

		div1.style,width	= "100%";
		div1.style.height	= cheight+"px";
		div1.style.overflow	= "hidden";
		div1.style.position	= "relative";
		
		div2.style,width	= "100%";
		div2.style.height	= cheight+"px";
		div2.style.overflow	= "visible";
		div2.style.position	= "absolute";
		
		for (var i=0; i < elements.length; i++) {
			div2.appendChild(elements[i][5]);
			div2.appendChild(elements[i][6]);
		}
		
		
		//td1.innerHTML	= "<img src=\"media/images/arrow_left.gif\" width=\"15\" height=\"60\" border=\"0\" />"
		
		//td3.innerHTML	= "<img src=\"media/images/arrow_right.gif\" width=\"15\" height=\"60\" border=\"0\" />"
		
		with (left_img) {
			src		= "media/images/arrow_left.gif";
			width	= "15";
			height	= "60";
			border	= "0";
		}
		
		with (left_img_o) {
			src				= "media/images/arrow_left_active.gif";
			width			= "15";
			height			= "60";
			border			= "0";
			style.display	= "none";
		}
		
		with (right_img) {
			src		= "media/images/arrow_right.gif";
			width	= "15";
			height	= "60";
			border	= "0";
		}
		
		with (right_img_o) {
			src				= "media/images/arrow_right_active.gif";
			width			= "15";
			height			= "60";
			border			= "0";
			style.display	= "none";
		}
		
		td1.appendChild(left_img);
		td1.appendChild(left_img_o);
		td1.onmouseover		= function() {left_img.style.display = "none"; left_img_o.style.display = "";};
		td1.onmouseout		= function() {left_img.style.display = ""; left_img_o.style.display = "none";};
		
		
		td3.appendChild(right_img);
		td3.appendChild(right_img_o);
		td3.onmouseover		= function() {right_img.style.display = "none"; right_img_o.style.display = "";};
		td3.onmouseout		= function() {right_img.style.display = ""; right_img_o.style.display = "none";};
		
		
		div1.appendChild(div2);
		
		td2.appendChild(div1);
		
		tr.appendChild(td1);
		tr.appendChild(td2);
		tr.appendChild(td3);
		
		tbody.appendChild(tr);
		
		table.appendChild(tbody);
		
		container.appendChild(table);
		
		display = true;		
		self.repaint();
	};
	
	this.startFade		= function () {
		stopfade = false;
	};
	
	this.stopFade		= function () {
		stopfade = true;
	};
	
	this.fade			= function (direction) {
		if (stopfade || !active)
			return;
			
		var	dim		= helper.getRealDimension(td2);
		var lastel	= elements[elements.length-1][5];
		var firstel	= elements[0][5];
		var coord_l	= helper.getRealCoordinates(lastel);
		var dim_l	= helper.getRealDimension(lastel);
		var coord_f	= helper.getRealCoordinates(firstel);
		
		var step	= (helper.isSafari()) ? 30:20;
		
		/*if (dim_l[0] + coord_l[0] + 10 < dim[0] && direction == -1) {
			self.stopFade();
			return;
		}
		
		if (coord_f[0] + 10 > 0 && direction == 1) {
			self.stopFade();
			return;
		}*/
		
		
		/*for (var i=0; i < elements.length; i++) {
			var el		= elements[i][5];
			var coords	= helper.getRealCoordinates(el);
			helper.moveTo(el, coords[0] + direction*step, null);
		}*/
		
		var coords	= helper.getRealCoordinates(div2);
		var dim		= helper.getRealDimension(div2);
		var dim1	= helper.getRealDimension(div1);

		if ((coords[0] >= 0 && direction == 1) || (coords[0] + dim[0] < dim1[0] && direction == -1)) {
			self.stopFade();
			return;
		}
		
		helper.moveTo(div2, coords[0] + direction*step, null);
		
		setTimeout(function() {self.fade(direction);}, 10);
	};
	
	
	this.mouseover		= function (elId) {
		if (helper.isSafari() && !self.mouse_inside(event)) return;
		if (helper.isSafari() && elements[elId][8]) return;
		if (!active) return;
		//elements[elId][7].appendFunction(function () {self.highlight(elId);});
		self.highlight(elId);
	};

	this.mouseout		= function (elId) {
		if (helper.isSafari() && !self.mouse_inside(event)) return;
		if (helper.isSafari() && !elements[elId][8]) return;
		if (!active) return;
		//elements[elId][7].appendFunction(function () {self.dehighlight(elId);});
		self.dehighlight(elId);
	};
	
	this.mouse_inside	= function (event) {
		mouse_x		= document.all ? window.event.clientX : event.pageX;
		mouse_y		= document.all ? window.event.clientY : event.pageY;
		var coords	= helper.getAbsoluteCoordinates(div1);
		var dim		= helper.getRealDimension(div1);
		
		if (mouse_x >= coords[0] && mouse_x <= coords[0] + dim[0] &&
			mouse_y >= coords[1] && mouse_y <= coords[1] + dim[1])
			return true;
			
		return false;
	};
	
	this.highlight		= function (elId, step, force) {
		var el	= elements[elId];
		
		if (!el) return;		
		
		if (!step) {
			
			step = 0;
			var coords		= helper.getRealCoordinates(el[5]);
			var dim			= helper.getRealDimension(el[5]);
			el[5].style.zIndex	= "1";
			helper.resizeTo(el[6], dim[0] + 20, dim[1] + 20);
			helper.moveTo(el[6], coords[0] - 10, coords[1] + dim[1] + 1);
			helper.setOpacity(el[5], 1);
		}
		
		if (step < 5) {
			if (step < 2)
				;//helper.incOpacity(el[5], 0.1);
				
			var coords		= helper.getRealCoordinates(el[5]);
			var dim			= helper.getRealDimension(el[5]);
			var top			= coords[1] - 2;
			var left		= coords[0] - 2;
			var width		= dim[0] + 4;
			var height		= Math.round(dim[1]/dim[0]*width);
		
			helper.resizeTo(el[5], width, height);
			helper.moveTo(el[5], left, top);
			helper.resizeTo(el[4], width, height);
			helper.moveTo(el[4], left, top);

			step++;
			setTimeout(function() {self.highlight(elId, step, true);}, 20);
		} else {
			//el[7].callback();
			var coords		= helper.getRealCoordinates(el[5]);
			var dim			= helper.getRealDimension(el[5]);
			helper.moveTo(el[6], null, coords[1] + dim[1]);
			el[6].style.display = "block";
			el[8]				= true;
		}
	};
	
	this.dehighlight		= function (elId, step, force) {
		var el	= elements[elId];
		
		if (!el) return;
		
		
		if (!step) {
			step = 0;
			helper.setOpacity(el[5], 0.8);
		}

		if (step < 5) {
			if (step < 2)
				;//helper.incOpacity(el[5], -0.1);
				
			var coords		= helper.getRealCoordinates(el[5]);
			var dim			= helper.getRealDimension(el[5]);
			var top			= coords[1] + 2;
			var left		= coords[0] + 2;
			var width		= dim[0] - 4;
			var height		= Math.round(dim[1]/dim[0]*width);
		
			helper.resizeTo(el[5], width, height);
			helper.moveTo(el[5], left, top);
			helper.resizeTo(el[4], width, height);
			helper.moveTo(el[4], left, top);
			
			step++;
			setTimeout(function() {self.dehighlight(elId, step, true);}, 20);
		} else {
			//el[7].callback();
			el[6].style.display = "none";
			el[8]				= false;
			el[5].style.zIndex	= "0";
		}
	};
	
	
	this.repaint		= function () {
		if (display && imgLoaded >= elements.length) {
			var left	= 10;
			var i		= 0;
			var dim;
			for (i=0; i < elements.length; i++) {
				dim			= helper.getRealDimension(elements[i][4]);
				var newdim	= new Array (dim[0], dim[1]);
				if (dim[0] > dim[1]) {
					newdim[0]	= elements[i][3];
					newdim[1]	= dim[1]/dim[0]*newdim[0];
				} else {
					newdim[1]	= elements[i][3];
					newdim[0]	= dim[0]/dim[1]*newdim[1];
				}
				dim = newdim;
				var top	= Math.round((cheight - dim[1])/2);
				elements[i][5].style.top	= top+"px";
				helper.resizeTo(elements[i][5], dim[0], dim[1]);
				helper.resizeTo(elements[i][4], dim[0], dim[1]);
				elements[i][4].width	= dim[0];
				elements[i][4].height	= dim[1];
				helper.moveTo(elements[i][5], left, top);
				left += dim[0] + 10;
				elements[i][4].style.visibility	= "visible";
			}
			helper.resizeTo(div2, left, null);
			self.scrollToCenter();
		} else {
			if (imgLoaded < elements.length) {
				imgLoaded++;
			} else {
				setTimeout(self.repaint, 100);
			}
		}	
			
	};
	
	
	this.scrollToCenter	= function (step, stepsize) {
		var dimension	= helper.getRealDimension(div2);
		var dimension1	= helper.getRealDimension(div1);
		var coords		= helper.getRealCoordinates(div2);
		var target		= -Math.round(dimension[0]/2) + Math.round(dimension1[0]/2);
		if (!step) {
			step		= 0;
			/*if (step < 10)
				stepsize	= Math.round(((dimension[0]/2) - dimension1[0]/2)/40);
			else if (step < 20) {
				stepsize	= Math.round(((dimension[0]/2) - dimension1[0]/2)/20);
			} else 
				stepsize	= Math.round(((dimension[0]/2) - dimension1[0]/2)/10);*/
		}
			
		var diff		= coords[0] - target;
		var direction	= (diff < 0) ? -1:1;
		diff			= (diff < 0) ? (-1)*diff:diff;
			
			
		if (diff == 0) {
			active = true;
			return;
		}
			
		if (diff > 500) {
			stepsize = 45;
		} else if (diff > 400) {
			stepsize = 40;
		} else if (diff > 300) {
			stepsize = 30;
		} else if (diff > 200) {
			stepsize = 25;
		} else if (diff > 100) {
			stepsize = 20;
		} else if (diff > 50) {
			stepsize = 15;
		} else if (diff > 25) {
			stepsize = 10;
		} else if (diff > 12) {
			stepsize = 5;
		} else if (diff > 6) {
			stepsize = 3;
		} else if (diff > 3) {
			stepsize = 2;
		} else  {
			stepsize = 1;
		}
		
		helper.moveTo(div2, coords[0]-(direction*stepsize), null);
		step++;
		setTimeout(function(){self.scrollToCenter(step, stepsize);}, 10);
		
		/*if (step < 	30000) {
			helper.moveTo(div2, coords[0]-stepsize, null);
			step++;
			setTimeout(function(){self.scrollToCenter(step, stepsize);}, 10);
		} else {
			active = true;;//helper.moveTo(div2, -Math.round(dimension[0]/2) + Math.round(dimension1[0]/2), null)
		}*/
	};
	
	this.finish			= function () {
		loaded = true;
	};
	
	helper.waitForBody(self.finish);
};


document.galleryviewer = new GalleryViewer ();;
function newsletter_subscribe () {
	var src_file	 = "ajax/newsletter.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params               = "?insert=subscribe&newslemail="+encodeURIComponent(document.newsletterform.newslemail.value)+"&isuserlogged="+encodeURIComponent(document.newsletterform.isuserlogged.value);
	func_param		 = new Array ("subscribe");
	document.newsletter_ajax.request_post(src_file, params, newsletter_callback, func_param, false, false);	
}

function newsletter_unsubscribe () {
	var src_file	 = "ajax/newsletter.ajax.php";
	if (document.relative_path)
		src_file		 = document.relative_path + src_file;
	params			= "?delete=unsubscribe&newslemail="+encodeURIComponent(document.newsletterform.newslemail.value)+"&isuserlogged="+encodeURIComponent(document.newsletterform.isuserlogged.value);
	func_param		 = new Array ("unsubscribe");
	document.newsletter_ajax.request_post(src_file, params, newsletter_callback, func_param, false, false);	
}



function newsletter_callback (answer, params) {
	var action		= params[0];
	if (answer) {
		switch (action) {
			case "subscribe":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						document.getElementById("newsletter_form").getElementsByTagName("div")[2].style.visibility	= "";
						document.getElementById("newsletter_form").getElementsByTagName("div")[0].style.visibility	= "hidden";
						document.getElementById("newslmsgnor").style.display = "none";
						document.getElementById("newslmsgsuberr").style.display = "none";
						document.getElementById("newslmsgtouus").style.display = "none";
						document.getElementById("newslmsgunsuberr").style.display = "none";
						document.getElementById("newslmsgtous").style.display = "block";
						break;
					
					case "ERROR":
						document.getElementById("newslmsgnor").style.display = "none";
						document.getElementById("newslmsgtous").style.display = "none";
						document.getElementById("newslmsgtouus").style.display = "none";
						document.getElementById("newslmsgunsuberr").style.display = "none";
						document.getElementById("newslmsgsuberr").style.display = "block";
						break;
				}
				break;


			case "unsubscribe":
				var first_space	= answer.indexOf(" ");
				var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
				switch (splittet[0]) {
					case "SUCCESSFUL":
						document.getElementById("newsletter_form").getElementsByTagName("div")[0].style.visibility	= "";
						document.getElementById("newsletter_form").getElementsByTagName("div")[2].style.visibility	= "hidden";
						document.getElementById("newslmsgnor").style.display = "none";
						document.getElementById("newslmsgsuberr").style.display = "none";
						document.getElementById("newslmsgtous").style.display = "none";
						document.getElementById("newslmsgunsuberr").style.display = "none";
						document.getElementById("newslmsgtouus").style.display = "block";
						break;
					
					case "ERROR":
						document.getElementById("newslmsgnor").style.display = "none";
						document.getElementById("newslmsgtous").style.display = "none";
						document.getElementById("newslmsgtouus").style.display = "none";
						document.getElementById("newslmsgtouus").style.display = "none";
						document.getElementById("newslmsgunsuberr").style.display = "block";
						break;
				}
				break;

		}
	}
}

document.newsletter_ajax		= new Ajax(5);
;
;function Pagination (pContainerId, pAjaxFile, pNumberPerPage, pNumberTotal, pAjaxParams, pTxtFirst, pTxtLast, pScrollToTop, pPageContainer, pCallbackFunc, pMyFunc) {
	var containerId		= pContainerId;
	var container		= null;
	var ajaxFile		= pAjaxFile;
	var txtFirst		= (pTxtFirst) ? pTxtFirst:"Erste";
	var txtLast			= (pTxtLast) ? pTxtLast:"Letzte";
	var ajaxParams		= pAjaxParams;
	var numberPerPage	= pNumberPerPage;
	var numberTotal		= pNumberTotal;
	var helper			= new Helper();
	var ajax			= new Ajax(15);
	var self			= this;
	var current			= 0;
	var pageContainer	= null;
	var myFunc			= pMyFunc;
	var myFuncA			= null;
	var scrollToTop		= pScrollToTop;
	var callbackFunc	= pCallbackFunc;

	if (numberTotal <= numberPerPage)
		return;

	if (!pPageContainer || pPageContainer.length < 1) {
		document.write("<div class=\"pagination\" id=\"pagination_"+containerId+"\"></div>");
		pageContainer	= document.getElementById("pagination_"+containerId);
	} else {
		pageContainer	= (document.getElementById(pPageContainer)) ? document.getElementById(pPageContainer):pPageContainer;
		pageContainer.className	= "pagination";
	};
	
	this.buildPageContainer	= function () {
		if (numberTotal <= numberPerPage) {
			if (pageContainer && pageContainer.style)
				pageContainer.style.display	= "none";
			if (container == null)
				container = document.getElementById(containerId);
			return;
		} else {
			if (pageContainer && pageContainer.style) 
				pageContainer.style.display	= "";
		}
		if (container == null)
			container = document.getElementById(containerId);
		container.innerHTML	= "<span href=\"javascript:void(0);\" id=\"anker_"+containerId+"\"></span>" + container.innerHTML;
		var html	 = "";
		var vis		 = (parseInt(current) != 0) ? "visible":"hidden";
		html		+= "<a class=\"paginate_first\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" style=\"visibility: "+vis+"\" onclick=\"document.pagination_"+containerId+".onclick(0);\">"+txtFirst+"</a>";
		vis			 = (parseInt(current)-parseInt(numberPerPage) >= 0) ? "visible":"hidden";
		html		+= "<a class=\"paginate_first\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" style=\"visibility: "+vis+"\" onclick=\"document.pagination_"+containerId+".onclick("+(current-numberPerPage)+");\">&lt;</a>";
		var page	 = 1;
		var i		 = 0;
		
		var test	 = Math.ceil(numberTotal/numberPerPage);
		
		if (test < 11) {
			for (; i < numberTotal; i += numberPerPage) {
				if (i != current)
					html	+= "<a class=\"paginate_middle\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" onclick=\"document.pagination_"+containerId+".onclick("+i+");\">"+(page++)+"</a>";
				else
					html	+= "<span class=\"current\"><strong>"+(page++)+"</strong></span>";
			}
		} else {
			cPage		= Math.ceil(current/numberPerPage) + 1;
			var tPages	= Math.ceil(numberTotal/numberPerPage);
			for (; i < numberTotal; i += numberPerPage) {
				if (cPage <= 5) {
					if (page > 11) {
						page++;
						continue;
					}
				} else if (cPage > 5 && cPage + 5 <= tPages) {
					if (page < cPage - 5 || page > cPage + 5) {
						page++;
						continue;
					}
				} else {
					if (page + 10 < tPages) {
						page++;
						continue;
					}
				}
				if (i != current)
					html	+= "<a class=\"paginate_middle\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" onclick=\"document.pagination_"+containerId+".onclick("+i+");\">"+page+"</a>";
				else
					html	+= "<span class=\"current\"><strong>"+page+"</strong></span>";
				page++;
			}
		}
		
		
		vis			 = (parseInt(current)+parseInt(numberPerPage) <= (parseInt(i)-parseInt(numberPerPage))) ? "visible":"hidden";//alert("current="+current+",numberPerPage="+numberPerPage+"i="+i);
		html		+= "<a  class=\"paginate_last\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" style=\"visibility: "+vis+"\" onclick=\"document.pagination_"+containerId+".onclick("+(current+numberPerPage)+");\">&gt;</a>";
		vis			 = (current != (i-numberPerPage)) ? "visible":"hidden";
		html		+= "<a  class=\"paginate_last\" onfocus=\"this.blur();\" href=\"javascript:void(0);\" style=\"visibility: "+vis+"\" onclick=\"document.pagination_"+containerId+".onclick("+(i-numberPerPage)+");\">"+txtLast+"</a>";
		pageContainer.innerHTML = html;
	};
	
	this.onclick		= function (pageIndex) {
		if (pageIndex == current)
			return;
		if (myFunc) {
			myFunc(pageIndex);
			return;
		}
		if (scrollToTop) {
			var pos	= document.helper.getAbsoluteCoordinates("anker_"+containerId);
			window.scrollTo(0, pos[1]);
		}
		var src_file	 = ajaxFile;
		if (document.relative_path)
			src_file		 = document.relative_path + src_file;
		params			 = "?pageIndex="+pageIndex+"&numberPerPage="+numberPerPage+"&numberTotal="+numberTotal+"&"+ajaxParams;
		func_param		 = new Array ("switch", pageIndex);
		container.innerHTML	= "<table border=\"0\" width=\"100%\" height=\"100%\"><tr><td style=\"text-align: center; vertical-align: middle;\"><img src=\"media/images/loading.gif\" width=\"25\"></td></tr></table>";
		ajax.request_post(src_file, params, self.callback, func_param, false, false);	
	};

	this.reload	= function () {
		var pageIndex = current;
		if (myFunc) {
			myFunc(pageIndex);
			return;
		}
		if (scrollToTop) {
			var pos	= document.helper.getAbsoluteCoordinates("anker_"+containerId);
			window.scrollTo(0, pos[1]);
		}
		var src_file	 = ajaxFile;
		if (document.relative_path)
			src_file		 = document.relative_path + src_file;
		params			 = "?pageIndex="+pageIndex+"&numberPerPage="+numberPerPage+"&numberTotal="+numberTotal+"&"+ajaxParams;
		func_param		 = new Array ("switch", pageIndex);
		container.innerHTML	= "<table border=\"0\" width=\"100%\" height=\"100%\"><tr><td style=\"text-align: center; vertical-align: middle;\"><img src=\"media/images/loading.gif\" width=\"25\"></td></tr></table>";
		ajax.request_post(src_file, params, self.callback, func_param, false, false);	
	};

	this.setCurrent		= function (index) {
		current			= index;
		self.buildPageContainer();
	};
	
	this.getCurrent		= function () {
		return current;
	};
	
	this.setTotalNumber	= function (number) {
		numberTotal = number;
		self.buildPageContainer();
	};
	
	this.setMyFunction	= function (myfunc) {
		myFunc	= myfunc;
	};

	this.setMyFunctionAfter	= function (myfuncA) {
		myFuncA	= myfuncA;
	};

	this.callback		= function (answer, params) {
		var action		= params[0];
		if (answer) {
			switch (action) {
				case "switch":
					if (answer == "login") {
						location.reload();
						return;
					}

					var first_space	= answer.indexOf(" ");
					var splittet	= new Array (answer.substring(0, first_space), answer.substring(first_space+1));
				
					switch (splittet[0]) {
						case "SUCCESSFUL":
							current = params[1];
							container.innerHTML = "<span href=\"javascript:void(0);\" id=\"anker_"+containerId+"\"></span>" + splittet[1];
							self.buildPageContainer();
							if (myFuncA) {
								myFuncA();
								return;
							}
							if (callbackFunc)
								window.setTimeout(callbackFunc, 1);
							break;
					
						case "ERROR":
							alert(splittet[1]);
							break;
							
						default:
							alert(splittet[1]);
					}
					break;
			}
		}
	};

	helper.waitForBody(self.buildPageContainer);
};;
;function Tooltip () {

	var self		= this;
	var helper		= new Helper();
	var body_loaded	= false;
	var helperdivs	= new Array ();


	this.show = function (e, index, source, width, height) {
		container = helperdivs[index][0];
		if (container.style.display == "none") {
			container.style.display		= "block";
			container.style.visibility	= "visible";
			if (width != "auto") helper.resizeTo(container, width, null);
			if (height != "auto") helper.resizeTo(container, null, height);
			var dim = helper.getRealScrollDimension(container);
			if (height == "auto")
				height	= dim[1];
			if (width == "auto")
				width	= dim[0];
			container.style.display		= "none";
			helper.setOpacity(container, 0);
			container.style.display	= "";
			//container.style.overflow	= "hidden";
			source = document.getElementById(source);
	
			var coord	= helper.getAbsoluteCoordinates(source);
			var dim		= helper.getRealDimension(source);
			var dim2	= helper.getRealDimension(container);
			var middle	= new Array (coord[0] + dim[0]/2, coord[1] + dim[1]/2);

			if (!document.tooltips_over_dim[index]) {
				document.tooltips_over_dim[index] = new Array (width, height);
			}
		
			var targetcoord		= new Array (middle[0] - document.tooltips_over_dim[index][0]/2, middle[1] - document.tooltips_over_dim[index][1]/2);

			if (targetcoord[0] < 0)
				targetcoord[0] = 0;
			if (targetcoord[1] < 0)
				targetcoord[1] = 0;
			

			helper.resizeTo(container, 33, 33);
			var dim2	= helper.getRealDimension(container);
			helper.moveTo(container, middle[0] - 33, middle[1] - 33);
			self.slideIn(index, targetcoord, document.tooltips_over_dim[index]);
		}
	};

	this.slideIn  = function (index, targetcoord, targetdim, step, stepsize_d, stepsize_c, startdim, direction) {
		//var index = container;
		container = helperdivs[index][0];
		var dim			= helper.getRealDimension(container);
		var coord		= helper.getAbsoluteCoordinates(container);

	
		if (!direction)
			direction = 1;
		
		if (!step) {
			step = 0;

			stepsize_d	= new Array ((targetdim[0]-33)/20, (targetdim[1]-33)/20);
			stepsize_c	= new Array ((coord[0]-targetcoord[0])/10, (coord[1]-targetcoord[1])/10);
			startdim	= new Array (33, 33);
		}

			
		if (step < 19) {
			step++;
			if (step < 9) {
				if (direction == 1) 
					helper.incOpacity(container, 0.1);

			}
			if (direction == 1) {
				helper.moveTo(container, coord[0]-stepsize_c[0]/2, coord[1]-stepsize_c[1]/2);
				helper.resizeTo(container, startdim[0]+((step+1)*stepsize_d[0]), startdim[1]+((step+1)*stepsize_d[1]));
			} else {
				helper.moveTo(container, coord[0]+stepsize_c[0]/2, coord[1]+stepsize_c[1]/2);
				helper.resizeTo(container, document.tooltips_over_dim[index][0]-((step+1)*stepsize_d[0]), document.tooltips_over_dim[index][1]-((step+1)*stepsize_d[1]));
			}
			setTimeout(function () { self.slideIn(index, targetcoord, targetdim, step, stepsize_d, stepsize_c, startdim, direction); }, 10);
		} else {
			if (direction == 1) {
				container.style.display	= "block";
				//helper.moveTo(container, targetcoord[0], targetcoord[1]);
				//container.style.overflow	= "auto";
			} else {
				container.style.display = "none";
				helper.resizeTo(container, 33, 33);
			}
		}
	};

	this.hide = function (event, index, source) {

		if (!body_loaded) return;
		
		
		for (var i=0; i < helperdivs.length; i++) {
			container	= helperdivs[i][0];
			source		= helperdivs[i][1];
		
			var mouse_x		= document.all ? window.event.clientX : event.pageX;
			var mouse_y		= document.all ? window.event.clientY : event.pageY;
			var range		= 2;
			
			if (!container) continue;

			var coords		= helper.getRealCoordinates(container);
			var dim			= helper.getRealDimension(container);


		
			if (	(container.style.display == "block") &&
					(coords[0] > mouse_x + range || coords[0]+dim[0] < mouse_x - range || coords[1] > mouse_y + range || coords[1]+dim[1] < mouse_y - range)
				) {
	
				//container.style.overflow	= "hidden";
			
				source = document.getElementById(source);

				var coord	= helper.getAbsoluteCoordinates(source);
				dim			= helper.getRealDimension(source);
				var dim2	= helper.getRealDimension(container);
				var middle	= new Array (coord[0] + dim[1]/2, coord[1] + dim[1]/2);
			
				container.style.display = "";
		
				var targetcoord = new Array (middle[0] - document.tooltips_over_dim[i][0]/2, middle[1] - document.tooltips_over_dim[i][1]/2);

				if (targetcoord[0] < 0)
					targetcoord[0] = 0;
				if (targetcoord[1] < 0)
					targetcoord[1] = 0;

				self.slideIn(i, targetcoord, document.tooltips_over_dim[i], null, null, null, null, -1);
			}
		}

	};
	
	this.hide2 = function (e, container, force) {return;
		hidestreams (e, container, force);
	};


	this.overContainer = function (container) {
		document.tooltips_over[container]	= true;
	};
	
	this.register = function (container, source, width, height, event) {
		if (!body_loaded) {
			setTimeout(function() { self.register(container, source, width, height, event); }, 500);
			return;
		}
		
		if (!container)
			return;
		
		if (document.getElementById(container))
			container	= document.getElementById(container);
		
		if (!container || !source || !document.getElementById(source))
			return;
		
		var content		= container.innerHTML;
		
		container.style.display	= "none";
		container				= container.cloneNode(true);
		helperdivs.push(new Array (container, source));
		
		//container			= helperdivs[helperdivs.length-1][0];
		var index			= helperdivs.length-1;
		container.innerHTML	= content;
		
		container.style.display		= "block";
		container.style.visibility	= "visible";
		

		if (!event)
			document.getElementById(source).onmouseover = function(e) { self.show(e, index, source, width, height);};
		else if (event == "onclick")
			document.getElementById(source).onclick = function(e) { self.show(e, index, source, width, height);};
		//document.getElementById(source).onmouseout = function(e) { self.hide2(e, container, true);};
		//document.getElementById(container).onmouseout = function(e) { self.hide2(e, container, true);};
		helper.resizeTo(container, 33, 33);
		
		//helper.addEvent(container, "mouseover", function () { self.overContainer(helperdivs.length-1) }, false);	
		container.style.display			= "none";
		//container.style.overflow		= "hidden";
		container.style.position		= "absolute";
		container.style.zIndex			= "20000";
		//container.style.overflow		= "hidden";
		document.body.appendChild(container);
	};
	
	this.finish = function () {
		body_loaded = true;
		helper.addEvent(document.body, "mousemove", function(e){self.hide(e, -1, 0);}, false);	
	};

	helper.waitForBody(function() { self.finish(); });

};

document.tooltip			= new Tooltip ();
document.tooltips_over		= new Object();
document.tooltips_over_dim	= new Object();;
