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

var Prototype = {
  Version: '1.6.0.3',

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

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

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

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

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

/* Based on Alex Arnell's inheritance implementation. */
var Class = {
  create: function() {
    var parent = null, properties = $A(arguments);
    if (Object.isFunction(properties[0]))
      parent = properties.shift();

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

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

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

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

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

    klass.prototype.constructor = klass;

    return klass;
  }
};

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

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

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

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

    return this;
  }
};

var Abstract = { };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return returnValue;
  }
};

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

RegExp.escape = function(str) {
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};

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

var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

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

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

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

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

Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return camelized;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

var $break = { };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Array.from = $A;

Object.extend(Array.prototype, Enumerable);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  activeRequestCount: 0
};

Ajax.Responders = {
  responders: [],

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

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

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

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

Object.extend(Ajax.Responders, Enumerable);

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

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

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

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

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

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

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

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

    this.parameters = params;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  status:      0,
  statusText: '',

  getStatus: Ajax.Request.prototype.getStatus,

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

  getHeader: Ajax.Request.prototype.getHeader,

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

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

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

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

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

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

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

    $super(url, options);
  },

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

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

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

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

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

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

    this.start();
  },

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

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

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

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

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

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

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

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

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

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

Element.cache = { };

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

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

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

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

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

  update: function(element, content) {
    element = $(element);
    if (content && content.toElement) content = content.toElement();
    if (Object.isElement(content)) return element.update().insert(content);
    content = Object.toHTML(content);
    element.innerHTML = content.stripScripts();
    content.evalScripts.bind(content).defer();
    return element;
  },

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

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

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

    var content, insert, tagName, childNodes;

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

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

      content = Object.toHTML(content);

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

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

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

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

    return element;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return false;
  },

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

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

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

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

    return element;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return $(document.body);
  },

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

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

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

    } while (element = element.offsetParent);

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

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

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

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

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

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

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

Element.Methods.identify.counter = 1;

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

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

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

          // returns the border-box dimensions rather than the content-box
          // dimensions, so we subtract padding and borders from the value
          var dim = parseInt(proceed(element, style), 10);

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

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

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

else if (Prototype.Browser.IE) {
  // IE doesn't report offsets correctly for static elements, so we change them
  // to "relative" to get the values, then change them back.
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    function(proceed, element) {
      element = $(element);
      // IE throws an error if element is not in document
      try { element.offsetParent }
      catch(e) { return $(document.body) }
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);
      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    }
  );

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

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

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

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

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

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

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

  Element._attributeTranslations = {
    read: {
      names: {
        'class': 'className',
        'for':   'htmlFor'
      },
      values: {
        _getAttr: function(element, attribute) {
          return element.getAttribute(attribute, 2);
        },
        _getAttrNode: function(element, attribute) {
          var node = element.getAttributeNode(attribute);
          return node ? node.value : "";
        },
        _getEv: function(element, attribute) {
          attribute = element.getAttribute(attribute);
          return attribute ? attribute.toString().slice(23, -2) : null;
        },
        _flag: function(element, attribute) {
          return $(element).hasAttribute(attribute) ? attribute : null;
        },
        style: function(element) {
          return element.style.cssText.toLowerCase();
        },
        title: function(element) {
          return element.title;
        }
      }
    }
  };

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

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

  Element._attributeTranslations.has = {};

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

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

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

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

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

    return element;
  };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Element.Methods.ByTag = { };

Object.extend(Element, Element.Methods);

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

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

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

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

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

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

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

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

document.viewport = {
  getDimensions: function() {
    var dimensions = { }, B = Prototype.Browser;
    $w('width height').each(function(d) {
      var D = d.capitalize();
      if (B.WebKit && !document.evaluate) {
        // Safari <3.0 needs self.innerWidth/Height
        dimensions[d] = self['inner' + D];
      } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
        // Opera <9.5 needs document.body.clientWidth/Height
        dimensions[d] = document.body['client' + D]
      } else {
        dimensions[d] = document.documentElement['client' + D];
      }
    });
    return dimensions;
  },

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

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

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

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

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

  },

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

    var e = this.expression;

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

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

    return true;
  },

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

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

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

    return true;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return match;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  getElements: function(form) {
    return $A($(form).getElementsByTagName('*')).inject([],
      function(elements, child) {
        if (Form.Element.Serializers[child.tagName.toLowerCase()])
          elements.push(Element.extend(child));
        return elements;
      }
    );
  },

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

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

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

    return matchingInputs;
  },

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

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

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

    return firstByIndex ? firstByIndex : elements.find(function(element) {
      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  cache: { },

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

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

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

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

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

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

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

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

      if (currentTarget && currentTarget.tagName) {
        // Firefox screws up the "click" event when moving between radio buttons
        // via arrow keys. It also screws up the "load" and "error" events on images,
        // reporting the document as the target instead of the original image.
        if (type === 'load' || type === 'error' ||
          (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
            && currentTarget.type === 'radio'))
              node = currentTarget;
      }
      if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
      return Element.extend(node);
    },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      return element;
    },

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

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

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

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

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

      destroyWrapper(id, eventName, handler);

      return element;
    },

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

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

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

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

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

Object.extend(Event, Event.Methods);

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

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

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

  var timer;

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

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

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

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

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

Hash.toQueryString = Object.toQueryString;

var Toggle = { display: Element.toggle };

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

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

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

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

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

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

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

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

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = Element.cumulativeOffset(element);

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

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

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

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

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

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

  cumulativeOffset: Element.Methods.cumulativeOffset,

  positionedOffset: Element.Methods.positionedOffset,

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

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

  realOffset: Element.Methods.cumulativeScrollOffset,

  offsetParent: Element.Methods.getOffsetParent,

  page: Element.Methods.viewportOffset,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Element.addMethods();PID_MENU = 14;
PID_FOOTER = 7;

PID_BULLEVARD = 2;
PID_ACTIONS = 3;
PID_EVENTS = 4;
PID_COMMUNITY = 5;
PID_HEROES = 6;

PID_BULLEVARD_DETAIL = 31;
PID_ACTIONS_DETAIL = 33;
PID_EVENTS_DETAIL = 32;
PID_HEROES_DETAIL = 40;
PID_USER_PROFILE = 44;

PID_GALLERIES_IMAGES = 998;
PID_GALLERIES_VIDEOS = 999;

PID_GALLERIES_DETAIL_IMAGE = 26;
PID_GALLERIES_DETAIL_VIDEO = 37;

PID_GALLERIES_SINGLE_IMAGE = 49;

PID_LOCATIONS_DETAIL = 46;

PID_BULLEVARD_TAGS = 28;
PID_ACTIONS_TAGS = 29;
PID_EVENTS_TAGS = 42;

PID_TAG = 50;

PID_SEARCH = 48;

PID_HEROES_AJAX = 41;
PID_PROFILE_AJAX = 45;
PID_SHAREIT_AJAX = 51;
PID_COMMENT_AJAX = 39;
PID_MAPSEARCH_AJAX = 57;
PID_PIPOP_AJAX = 77;
PID_PILATEST_AJAX = 78;
PID_PIDASHBOARD_AJAX = 82;

PID_PROFILE = 16;

CAT_ACTIONS = 1;
CAT_BULLEVARD = 2;

PID_PASSWORD_STRENGTH = 95;

COMMON = {
  articleDetailMap : {
    1 : PID_ACTIONS_DETAIL,
    2 : PID_BULLEVARD_DETAIL
  }
};

TEASER_IMG_WIDTH = 470;
TEASER_IMG_HEIGHT = 268;

var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);

var WEB_ROOT = 'http://'+ document.location.host + '/';

var container_number = 0;
var last_container = 0;

function __init() {
	var search = document.location.search;
	var req = {};
	if (search) {
		if (search.substring(0, 1) == '?') 
			search = search.substring(1);

		var params = search.split('&');
		for (var i = 0; i < params.length; i++)	{
			var param = params[i];
			var arr = param.split('=');
			var key = arr[0];
			var value = arr[1];
			req[key] = value;
		}
	}
	window.REQUEST = req;

	var path = document.location.href.substr(('http://'+document.location.host).length);
	var iof = path.indexOf('?');
	var pathparts = (iof != -1 ? path.substr(0, path.indexOf('?')) : path).split('/');
	pathparts.pop();
	path = pathparts.join('/')+'/';

	window.PATH = path;
}
__init();
var use_teaser_title_image = true;
var scale_teaser_images = true;

function isGalleryLightboxOpen() {
	return (window.lightente && window.lightente.isWindowOpened);
}

function hideGalleryLightbox() {
	window.lightente.closeWindow(false);
}

function openLoginWindow() {
	if (window.loginWindowIsOpen) return;
	window.loginWindowIsOpen = true;
	
	if (isGalleryLightboxOpen()) {
		hideGalleryLightbox();
	} else {
		showEmbeds(false);
	}

	var link = document.getElementById('login_link');
	var url = link.href;
//	var pos = url.indexOf('&urlAfterLogin');
	//if (pos > 0) url = url.substr(0, pos);

	// realurl version
	url = stripOutGetParam('urlAfterLogin', url, 2);

//	url += '&urlAfterLogin=' + escape(getLoginRedirectURL());
// realurl version
	url += 'urlAfterLogin/' + escape(getLoginRedirectURL()) + '/';
	link.href = url;
	myLightWindow.activate(null, link);
}

function stripOutGetParam(param, url, parts) {
	// realurl conformity
	var strip = 0;
	var pathParts = url.split('/');
	var newParts = [];
	for (var i = 0; i < pathParts.length; i++) {
		if ((strip > 0 || pathParts[i] == param) && strip < parts) {
			strip++;
		} else {
			newParts[newParts.length] = pathParts[i];
		}
	}
	return (newParts.join('/'));
}

var site_search_cleared = false;
function siteSearchFocus() {
	if (! site_search_cleared) {
		document.getElementById('site_search_text').value = ''
		site_search_cleared = true;
	}
}
var map_search_cleared = false;

function mapSearchFocus(id) {
	if (! map_search_cleared) {
		$(id ? id : 'map_search_text').value = ''
		map_search_cleared = true;
	}
}

function onPageLoad()
{
	//fixBackgroundPNG(document.getElementById("roll_bottom_text"));

	//fixPNG('search_bg_img');
	if (window.partymode)
	{
	    document.getElementById('search_lense').src= '/fileadmin/sitetemplates/i/search_lense_night.gif';
	}
//	fixPNG('detail_icon_bull');
	fixPNG('detail_icon_fav');

	for (var i = 0; i < onLoadFuncs.length; i++)
		onLoadFuncs[i]();

	if (window.lightwindowInit)
		lightwindowInit();
	_restorePageContext();
	// wordWrap();
}

function fixBackgroundPNG(obj)
{
  if ((version >= 5.5) && (version < 7) && (document.body.filters))
    {
    obj.style.background = "";
    obj.style.cssText = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/roll_bottom_text_background.png',sizingMethod='scale')";
    }
  else
  {
    obj.style.background = "url(i/roll_bottom_text_background.png) no-repeat";
  }
}

function RBTeaser(jsRef) {
	this.jsRef = jsRef;
	eval(jsRef + ' = this');
	this.data = null;
	this.flipIndex = 1;
	this.autoFlip = true;
	this.watchedImages = {};
	this.controlMap = false;
	this.lastMarker = null;

//	this.controlMap = true;
}

RBTeaser.prototype.flipTimeout = 5000;
RBTeaser.prototype.flipStepTimeout = 40;
RBTeaser.prototype.flipSteps = 20;
RBTeaser.prototype.titleWrap = ['<div class="teaser_title">','</div><div class="teaser_title_separator"></div>'];

RBTeaser.prototype.setData = function(data) {
	this.data = data;
}

RBTeaser.prototype.setUserContentPanel = function(obj) {
	this.userContentPanel = obj;
}

RBTeaser.prototype.start = function() {
	this.curDataIndex = Math.floor(Math.random() * this.data.length);
	if (window.location.href.substr(window.location.href.length-2)!='87')
		if (window.rbmap_loaded)
			rbmap.setSpecific(true);
	this.prepareFlip();
	this._doFlip();
}

RBTeaser.prototype.getNextDataIndex = function() {
	var i = this.curDataIndex + 1;
	if (i >= this.data.length)
		i = 0;
	return i;
}

RBTeaser.prototype.prepareFlip = function() {
	var nextDataIndex = this.getNextDataIndex();
	var nextFlipIndex = (this.flipIndex == 1) ? 2 : 1;
	var suf = nextFlipIndex;

	var row = this.data[nextDataIndex];
	
	if (!row) {
		return;
	}
/* obsoleted, url comes from server
	var title = row.title;
	title = title.replace(/\r\n/g, " ");
	title = title.replace(/\r/g, " ");
	var orig_lines = title.split("\n");
	var lines = [];
	
	for (var i = 0; i < orig_lines.length; i++) {
		if (orig_lines[i].trim().length) lines[lines.length] = orig_lines[i];
	}

	var w = this.titleWrap;
	var titleHtml = w[0] + lines.join(w[1] + w[0]) + w[1];

	var page_id;
	var param;
	var img_url;
	var catname;
	var catid;

	switch (row.realm) {
		case 'article':
			param = 'article_id';
			// img_url = WEB_ROOT + 'uploads/cd_articles/'+ row.image;
			img_url = 'uploads/cd_articles/'+ row.image;
			
			switch (row.mc) {
				case CAT_ACTIONS:
					page_id = PID_ACTIONS_DETAIL;
					catname = 'SPORTS';
					catid = PID_ACTIONS; 
					break;
				case CAT_BULLEVARD:
					page_id = PID_BULLEVARD_DETAIL;
					catname = 'CULTURE';
					catid = PID_BULLEVARD;
					break;
				default:
					alert('teaser ERROR: invalid article category:' + row.mc);
					return;
			}

			break;
		
		case 'gallery':
			// img_url = WEB_ROOT + row.image;
			img_url = row.image;
			
			switch (row.type) {
				case 0:
					page_id = PID_GALLERIES_DETAIL_IMAGE;
					param = 'tx_cdgalleries_pi1[uid]';
					catname = 'PHOTOS';
					catid = PID_GALLERIES_IMAGES;
					break;
				case 1:
					page_id = PID_GALLERIES_DETAIL_VIDEO;
					param = 'tx_cdgalleries_pivideo[uid]';
					catname = 'VIDEOS';
					catid = PID_GALLERIES_VIDEOS;
					break;
				default:
					alert('teaser ERROR: invalid gallery type:' + row.type);
					return;
			}

			break;

		default:
			alert('ERROR: invalid main category:' + row.mc);
			return;
	}
// TODO: in new design - do something with teaser link
	// var page_url = WEB_ROOT + 'index.php?id=' + page_id +'&'+param+'='+ row.uid;
	// some of the above is obsoleted by the fact that url comes in json
*/
	var page_url = row.url;

	var linkel = document.getElementById('teaser_link'+suf);
	if (linkel) {
		linkel.href = page_url;
	}
/*
//	document.getElementById('teaser_title_link_cat'+suf).innerHTML = '<a href="index.php?id='+catid+'">'+catname+':</a>';
	// document.getElementById('teaser_img'+suf).src = img_url;

	var urlParams = {
		pwd: 'runme',
		image: img_url,
		size: 'main',
		text: row.title
	};
	// var conv_img_url = '/typo3conf/ext/rb_misc/modteaser/convert.php?' + serializeUrl(urlParams);
*/
	var conv_img_url = row.image_url;
	
	document.getElementById('teaser_img'+suf).src = conv_img_url;
//	document.getElementById('teaser_img'+suf).style.backgroundImage = 'url('+conv_img_url+')';
//	this.watchImage(conv_img_url);
}

RBTeaser.prototype.scheduleFlip = function() {
	this.prepareFlip();
	this._flipTimer = setTimeout(this.jsRef+'.flip()', this.flipTimeout);
}

RBTeaser.prototype.stopFlipping = function() {
	if (this._flipTimer) {
		clearTimeout(this._flipTimer);
		delete this._flipTimer;
		delete this._flipStep;
		delete this._flipSteps;
		var fromIndex = this.flipIndex;
		// var fromEls = ['teaser_container', 'teaser_head'];
		// var fromEls = ['teaser_img'];
		var fromEls = ['teaser_container'];

		for(var i = 0; i < fromEls.length; i++) {
			var fromEl = document.getElementById(fromEls[i]+fromIndex);
			if (fromEl) this.setOpacity(fromEl, 1);
		}
		if (this.controlMap && window.rbmap_loaded && rbmap.isAsyncControlAllowed()) {
			var row = this.data[this.curDataIndex];
			this.navigateMapTo(row);
		}
	}
}

RBTeaser.prototype.resumeFlipping = function() {
	if (this._flipTimer || OverlayVisible()) return;
	this.scheduleFlip();
}

RBTeaser.prototype.handleOnMouseOver = function(event) {
	this.stopFlipping();
}

RBTeaser.prototype.handleOnMouseOut = function(event) {
	this.resumeFlipping();
}

RBTeaser.prototype.isFlipping = function() {
	return !(!this._flipSteps);
}

RBTeaser.prototype.flip = function() {
	this._flipSteps = this.flipSteps;
	this._flipStep = 0;
	this._flipTimer = window.setInterval(this.jsRef+'._flipStepFunc()', this.flipStepTimeout); // this._flipStepFunc();
	if (this.controlMap && window.rbmap_loaded && rbmap.isAsyncControlAllowed()) {
		var nextDataIndex = this.getNextDataIndex();
		var row = this.data[nextDataIndex];
		this.navigateMapTo(row);
	}
}

RBTeaser.prototype.navigateMapTo = function(obj) {
	var cat;
	if (!obj) return;
	if (obj.realm == 'article')
		cat = (obj.mc == CAT_BULLEVARD) ? 'b' : 'a';
	else // gallery
		cat = (obj.type == 0) ? 'gi' : 'gv';
	if (window.rbmap_loaded) {
		rbmap.closeInfoWindow();
		var m = rbmap.findMarker(cat, obj.uid);

		if (m) {
			if (this.lastMarker) {
				this.lastMarker.isSpecific = false;
			}
			// rbmap.panTo(m.lng, m.lat);
			m.isSpecific = true;
			m.openInfoWindow();
			this.lastMarker = m;
		}
	}
}

RBTeaser.prototype._flipStepFunc = function() {
	this._flipStep++;

	var fromIndex = this.flipIndex;
	// var fromEls = ['teaser_container', 'teaser_head'];
	// var fromEls = ['teaser_img'];
	var fromEls = ['teaser_container'];

	if (this._flipStep > this._flipSteps) {
		window.clearInterval(this._flipTimer);
		this._doFlip();
	} else {
		// next flip frame
		var fromOpaq = 1 - this._flipStep / this._flipSteps;
		
		for (var i = 0; i < fromEls.length; i++) {
			var fromEl = document.getElementById(fromEls[i]+fromIndex);
			if (fromEl) this.setOpacity(fromEl, fromOpaq);
		}

//		this._flipTimer = setTimeout(this.jsRef+'._flipStepFunc()', this.flipStepTimeout);
	}
}

RBTeaser.prototype._doFlip = function() {
	var fromIndex = this.flipIndex;
	var toIndex = (this.flipIndex == 1) ? 2 : 1;
	// var elements = ['teaser_container', 'teaser_head'];
	// var elements = ['teaser_img'];
	var elements = ['teaser_container'];

	delete this._flipTimer;
	delete this._flipStep;
	delete this._flipSteps;

	for (var i = 0; i < elements.length; i++) {
		var fromEl = document.getElementById(elements[i]+fromIndex);
		var toEl = document.getElementById(elements[i]+toIndex);
		if (fromEl && toEl) {
			var fromZ = fromEl.style.zIndex;
			fromEl.style.zIndex = toEl.style.zIndex;
			toEl.style.zIndex = fromZ;
			this.setOpacity(fromEl, 1);
		}
	}
	
	this.curDataIndex = this.getNextDataIndex();
	var object = this.getCurObject();
	
	if (this.userContentPanel) {
		this.userContentPanel.setCurObject(object);
	}

	this.flipIndex = toIndex;

	if (this.autoFlip)
		this.scheduleFlip();
}

RBTeaser.prototype.setOpacity = function(el, opacity) {
	el.style.opacity = opacity;
	el.style.filter = 'alpha(opacity='+(opacity * 100)+')';
}

RBTeaser.prototype.getCurObject = function() {
	return this.data[this.curDataIndex];
}

RBTeaser.prototype.updateContentTools = function() {
	if (! contentTools)
		return;
	for (var i = 0; i < this.data.length; i++) {
		var obj = this.data[i];
//		contentTools.setObjectBullCount(obj.realm, obj.uid, obj.b);
		contentTools.setObjectCommentCount(obj.realm, obj.uid, obj.c);
		contentTools.setObjectViewCount(obj.realm, obj.uid, obj.v);
	}
}

RBTeaser.prototype.watchImage = function(src) {
	var _this = this;
	imageWatcher.addImage(src, function(src) {
		_this.onImageComplete(src);
	});
}

RBTeaser.prototype.onImageComplete = function(src) {
	for (var i = 1; i <= 2; i++) {
		var docImg = document.getElementById('teaser_img'+i);
		if (docImg.src == src) {
			if (scale_teaser_images) {
				// this is a fix for initial teaser images with wrong dimensions
				var watchImg = imageWatcher.getImage(src);
				if (watchImg.width == 476 && watchImg.height == 268) {
					docImg.style.width = TEASER_IMG_WIDTH + 'px';
					docImg.style.height = TEASER_IMG_HEIGHT + 'px';
				} else {
					var size = getBoxedImageSize(watchImg.width, watchImg.height, TEASER_IMG_WIDTH, TEASER_IMG_HEIGHT);
					// dbg('teaser_img'+i+' '+src+' '+size[0]+'x'+size[1]);
					docImg.style.width = size[0] + 'px';
					docImg.style.height = size[1] + 'px';
				}
			} else {
				docImg.style.width = TEASER_IMG_WIDTH + 'px';
				docImg.style.height = TEASER_IMG_HEIGHT + 'px';
			}
		}
	}
}

var imageWatcher;
ImageWatcher = function() {
	this.ready = {};
	this.loading = {};
	setInterval('imageWatcher.check()', 50);
}
ImageWatcher.prototype.addImage = function(src, callback) {
	var image = new Image();
	image.src = src;
	if (image.complete) {
		this.ready[src] = {src:src, image:image};
		callback(src);
	} else
		this.loading[src] = {src:src, image:image, callback:callback};
}

ImageWatcher.prototype.check = function() {
	var src;
	var moveKeys = [];
	for (src in this.loading) {
		var info = this.loading[src];
		if (info.image.complete)
			moveKeys[moveKeys.length] = src;
	}
	for (var i = 0; i < moveKeys.length; i++) {
		var src = moveKeys[i];
		var obj = this.loading[src];
		delete this.loading[src];
		this.ready[src] = obj;
		if (obj.callback)
			obj.callback(src);
		delete obj.callback;
	}
}
ImageWatcher.prototype.getImage = function(src) {
	var info = this.ready[src];
	if (! info)
		info = this.loading[src];
	return info.image;
}
imageWatcher = new ImageWatcher();

var contentTools;
ContentTools = function(jsRef) {
	this.jsRef = jsRef;
	eval(jsRef + ' = this');
	this.counts = {};
}
/*ContentTools.prototype.getObjectBullCount = function(realm, uid) {
	return this.getObjectCount(realm, uid, 'bull');
}
ContentTools.prototype.setObjectBullCount = function(realm, uid, count) {
	this.setObjectCount(realm, uid, 'bull', count);
} */
ContentTools.prototype.getObjectCommentCount = function(realm, uid) {
	return this.getObjectCount(realm, uid, 'comment');
}
ContentTools.prototype.setObjectCommentCount = function(realm, uid, count) {
	this.setObjectCount(realm, uid, 'comment', count);
}
ContentTools.prototype.getObjectViewCount = function(realm, uid) {
	return this.getObjectCount(realm, uid, 'view');
}
ContentTools.prototype.setObjectViewCount = function(realm, uid, count) {
	this.setObjectCount(realm, uid, 'view', count);
}
ContentTools.prototype.setObjectCount = function(realm, uid, what, count) {
	if (! this.counts[realm])
		this.counts[realm] = {};
	if (! this.counts[realm][uid])
		this.counts[realm][uid] = {};
	this.counts[realm][uid][what] = count;
}
ContentTools.prototype.getObjectCount = function(realm, uid, what) {
	if (! this.counts[realm] || ! this.counts[realm][uid] || 
		! this.counts[realm][uid][what])
		return 0;
	else
		return this.counts[realm][uid][what];
}

var userContentTools;
var rb_user_uid;

UserContentTools = function(){
	this.listeners = [];
}
UserContentTools.prototype.SHIFT = 3;
UserContentTools.prototype.FL_BULL = 1;
UserContentTools.prototype.FL_FAV = 2;
UserContentTools.prototype.FL_IM_HERE = 4;

UserContentTools.prototype.setData = function(data) {
	var outerMap = {};
	var mask = ~(0xFFFFFFFF << this.SHIFT);
	var key;
	for (key in data) {
		// var arr = data[key].split(',');
		var arr = data[key];
		var map = {};
		for (var i = 0; i < arr.length; i++) {
			var el = arr[i];
			var uid = el >> this.SHIFT;
			var bits = el & mask;
			map[uid] = bits;
		}
		outerMap[key] = map;
	}
	this.map = outerMap;
	this.counts = {};
}

UserContentTools.prototype.getImageGalleryStats = function(object, callback) {
	var _this = this;
	new Ajax.Request('/ajax/userlinks.php?action=imggalstats&realm=' + object.realm + '&uid='+ object.uid + '&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";

			var json;
			eval('json = '+transport.responseText);

			var uid;
			var realm = 'gallery_image';
			if (window.contentTools) {
				for (uid in json) {
					var o = json[uid];
//					contentTools.setObjectBullCount(realm, uid, o[0]);
					contentTools.setObjectViewCount(realm, uid, o[1]);
					contentTools.setObjectCommentCount(realm, uid, o[2]);
					_this._notifyListeners({realm:realm,uid:uid});
				}
			}
			
		},
		onFailure: function(){ alert('Unable to update view count') }
	});
}

/*
UserContentTools.prototype.bull = function(object, callback) {
	new Ajax.Request('/ajax/userlinks.php?action=bull&realm=' + object.realm + '&uid='+ object.uid + '&slt='+Math.random(), {
		method:'get',
		onSuccess: (function(transport) {
			var response = transport.responseText || "no response text";
			// alert(transport.responseText);
			var arr = transport.responseText.split('|');
			var res = arr[0];
			var count = arr[1];
			var newBullFlag = (res == 'bulled');
			this.setObjectFlag(object.realm, object.uid, this.FL_BULL, newBullFlag);
			if (contentTools) contentTools.setObjectBullCount(object.realm, object.uid, count);
			this._notifyListeners(object);
			if (callback) callback();
		}).bind(this),
		onFailure: function(){ alert('Unable to bull object') }
	});
}
*/
UserContentTools.prototype.fav = function(object, callback) {
	var _this = this;
	new Ajax.Request('/ajax/userlinks.php?action=fav&realm=' + object.realm + '&uid='+ object.uid + '&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";
			var newFavFlag = (response == 'fav');
			_this.setObjectFlag(object.realm, object.uid, _this.FL_FAV, newFavFlag);
			_this._notifyListeners(object);
			if (callback)
				callback(object);
		},
		onFailure: function(){ alert('Unable to save object') }
	});
}

UserContentTools.prototype.im_here = function(object, callback) {
	var _this = this;
	new Ajax.Request('/ajax/userlinks.php?action=imh&realm=' + object.realm + '&uid='+ object.uid + '&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";
			var newFavFlag = (response == 'here');
			_this.setObjectFlag(object.realm, object.uid, _this.FL_IM_HERE, newFavFlag);
			_this._notifyListeners(object);
			if (callback)
				callback(object);
		},
		onFailure: function(){ alert('Unable to save object') }
	});
}

UserContentTools.prototype.view = function(object, callback) {
	// TODO: max. once per object per session
	var _this = this;
	new Ajax.Request('/ajax/userlinks.php?action=view&realm=' + object.realm + '&uid='+ object.uid + '&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport) {
			var newViewCount = parseInt(transport.responseText) || 0;

			if (contentTools)
				contentTools.setObjectViewCount(object.realm, object.uid, newViewCount);

			_this._notifyListeners(object);
			if (callback)
				callback(object);
		},
		onFailure: function(){ alert('Unable to save object') }
	});
}

UserContentTools.prototype.setObjectFlag = function(realm, uid, flag, value) {
	var map = this.map[realm];
	if (! map) {
		map = {};
		map[uid] = value ? flag : 0;
		this.map[realm] = map;
	}
	if (typeof(map[uid]) == 'undefined') {
		map[uid] = value ? flag : 0;
	} else {
		var bits = map[uid];
		if (value) bits |= flag;
		else bits &= ~flag;
		map[uid] = bits;
	}
}

UserContentTools.prototype._notifyListeners = function(obj) {
	for (var i = 0; i < this.listeners.length; i++)
		this.listeners[i].userContentToolsUpdated(obj);
}

UserContentTools.prototype.addListener = function(obj) {
	this.listeners[this.listeners.length] = obj;
}

UserContentTools.prototype.getObjectFlag = function(realm, uid, flag) {
	if (!this.map[realm] || typeof(this.map[realm][uid]) == 'undefined') return false;
	else return (this.map[realm][uid] & flag) ? true : false;
}

/* class represents an interface to a single panel for bullit saveit, etc 
(a single page may have more of those) */
UserContentPanel = function(jsRef, id_prefix) {
	this.jsRef = jsRef;
	eval(jsRef + ' = this');
	this.id_prefix = id_prefix;
	this.fixPNG();
}
UserContentPanel.prototype.fixPNG = function() {
	/*
//	if (this.getElement('icon_bull'))
//		fixPNG(this.getElement('icon_bull'));
	if (this.getElement('icon_fav'))
		fixPNG(this.getElement('icon_fav'));
	if (this.getElement('icon_share'))
		fixPNG(this.getElement('icon_share'));
	if (this.getElement('icon_comment'))
		fixPNG(this.getElement('icon_comment'));
	*/
}

UserContentPanel.prototype.setCurObject = function(obj) {
	this.curObject = obj;
	/*
	var x;
	var s = '';
	for (x in obj)
		s += ''+x+' => '+obj[x]+'\n';
	alert(s);
	*/
	this.updateFav();
//	this.updateBull();
	this.updateComments();
	this.updateViews();
	this.updateImHere();
}

/* ContentTools listener */
/* this function never called
UserContentPanel.prototype.contentToolsUpdated = function(obj) {
	if (this.curObject && this.curObject.uid == obj.uid) {
//		this.updateBull();
		this.updateComments();
		this.updateViews();
		this.updateImHere();
	}
}
*/
/* UserContentTools listener */
UserContentPanel.prototype.userContentToolsUpdated = function(obj) {
	// dbg (this.jsRef + ' updated! ')
	if (this.curObject && this.curObject.uid == obj.uid) {
		this.updateFav();
//		this.updateBull();
		this.updateViews();
		this.updateImHere();
		this.updateComments(); // copied from contentToolsUpdated
	}
}

UserContentPanel.prototype.fav = function() {
	if (! rb_user_uid) {
		openLoginWindow();
		return;
	}
	var _this = this;
	userContentTools.fav(this.curObject/*, function(){
		_this.updateFav();
	}*/);
}
/*
UserContentPanel.prototype.bull = function() {
	if (! rb_user_uid) {
		openLoginWindow();
		return;
	}
	var _this = this;
	userContentTools.bull(this.curObject
	//, function(){	_this.updateBull();}
	);
}
*/
UserContentPanel.prototype.im_here = function() {
	if (! rb_user_uid) {
		openLoginWindow();
		return;
	}
	var _this = this;
	userContentTools.im_here(this.curObject/*, function(){
		// _this.updateBull();
	}*/);
}

UserContentPanel.prototype.comment = function() {
	var realm = this.curObject.realm;
	var uid = this.curObject.uid;

	var url = null;
	var hash = null;
	switch (realm) {
		case 'article': 
			if (REQUEST.article_id && REQUEST.article_id == uid) {
				hash = "#comment";
			}
			else {
				mc = this.curObject.mc;
				switch (mc) {
					case CAT_BULLEVARD:
						pid = PID_BULLEVARD_DETAIL;
						break;
					case CAT_ACTIONS:
						pid = PID_ACTIONS_DETAIL;
						break;
				}
				url = 'index.php?id='+ pid + '&article_id=' + uid;
			}
			break;

		case 'event': 
			if (REQUEST.event_id && REQUEST.event_id == uid)
				hash = "#comment";
			else
				url = 'index.php?id='+ PID_ACTIONS_DETAIL + '&event_id=' + uid;
			break;

		case 'hero': 
			if (REQUEST.hero_id && REQUEST.hero_id == uid)
				hash = "#comment";
			else
				url = 'index.php?id='+ PID_HEROES_DETAIL + '&hero_id=' + uid;
			break;
		
		case 'location': 
			if (REQUEST.location_id && REQUEST.location_id == uid)
				hash = "#comment";
			else
				url = 'index.php?id='+ PID_LOCATIONS_DETAIL + '&location_id=' + uid;
			break;
		
		case 'gallery': 
			var pid;
			var param;
			var gid = REQUEST['tx_cdgalleries_pi1[uid]'];
			if (gid) {
				pid = PID_GALLERIES_DETAIL_IMAGE;
				param = 'tx_cdgalleries_pi1[uid]';
			} 
			else {
				gid = REQUEST['tx_cdgalleries_pivideo[uid]'];
				pid = PID_GALLERIES_DETAIL_VIDEO;
				param = 'tx_cdgalleries_pivideo[uid]';
			}
			if (gid == uid)
				hash = "#comment";
			else
				url = 'index.php?id='+ pid + '&' + param + '=' + uid;
			break;
		

		case 'gallery_image': 
			if (REQUEST['tx_cdgalleries_pi1[image_uid]'] == uid)
				hash = "#comment";
			else
				url = 'index.php?id='+ PID_GALLERIES_SINGLE_IMAGE + '&tx_cdgalleries_pi1[image_uid]=' + uid;
			break;
	}
	

	if (! rb_user_uid) {
		savePageContext({type: 'comment',url: url});
		if (hash) { // same page
			document.location.hash = hash;
		} 
		else { // other page
			/*
			savePageContext({
				type: 'gotocomment',
				url: url
			});
			*/
		}
		openLoginWindow();
		return;
	} 
	else {
		if (hash) {
			document.location.hash = hash;
			postComment(null, document.getElementById('post_new_comment'));
		} 
		else {
			savePageContext({type: 'comment'});
			document.location.href = url + '#|type:comment';
		}
	}
}

UserContentPanel.prototype.onMouseEvent = function(over, target, event) {
	this.setIcon(over, target);
}

UserContentPanel.prototype.share = function(event, el) {
	if (isGalleryLightboxOpen())
		hideGalleryLightbox();
	else
		showEmbeds(false);
	myLightWindow.activate(event, el);
}

UserContentPanel.prototype.updateFav = function() {
	if (rb_user_uid && this.curObject) {
		var obj = this.curObject;
		var flag = userContentTools.getObjectFlag(obj.realm, obj.uid, userContentTools.FL_FAV);
		this.setFavFlag(flag);
	}
}
UserContentPanel.prototype.updateImHere = function() {
	if (rb_user_uid && this.curObject) {
		var obj = this.curObject;
		var flag = userContentTools.getObjectFlag(obj.realm, obj.uid, userContentTools.FL_IM_HERE);
		this.setImHereFlag(flag);
	}
}
/*
UserContentPanel.prototype.updateBull = function() {
	var obj = this.curObject;

	if (rb_user_uid && this.curObject) {
		var flag = userContentTools.getObjectFlag(obj.realm, obj.uid, userContentTools.FL_BULL);
		this.setBulledFlag(flag
			//,count
			);
	}

	if (this.curObject) {
		var bulls = contentTools.getObjectBullCount(obj.realm, obj.uid);
		// alert('bulls:'+bulls);
		if (this.getElement('bull_count'))
			this.getElement('bull_count').innerHTML = bulls;
	}
}
*/
UserContentPanel.prototype.updateComments = function() {
	var obj = this.curObject;
	if (!obj)
		return;
	var comments = contentTools.getObjectCommentCount(obj.realm, obj.uid);
	if (this.getElement('comment_count'))
		this.getElement('comment_count').innerHTML = comments;
}
UserContentPanel.prototype.updateViews = function() {
	var obj = this.curObject;
		if (!obj)
	{
		return;
	}
	var views = contentTools.getObjectViewCount(obj.realm, obj.uid);
	if (this.getElement('view_count'))
		this.getElement('view_count').innerHTML = views;
}
/*
UserContentPanel.prototype.setBulledFlag = function(flag, count) {
	if (typeof(count) == 'undefined')
		count = '0';
	if (this.getElement('text_bull')) {
		var btn = this.getElement('icon_bull').parentNode.parentNode;
		btn.className = flag ? 'teaser_menu_button_active' : 'teaser_menu_button';
	}
	
	if (this.getElement('bull_count'))
		this.getElement('bull_count').innerHTML = count;

	if (this.id_prefix == 'detail' || this.id_prefix == 'imggal') { // mini bull on event detail page
		var icon = flag ? 'gal_bull_done.gif' : 'gal_bull.gif';
		var img = WEB_ROOT + 'fileadmin/sitetemplates/i/' + icon;
		if (this.getElement('icon_bull')) {
			this.getElement('icon_bull').src = img;
			this.getElement('icon_bull').title = 'Das gefällt mir'+(flag ? ' nicht!' : '!');
//			if (this.id_prefix != 'imggal')
//				fixPNG(this.getElement('icon_bull'));
		}
	}
}
*/
UserContentPanel.prototype.setFavFlag = function(flag) {
	if (this.getElement('text_fav')) {
		var btn = this.getElement('icon_fav').parentNode.parentNode;
		btn.className = flag ? 'teaser_menu_button_active' : 'teaser_menu_button';
	}
	if (this.id_prefix == 'detail' || this.id_prefix == 'imggal') { // mini bull on event detail page
		var icon;
		if (this.id_prefix == 'imggal') {
			icon = flag ? 'gal_save_done.gif' : 'gal_save.gif';
		} else {
			icon = flag ? 'gal_save_done.gif' : 'gal_save.gif';
		}
		var img = WEB_ROOT + 'fileadmin/sitetemplates/i/' + icon;
		if (this.getElement('icon_fav')) {
			this.getElement('icon_fav').src = img;
			this.getElement('icon_fav').title = 'Das merk ich mir '+(flag ? 'nicht mehr!' : '!');
			if (this.id_prefix != 'imggal')
				fixPNG(this.getElement('icon_fav'));
		}
	}
}
UserContentPanel.prototype.setImHereFlag = function(flag) {
	if (this.getElement('text_im_here') && this.curObject) {
		this.getElement('text_im_here').innerHTML = flag ? 'Ich bin da' : 'Ich bin da';
		this.getElement('text_im_here').style.color = flag ? '#ff3333' : '#CCCCCC';
		var div_id = 'imh_div_'+this.curObject.uid+'_'+rb_user_uid;
		var div = document.getElementById(div_id);
		if (div) {
			if (flag)
				new Effect.Appear(div);
			else {
				if (div.style.display != 'none')
					new Effect.Fade(div);
			}
		}
		// div.style.display = 'none';
	}
}

/*
UserContentPanel.prototype.setFavIcon = function(active) {
	var icon = active ? 'teaser/saveit_over.png' : 'teaser/saveit.png';
	var img = WEB_ROOT + 'fileadmin/sitetemplates/i/' + icon;
	if (this.getElement('icon_fav')) {
		this.getElement('icon_fav').src = img;
		fixPNG(this.getElement('icon_fav'));
	}
}
*/

UserContentPanel.prototype.setIcon = function(over, what) {
	var icon = over ? 'teaser/'+what+'_over.png' : 'teaser/'+what+'.png';
	var img = WEB_ROOT + 'fileadmin/sitetemplates/i/' + icon;
	if (this.getElement('icon_'+what)) {
		this.getElement('icon_'+what).src = img;
		// fixPNG(this.getElement('icon_'+what));
	}
}

UserContentPanel.prototype.getElement = function (subid) {
	return document.getElementById(this.id_prefix + '_' + subid);
}

ImageGallery = function(gal_uid, images) {
	this.gal_uid = gal_uid;
	this.images = images;
	this.curImage = 0;
	this.showCurImage();
}
ImageGallery.prototype.next = function() {
	this.curImage++;
	if (this.curImage >= (this.images.length -1)) {
		this.curImage = this.images.length - 1;
		document.getElementById('imggal_next').style.display = 'none';
	} 
	if (this.curImage > 0 ) {
		document.getElementById('imggal_prev').style.display = 'inline';
	}
	this.showCurImage();
}
ImageGallery.prototype.prev = function() {
	this.curImage--;
	if (this.curImage <= 0) {
		this.curImage = 0;
		document.getElementById('imggal_prev').style.display = 'none';
	} 
	if (this.curImage < (this.images.length - -1)) {
		document.getElementById('imggal_next').style.display = 'inline';
	}
	this.showCurImage();
}
ImageGallery.prototype.showCurImage = function() {
	var src = WEB_ROOT + this.images[this.curImage];
	document.getElementById('imggal_img').src = src;
}
ImageGallery.prototype.click = function() {
	var url = WEB_ROOT + 'index.php?id='+ PID_GALLERIES_DETAIL_IMAGE + '&tx_cdgalleries_pi1[uid]=' + this.gal_uid;
	document.location.href = url;
	// alert('go to gallery '+ this.gal_uid);
}

TabberClick = function(type, realm, addURI) {
	var tabber = window['tabber_'+type];
	if (! tabber) {
		tabber = new Tabber(type);
		window['tabber_'+type] = tabber;
	}
	tabber.fetch(realm, addURI);
}

Tabber = function(type) {
	this.type = type;
}
Tabber.prototype.fetch = function(tab, addURI) {
	var tabId = 'tabber_'+this.type+'_'+tab;
	var tabEl = document.getElementById(tabId);
	var tabContainer = tabEl.parentNode;
	for (var i = 0; i < tabContainer.childNodes.length; i++) {
		var node = tabContainer.childNodes[i];
		if (node.className)
			node.className = 'submenu_item';
	}
	tabEl.className = 'submenu_item_active';
	var tabberLeftMenu = $('tabber_left_menu');
	if (tabberLeftMenu)
	{
		var subTab = null;
		if (addURI)
		{
			subTab = addURI.split('=')[1];
		}
		
		for (var i = 0; i < tabberLeftMenu.childNodes.length; i++) {
			var node = tabberLeftMenu.childNodes[i];
			if (node.className)
				node.className = 'widget_left_menu_item';
		}	
		if (!subTab)
		{
			subTab = 'action';
		}
		$('widget_left_menu_'+subTab).className = 'widget_left_menu_item_active';
	}

	var _this = this;
	/* Draw animation */
	var contentEl = document.getElementById('tabber_'+this.type+'_content');
	if (contentEl)
	{
		contentEl.style.textAlign = "center";
		contentEl.innerHTML = '<img src="/fileadmin/sitetemplates/i/lightwindow/ajax-loading.gif" style="margin-top:5px;" border="0" />';

	}

	/* TODO: mainCat
	var pageId = REQUEST['id'];
	var maincat = null;
	if (pageId) {
		pageId = parseInt(pageId);

		switch (pageId) {
			case PID_BULLEVARD:
				maincat = CAT_BULLEVARD;
				break;
			case PID_ACTIONS:
				maincat = CAT_ACTIONS;
				break;
		}
	}
	*/
	
	var url;
	switch (this.type) {
		case "hero":
			url = '/index.php?id='+ PID_HEROES_AJAX +'&tab=' + tab + '&tabOnly=1&hero_id='+window.cur_hero_uid+'&slt='+Math.random();
		break;
		case "profile":
			url = 'index.php?id='+PID_PROFILE_AJAX+'&tab='+tab+'&tabOnly=1&slt='+Math.random();
			break;
		case 'pop': 
			url = 'index.php?id='+PID_PIPOP_AJAX+'&tab='+tab+'&tabOnly=1';
		break;
		case 'latest':
			url = 'index.php?id='+PID_PILATEST_AJAX+'&tab='+tab+'&tabOnly=1';
		break;
		case 'dashboard':
			url = 'index.php?id='+PID_PIDASHBOARD_AJAX+'&tab='+tab+'&tabOnly=1&slt='+Math.random();
		break;
		default:	
			url = '/ajax/widgets.php?type='+this.type+'&tab=' + tab + '&tabOnly=1&slt='+Math.random();
		break;
	}
	
	if (addURI)
	{
		url += "&"+addURI;
	}
/*	if (this.type == 'hero')
		
	else
		url = '/ajax/widgets.php?type='+this.type+'&tab=' + tab + '&tabOnly=1&slt='+Math.random();
	/*
	if (maincat)
		url += '&maincat='+maincat;
	*/

	new Ajax.Request(url, {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";
			var contentEl = document.getElementById('tabber_'+_this.type+'_content');
			contentEl.style.textAlign = "left";
			contentEl.innerHTML = response;
			doSIFR(true);
			AjaxEvalScripts(contentEl);
		},
		onFailure: function(){ alert('Unable to fetch content') }
	});
}

/*
This function is used  to display an overlay.
params:
	subst (opt): associative array, keys - element ids, values - text/html to insert
	onShow (opt): function to be called after overlay is displayed and subst applied
	onAction: function to be called when calling OverlayAction from overlay template,
	          it will receive a single parameter, which is the action.
			  if the function returns false the overlay window will not be automatically
			  closed.
*/
function OverlayShow(template, params) {
	if (window.rbteaser)
		window.rbteaser.stopFlipping();
	var overlay = new Overlay(template, params);
	overlay.show();
}
/* function should be called from overlay templates to trigger the call of
   the overlay's onAction function parameter */
function OverlayAction(action) {
	var overlay = window._curOverlay;
	overlay.processAction(action);
}
/* destroys overlay if any */
function OverlayClose() {
	if (window._curOverlay) {
		var target = document.body;
		target.removeChild(target.firstChild);
		window._curOverlay = null;
		if (window.rbteaser)
			window.rbteaser.stopFlipping();
	}
}
function OverlayVisible() {
	return !(!window._curOverlay);
}

Overlay = function(template, params) {
	this.template = template;
	this.params = params;
}
Overlay.wrap = [
	'<div style="border:1px solid red; background-color: #6eb6c0; position:absolute; top:0px; left:0px; widgh:auto; z-index:10000"><form name="ovl_form">'
	,
	'</form></div>'
];
Overlay.prototype.show = function() {
	window._curOverlay = this;
	_this = this;
	var url = '/fileadmin/plugintemplates/ovl/'+ this.template + '.html?slt'+Math.random();
	new Ajax.Request(url, {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "missing template";
			_this.onTemplateArrived(response);
		},
		onFailure: function(){ alert('Unable to fetch content') }
	});
}
Overlay.prototype.onTemplateArrived = function(template) {
	var w = Overlay.wrap;
	var html = w[0] + template + w[1];
	
	var target = document.body;
	var div = document.createElement('div');
	div.innerHTML = html;
	target.insertBefore(div, target.firstChild);

	if (this.params.subst) {
		var subst = this.params.subst;
		for (var key in subst) {
			var value = subst[key];
			var el = document.getElementById('ovl_'+ key);
			if (el)
				el.innerHTML = value;
			else
				alert('overlay element id = ovl_'+key+' not found!');
		}
	}

	if (this.params.form) {
		var f = this.params.form;
		var form = document.ovl_form;
		for (var key in f) {
			if (form[key])
				form[key].value = f[key];
			else
				alert('overlay input element name = '+key+' not found!');
		}
	}

	if (this.params.onShow)
		this.params.onShow();
}

Overlay.prototype.processAction = function(action) {
	var close = true;
	if (this.params.onAction)
		close = this.params.onAction(action, this);

	if (close !== false) {
		OverlayClose();
	}
}
Overlay.prototype.getFormData = function() {
	var form = document.ovl_form;
	
	map = {};
	var els = form.getElementsByTagName('input');
	for (var i = 0; i < els.length; i++) {
		var el = form.elements[i];
		var name = el.name;
		var value = el.value;
		if (name)
			map[name] = value;
	}

	return map;
/*
	if (encode) {
		var arr = [];
		for (key in map) {
			var value = map[key];
			arr[arr.length] = key + '=' +escape(value);
		}
		var data = arr.join('&');
		return data;
	} else {
		return map;
	}

	if (! document.all) { // FF
		var key;
		for (key in form.elements) {
			var el = form.elements[key];
			if (typeof(el) == 'object') {
				var name = el.name;
				var value = el.value;
				if (name)
					map[name] = value;
			}
		}
	} else {
		for (var i = 0; i < form.elements.length; i++) {
		   var el = form.elements[i];
			if (typeof(el) == 'object') {
				var name = el.name;
				var value = el.value;
				dbg(name+ '=>' +value);
				if (name)
					map[name] = value;
			}
		}
	}
*/
}

ShareIt = function() {
	OverlayShow('shareit', {
		onAction: function(action, overlay) {
			switch(action) {
				case 'send':
					var data = overlay.getFormData(true);
					var url = '/ajax/userutils.php?action=shareit&slt'+Math.random();
					document.getElementById('ovl_response').className = 'ovl_status';
					document.getElementById('ovl_response').innerHTML = 'Email wird versendet...';
					new Ajax.Request(url, {
						method: 'post',
						parameters: data,
						onSuccess: function(transport) {
							var response = transport.responseText || "antwort vom Server fehlt";
							if (response == 'sent') {
								document.getElementById('ovl_response').innerHTML = 'Email erfolgreich versendet';
								document.getElementById('ovl_response').className = 'ovl_message';
								document.getElementById('ovl_send_btn').style.display = 'none';
								document.getElementById('ovl_cancel_btn').value = 'Schliessen';
							} else {
								document.getElementById('ovl_response').innerHTML = 'Fehler beim versenden der Email';
								document.getElementById('ovl_response').className = 'ovl_error';
							}
						},
						onFailure: function(){ alert('Unable to save item') }
					});
					return false;
			}
		}
	})
}

/**
 * Micox Word Wrap 2.0 
 * elmicoxcodes.blogspot.com - www.ievolutionweb.com - micoxjcg@yahoo.com.br
 * Creative Commons License - creativecommons.org
 * 
 * Description:
 * Wraps large words in Firefox and Opera.
 * Works just like the word-wrap: break-word; CSS property in Internet Explorer
 *
 * Usage:
 * 1) Include this JS file in your page. Example: 
 * 2) Set 'word-wrap' as the classname of the elements that you want to word break. Example: 

 *
**/

function wrap(quem){
 var larg_total,larg_carac,quant_quebra,pos_quebra, over_orig;
 var elementos,quem, pai, caracs, texto, pai_texto, display_orig, wid_orig;
   
    if(quem.nodeType==3){
  //elemento tipo texto. tenho que verificar se o pai dele tí quebrando
 
  if(quem.nodeValue.replace('\n','').replace('\t','').trim()==''){
   //se o textNode for vazio, nÜo prossigo
   return true;
  }
 
  pai = quem.parentNode;  
  texto = quem.nodeValue;  
 
  //pegando a largura setada oficial
  display_orig = pai.style.display;
  over_orig = pai.style.overflow;
  wid_orig = pai.style.width;
  pai.style.display="block";
  pai.style.overflow="hidden";
  larg_oficial = pai.offsetWidth;
 
  //pegando a largura real total
  pai.style.display="table";
  pai.style.width = "auto"; //para o Opera
  pai.style.overflow = "visible";
  larg_total = pai.offsetWidth;
  //alert("texto: " + texto + " \r\n larg_oficial:" + larg_oficial + " \r\n larg_total:" + larg_total)
  pai.style.overflow = over_orig;
 
  if(larg_total>larg_oficial){ //se o pai do text tí extrapolando, quebro o text
   pos_quebra = 0;
   caracs = pai.textContent.length;
   //recalculando a largura real tirando os espa�os pra poder calcular
   // direito a largura dos caracs e quando vou quebrar
   
   quem.nodeValue = pai.textContent.replace(/ /g,"��") + " ";
   larg_total = pai.offsetWidth;
   pai.style.display = display_orig;
   
   larg_carac = larg_total / caracs ;
   quant_quebra = parseInt(larg_oficial/larg_carac) - 2;
   
   quem.nodeValue = '';
   
   while(pos_quebra<=caracs){
    quem.nodeValue += texto.substring(pos_quebra,pos_quebra + quant_quebra) + " "
    pos_quebra = pos_quebra + quant_quebra;
   }  
  }
  pai.style.display = display_orig;
  pai.style.display = over_orig;
  pai.style.width = wid_orig;
 
 }else if(quem.childNodes.length==1 && quem.childNodes[0].nodeType==3){
  //é o çltimo do n��vel e o çnico filho é texto
  texto = String(quem.innerHTML); //salvando o original
 
 
  /*quem.innerHTML = " "  
  display_orig = quem.style.display;
  quem.style.display="block";
  larg_oficial = quem.offsetWidth;
   
  quem.style.display="table";
  quem.innerHTML = texto;
  larg_total = quem.offsetWidth;*/
 
  //pegando a largura setada oficial
  display_orig = quem.style.display;
  over_orig = quem.style.overflow;
  wid_orig = quem.style.width;
  quem.style.display="block";
  quem.style.overflow="hidden";
  larg_oficial = quem.offsetWidth;
 
  //pegando a largura real total
  quem.style.display="table";
  quem.style.width = "auto"; //para o Opera
  quem.style.overflow = "visible";
  larg_total = quem.offsetWidth;
  //alert("texto: " + texto + " \r\n larg_oficial:" + larg_oficial + " \r\n larg_total:" + larg_total)
  quem.style.overflow = over_orig;
   
  if(larg_total>larg_oficial){ //quebrando quem extrapolou
   pos_quebra = 0;
   caracs = texto.length;
   //recalculando a largura real tirando os espa�os pra poder calcular
   // direito a largura dos caracs e quando vou quebrar
   quem.innerHTML = quem.innerHTML.replace(/ /g,"��");
   larg_total = quem.offsetWidth;
   larg_carac = larg_total / caracs ;
   
   quant_quebra = parseInt(larg_oficial/larg_carac) - 2;
   quem.innerHTML = ""
   
   while(pos_quebra<=caracs){
    quem.innerHTML += texto.substring(pos_quebra,pos_quebra + quant_quebra) + " "
    pos_quebra = pos_quebra + quant_quebra;
   }
   
  }
  quem.style.display = display_orig;
  quem.style.display = over_orig;
  quem.style.width = wid_orig;
 
 }else if(quem.childNodes.length>0){
  //se tiver mais que um filho, vou ter que executar de filho em filho nele
  for(var i=0;i<quem.childNodes.length;i++){
   wrap(quem.childNodes[i]);
  }
 }
}
function wordWrap(){  
    var elementos = document.body.getElementsByTagName("*")
 
    if(navigator.appName.indexOf("Internet Explorer")>-1){
        for(var i=0; i<elementos.length;i++){
            if(elementos[i].className.indexOf("word-wrap")>-1){
                elementos[i].style.wordWrap = "break-word";
            }
        }
    }else{
        for(var i=0; i<elementos.length;i++){
            if(elementos[i].className.indexOf("word-wrap")>-1){
                wrap(elementos[i]);
            }
        }
    }
}

String.prototype.trim = function() {
	return this.replace(/^[ ]+|[ ]+$/g,"");
}

function ShowTeaserFlash(flag) {
	var el = document.getElementById('teaser_sifr');
	if (el)
		el.style.display = flag ? 'block' : 'none';

	el = document.getElementById('mplayer');
	if (el)
		el.style.display = flag ? 'block' : 'none';
}

function updateContent(target,value,fieldType,add)
{
	var obj = document.getElementById(target);
	if (obj)
	{
		if (fieldType == 'radio')
		{
			var imgs = obj.getElementsByTagName("img");
			for(var i=0;i<imgs.length;i++)
			{
				var attr = window.Element.readAttribute(imgs[i],"value");
				if (attr == value)
				{
					imgs[i].src = "/fileadmin/sitetemplates/i/icon_bullet_active.png";
				}
				else
				{
					imgs[i].src = "/fileadmin/sitetemplates/i/icon_bullet_inactive.png";
				}
			}
			if (add)
			{
				eval(add);
			}
			return;
			
		}
		obj.innerHTML = value;
	}
}

SearchTool = function() {
	
}
SearchTool.prototype.search = function(params) {
	var _this = this;
	new Ajax.Request('/index.php?id='+ PID_SEARCH_AJAX + '&ajax=1&query='+ escape(params.query) +'&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";
			_this.displayContent(response);
		},
		onFailure: function(){ alert('Unable to save object') }
	});
}

SearchTool.prototype.displayContent = function(html) {
	document.getElementById('search_content').innerHTML = html;
}

function fixPNG(img) {
	version = parseFloat(arVersion[1]);
	if ((version >= 5.5) && (version < 7) && (document.body.filters)) {
		if (! img)
			return;
		if (typeof(img) == 'string')
			// alert('str: '+ img);
			img = document.getElementById(img);
		if (! img)
			return;
		// alert('img: '+ img.src);
		var src = img.src;
		img.src='/clear.gif';
		img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+ src +"', sizingMethod='scale')";
	}
}

// what is this??? who needs this THIS WAY?
function __fixPNG(img) {
	version = parseFloat(arVersion[1]);
	if ((version >= 5.5) && (version < 7) && (document.body.filters)) {
		if (typeof(img) == 'string')
			img = document.getElementById(img);
		if (! img)
			return;
		var f = 'DXImageTransform.Microsoft.AlphaImageLoader';

//		$(img).absolutize();
//		$(img).style.filter = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader';
		var dimensions = $(img).getDimensions();
		var imgID = (img.id) ? 'id="' + img.id + '" ' : '';
		var imgClass = (img.className) ? 'class="' + img.className + '" ' : '';
		var imgTitle = (img.title) ? 'title="' + img.title + '" ' : 'title="' + img.alt + '" ';
		var imgStyle = 'display:inline-block;' + img.style.cssText;
		if (img.align == 'left') imgStyle = 'float:left;' + imgStyle;
		if (img.align == 'right') imgStyle = 'float:right;' + imgStyle;
		if (img.parentElement && img.parentElement.href) imgStyle = 'cursor:hand;' + imgStyle;
		var strNewHTML = '<div ' + imgID + imgClass + imgTitle
			+ 'style="' + 'width:' + dimensions.width + 'px; height:' + dimensions.height + 'px;' + imgStyle + ';'
			+ 'background-color:transparent;'
			+ 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader'
			+ '(enabled=true, src=\'' + img.src + 'dudl\', sizingMethod=\'scale\');'
			+ '"></div>';
		img.outerHTML = strNewHTML;
//		alert($(img).src);
		
	}
}

var embedElements;
var embedsShown = true;
var _shouldHideEmbeds = null
function shouldHideEmbeds() {
	if (_shouldHideEmbeds === null) {
		var hide = true;
		var ua = navigator.userAgent;
		dbg(ua);
		var lua = ua.toLowerCase();
		if (lua.indexOf('windows') >= 0 && ua.indexOf('MSIE') > 0) {
			hide = false;
		} else if (lua.indexOf('windows') >= 0 && lua.indexOf('firefox') >= 0) {
			hide = false;
		}
		_shouldHideEmbeds = hide;
	}
	return _shouldHideEmbeds;
}
function showEmbeds(flag) {
	if (! shouldHideEmbeds())
		return;
	if (embedsShown ^ flag) {
		if (!embedElements)
			embedElements = document.body.getElementsByTagName('embed');
		for (var i = 0; i < embedElements.length; i++) {
			embedElements[i].style.display = flag ? 'block' : 'none';
		}
		embedsShown = flag;
	}
}

function dbg(msg) {
	if (typeof(window.console) != 'undefined') window.console.debug(msg);
}

function submitLogin(e) {
	// hook needed for realurl
	// this function is not called in firefox? -- now it is called... everywhere...
	dbg('submitLogin called');
	document.getElementById('login_redirect_url').value = getLoginRedirectURL();
	dbg(document.getElementById('login_redirect_url').value);

	var possibleSafari = !Prototype.Browser.IE && !Prototype.Browser.Opera 
                            && !Prototype.Browser.WebKit && !Prototype.Browser.Gecko
                            && !Prototype.Browser.MobileSafari;
	if (Prototype.Browser.Gecko) {
//		console.debug(e);
//		e.preventDefault();
//		document.getElementById('login_btn_ff').click();
	} else {    
		document.getElementById('login_btn').click();
	}

	return false;
}

function checkPassword(e) {
	var pwd = document.getElementById('change_pwd');
	var conf_pwd = document.getElementById('change_pwd_confirm');

	if (pwd && conf_pwd)
	{
		var old_pwd = document.getElementById('old_password_value');
		var old_pwd_confirm = document.getElementById('change_old_pwd');

		if (old_pwd.value != old_pwd_confirm.value)
		{
			old_pwd_confirm.value = '';
			pwd.value = '';
			conf_pwd.value = '';
			alert('Please enter correct current password!');
			return false;
		}
		if (pwd.value == '' || pwd.value == '')
		{
			alert('Password and Confirm Password should be entered!');
			return false;
		}
		if (pwd.value != conf_pwd.value)
		{
			alert('Password and Confirm Password fields are not equal!');
			return false;
		}
	}
	myLightWindow.submitForm(e);
	return false;
}

var _savedPageContext;
/* This function should be used to save the current client context so that
   after login / registration the user proceeds with the action intended.
   E.x. while not logged in use clicks at "post a comment", since the user
   is not logged in, the login lightbox is displayed. the context should be set
   so that after the user is logged in and page reloads, the comment lightbox
   should appear immediately. This function works in tandem with _restorePageContext()
   thus for every particular context specification there should be a section in
   _restorePageContext that will restore the client state accordingly. */
function savePageContext(context) {
	_savedPageContext = context;
}
function _restorePageContext() {
	var context = _getPageContext();
	if (! context)
		return;
	var i;
	var type = context.type;
	switch (type) {
		case 'comment': // comment
			if (context.id) {
				document.location.hash = 'a_'+context.id;
				var el = document.getElementById(context.id);
			} else {
				document.location.hash = 'comment';
				var el = document.getElementById('post_new_comment');
			}
			showEmbeds(false);
			myLightWindow.activate(null, el);
			break;
		case 'gotocomment':
			document.location.hash = 'comment';
			break;
	}
}
function _getPageContext() {
	var hash = document.location.hash;
	if (hash) {
		var arr = hash.split('|');
		if (arr.length != 2)
			return null;
		return unserializeContext(arr[1]);
	}
	return null;
}

function cloneObject(obj) {
	var clone = {};
	var key;
	for (key in obj) {
		clone[key] = obj[key];
	}
	return clone;
}

function getLoginRedirectURL() {
	var req = cloneObject(REQUEST);
//	req.slt = Math.round(Math.random() * 10000); // slt is not needed in ie6 for the login url 

	var context = _savedPageContext;
	if (context) context = cloneObject(context);

	var url;
	var hash = '';
	
	if (context && context.url) {
		url = context.url;
		delete context.url;

		var pos = url.indexOf('#');
		if (pos > 0) {
			url = url.substr(0, pos);
			hash = url.substr(pos + 1);
		}

	} else {
//		url = 'index.php';
// realurl version
		url = '';
		var query = serializeUrl(req);
//		if (query.length) url += '?' + query;
// realurl version
		if (query.length) url += query;
		if (document.location.hash) hash = document.location.hash.substr(1);
	}

	if (context) {
		var serContext = serializeContext(context);
		if (serContext.length > 0) hash += '|' + serContext;
	}

	if (url.indexOf('http:') != 0 && url.indexOf('/') != 0) {
		// absolutize url
		url = encodeURIComponent(PATH) + url;
	}
	
	if (hash.length) url += '#' + hash;
	return url;
}

function serializeObject(obj, recSep, fldSep) {
	var str = '';
	var key;
	for (key in obj) {
		str += recSep + key + fldSep + encodeURIComponent(obj[key]);
	}

	return str.substr(1);
}

function unserializeObject(str, recSep, fldSep) {
	var params = str.split(recSep);
	var obj = {};
	for (var i = 0; i < params.length; i++) {
		var param = params[i];
		var arr = param.split(fldSep);
		obj[arr[0]] = decodeURI(arr[1]);
	}
	return obj
}

function serializeUrl(url) {
	return serializeObject(url, '&', '=');
// realurl version
//	return serializeObject(url, '/', '/');
}

function serializeContext(context) {
	return serializeObject(context, ',', ':');
}

function unserializeUrl(url) {
	return unserializeObject(url, '&', '=');
// realurl version
//	return unserializeObject(url, '/', '/');
}

function unserializeContext(context) {
	return unserializeObject(context, ',', ':');
}

function isLoggedIn() {
	return !(!window.rb_user_uid);
}

function postComment(event, el) {
	if (! isLoggedIn()) {
		var pctx = {
			type: 'comment'
		};
		if (el.id && el.id.substr(0, 4) == 'com_')
			pctx.id = el.id;
		savePageContext(pctx);
		openLoginWindow();
	} else {
		showEmbeds(false);
		myLightWindow.activate(event, el);
	}
}

function reloadWindowWithHash(hash) {
	var req = cloneObject(REQUEST);
	req.slt= Math.round(Math.random() * 10000);
	var urlpart = serializeUrl(req);
	var url = 'index.php';
	if (urlpart.length)
		url += '?'+urlpart;
	url += '#'+ hash;
	document.location.href = url;
}

function Login(event, el) {
	openLoginWindow();
}

function Logoff() {
	new Ajax.Request('/index.php?logoff=1&slt='+Math.random(), {
		method:'get',
		onSuccess: function() {
			var url = document.location.href;
			if (url.indexOf("index.php?id="+PID_PROFILE) > 0) {
				document.location.href = "/index.php"; 
			} else {
				document.location.href = PATH; // getLoginRedirectURL(); 
			}
		},
		onFailure: function(){ alert('Unable to logoff') }
	});
}

function MapSearch(id) {
	this.el = $(id ? id : 'map_search_results');
	this.lastquery = '';
}

MapSearch.prototype.navigate = function(lng, lat, cat, uid, title) {
	if (this.onSearchNavigate) this.onSearchNavigate(lng, lat, cat, uid, title);
	if (window.rbmap_loaded) {
		rbmap.panTo(lng, lat);
	}
}

MapSearch.prototype.enableGeocoder = true;
MapSearch.prototype.search = function(id) {
	var query = $(id ? id : 'map_search_text').value;

	if (this.enableGeocoder) {
		if (! this.geo) this.geo = new GClientGeocoder();
		
		var _this = this;
		
		this.geo.getLatLng(query, function(point) {
			if (!point) {
				_this.searchDatabase(query);
			} else {
				if (window.rbmap_loaded) {
					rbmap.map.panTo(point);
				}
			}
		});
	} else {
		this.searchDatabase(query);
	}
}

MapSearch.prototype.searchDatabase = function(query) {
	if (query == this.lastquery) {
		if (this.lastresponse) this.processResults(this.lastresponse);
		else this.openResults();
		return;
	} 

	this.lastquery = query;

	var _this = this;
	new Ajax.Request('/index.php?id='+ PID_MAPSEARCH_AJAX +'&query='+ escape(query) +'&slt='+Math.random(), {
		method:'get',
		onSuccess: function(transport){
			var response = transport.responseText || "antwort vom Server fehlt";
			// alert(response);
			_this.lastresponse = response;
			_this.processResults(response);
		},
		onFailure: function() { alert('Unable to search in map') }
	});
}

MapSearch.prototype.processResults = function(response) {
	this.curResultsPage = 1;
	this.el.update(response);
	this.openResults();
}

MapSearch.prototype.openResults = function() {
	if (this.open) return;
	
	showEmbeds(false);
	new Effect.SlideDown(this.el);
	this.open = true;
}

MapSearch.prototype.closeResults = function() {
	if (!this.open) return;

	new Effect.SlideUp(this.el, {
		afterFinish: function() { 
			showEmbeds(true); }
		}
	);

	this.open = false;
}

MapSearch.prototype.showResultsPage = function(num) {
	if (this.curResultsPage == num) return;
	
	var el = $('map_results_page_'+ this.curResultsPage);
	if (el) el.style.display = 'none';

/*	el = $('map_results_pagelink_'+ this.curResultsPage);
	if (el) el.className = 'page_normal';
*/
	el = $('map_results_page_'+ num);
	if (el) el.style.display = 'block';
/*	
	el = $('map_results_pagelink_'+ num);
	if (el) el.className = 'page_active';
*/
	this.curResultsPage = num;
}

function getBoxedImageSize(orig_w, orig_h, box_w, box_h) {
	if (! orig_w || ! orig_h) {
		thumb_w = box_w;
		thumb_h = box_h;
	} else {
		var shrinkFactorX = orig_w / box_w;
		var shrinkFactorY = orig_h / box_h;
		var shrinkFactor;
		if (shrinkFactorX > shrinkFactorY)
			shrinkFactor = shrinkFactorX;
		else
			shrinkFactor = shrinkFactorY;
		var thumb_w = Math.round(orig_w / shrinkFactor);
		var thumb_h = Math.round(orig_h / shrinkFactor);
	}
	return [thumb_w, thumb_h];
}

function showImageUpload()
{
	var frm = document.getElementById("upload_image_form");
	if (frm)
	{
		frm.style.display = "";
	}
}

// A Rectangle is a simple overlay that outlines a lat/lng bounds on the
// map. It has a border of the given weight and color and can optionally
// have a semi-transparent background color.

function RBInfoWindow(point, width, content) {
	this.point = point;
	this.width = width;
	this.content = content;
}

RBInfoWindow.createClass = function() {
	
RBInfoWindow.prototype = new GOverlay();

RBInfoWindow.prototype.initialize = function(map) {
	var div = document.createElement("div");

	  div.style.width = (this.width + 10)+'px';

	  div.style.position = "absolute";
	  div.style.visibility = 'hidden';
	  map.getPane(G_MAP_FLOAT_PANE).appendChild(div);
	  this.map = map;
	  this.div = div;
	}

	RBInfoWindow.prototype.remove = function() {
	  this.div.parentNode.removeChild(this.div);
	}

	// Copy our data to a new RBInfoWindow
	RBInfoWindow.prototype.copy = function() {
	  return new RBInfoWindow(this.point);
	}
	
	// Redraw the rectangle based on the current projection and zoom level
	RBInfoWindow.prototype.redraw = function(force) {
	  // We only need to redraw if the coordinate system has changed
	  if (!force)
		  return;

	  this.div.innerHTML = this.render(this.width, 0, this.content);

	  this.adjust();
		  
	  /*
	  this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
	  this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
	  this.div_.style.left = Math.round(c1.x + c(Math.min(c2.x, c1.x) - this.weight_) + "px";
	  this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
	  */
	}
	
	/* private stuff */
	RBInfoWindow.prototype.el = {
		tl : {img: 'tl.png', w:6, h:6},
		t  : {img: 't.png',  w:1, h:6},
		tr : {img: 'tr.png', w:6, h:6},
		bl : {img: 'bl.png', w:6, h:8},
		b  : {img: 'b.png',  w:1, h:8},
		br : {img: 'br.png', w:6, h:8},
		bm : {img: 'bm.png', w:33, h:32},
		
		l  : {img: 'l.png',  w:6, h:1},
		r  : {img: 'r.png',  w:6, h:1}
	};

	RBInfoWindow.prototype.render = function(w, h, content) {
		var ip = '/fileadmin/sitetemplates/i/map_bubble/';
		var el = this.el;
	
		var com = 'line-height:1px;';
	
		var browserVer = parseFloat(arVersion[1]);
		var usePngFix = ((browserVer >= 5.5) && (browserVer < 7) && (document.body.filters)); 
		function bg(src) {
			var ret
			if (usePngFix)
				ret = "filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + ip+src + "',sizingMethod='scale')";
				// ret = '';
			else
				ret = 'background-image: url('+ip+src+');';
			return ret;
		}
	
		var w_b_ml = Math.round((w - el.bm.w) / 2);
		var w_b_mr = w - w_b_ml - el.bm.w;
		var bm_pad = el.bm.h - el.b.h;
		var html = 
	'<table id="bbl_tbl" style="border:0px" cellpadding="0" cellspacing="0">\n' +
	' <tr>\n'+
	'  <td style="width:'+ el.tl.w +'px; height:'+el.t.h+'px; '+bg(el.tl.img)+com+'"></td>\n' +
	'  <td id="bbl_t" style="width:'+ w +'px; height:'+el.t.h+'px; '+bg(el.t.img)+com+'"></td>\n' +
	'  <td style="width:'+ el.tr.w +'px; height:'+el.t.h+'px; '+bg(el.tr.img)+com+'"></td>\n' +
	' </tr>\n'+
	' <tr>\n'+
	'  <td style="width:'+ el.l.w +'px; '+bg(el.l.img)+com+'"></td>\n' +
	'  <td id="bbl_content" style="width:'+ w +'px; background-color:#FFFFFF; padding-left:3px; padding-right:5px">'+content+'</td>\n' +
	'  <td style="width:'+ el.r.w +'px; '+bg(el.r.img)+com+'"></td>\n' +
	' </tr>\n'+
	'</table>'+
	'<table style="border:0px" cellpadding="0" cellspacing="0">\n' +
	' <tr>\n'+
	'  <td style="width:'+ el.bl.w +'px; height:'+el.b.h+'px; '+bg(el.bl.img)+com+'"></td>\n' +
	'  <td id="bbl_bml" style="width:'+ w_b_ml +'px; height:'+el.b.h+'px; '+bg(el.b.img)+com+'"></td>\n' +
	'  <td rowspan="2" style="width:'+ el.bm.w +'px; height:'+el.bm.h+'px; '+bg(el.bm.img)+com+'"></td>\n' +
	'  <td id="bbl_bmr" style="width:'+ w_b_mr +'px; height:'+el.b.h+'px; '+bg(el.b.img)+com+'"></td>\n' +
	'  <td id="bbl_br" style="width:'+ el.br.w +'px; height:'+el.b.h+'px; '+bg(el.br.img)+com+'"></td>\n' +
	' </tr>\n'+
	' <tr>\n'+
	'  <td colspan="2" style="height:'+bm_pad+'px"></td>\n' +
	'  <td colspan="2" style="height:'+bm_pad+'px"></td>\n' +
	' </tr>\n'+
	'</table>'+
	'<div style="position:absolute; width:10px; height:10px; top:3px; right:1px;"><a href="#" onclick="rbmap.closeInfoWindow(); return false;">X</a></div>';
		return html;
	}
	
	RBInfoWindow.prototype.resize = function(w, h) {
		var el = this.el;
		var w_b_ml = Math.round((w - el.bm.w) / 2);
		var w_b_mr = w - w_b_ml - el.bm.w;
		document.getElementById('bbl_t').style.width = w + 'px';
		document.getElementById('bbl_bml').style.width = w_b_ml + 'px';
		document.getElementById('bbl_bmr').style.width = w_b_mr + 'px';
	}
	
	RBInfoWindow.prototype.setContent = function(content) {
		document.getElementById('bbl_content').innerHTML = content;
	}
	
	RBInfoWindow.prototype.adjust = function() {
		var c = this.map.fromLatLngToDivPixel(this.point);

		var tbl_pos = getAbsoluteElementPosition(document.getElementById('bbl_tbl'));
		var br_pos = getAbsoluteElementPosition(document.getElementById('bbl_br'));
		var w = br_pos[0] - tbl_pos[0];
		var h = br_pos[1] - tbl_pos[1];

		this.div.style.left = (c.x - w / 2 - 3) + 'px';
		this.div.style.top = (c.y - h - 65) + 'px';
		this.div.style.visibility = 'visible';

		var center = {
			x : c.x,
			y : c.y - (h / 2)
		}

		var p = this.map.fromDivPixelToLatLng(center)
		rbmap.map.panTo(p);
	}
}

var iw;

if (typeof(addOnMarkersLoad) != 'undefined') addOnMarkersLoad(function(){
	RBInfoWindow.createClass();
	/*
	iw = new RBInfoWindow();
	iw.test(100, 50, 'hello<br/>world!');
	map.addOverlay(new RBInfoWindow(map.getCenter()));
	*/
});

function getAbsoluteElementPosition(el) {
	var left = 0;
	var top = 0;
	while (el) {
		left += el.offsetLeft;
		top += el.offsetTop;
		el = el.offsetParent;
	}
	return [left, top];
}

function loginAction() {
	myLightWindow.deactivate(); 
	document.location.href = getLoginRedirectURL(); 
}

function ajaxSendForm(formname, url, responseid, successFunc) {
	
	var postBody = "";
	if (formname){
		postBody = $(formname).serialize();
	}

	if (responseid) $(responseid).update('<img src="/fileadmin/sitetemplates/i/lightwindow/ajax-loading.gif" style="margin-top:5px;" border="0" />');

	new Ajax.Request(url, {
		method: 'post',
		postBody: postBody,
		onSuccess: function(transport) {
			var response = transport.responseText || 'No response from '+url;
			if (responseid) $(responseid).update(response);
			
			
			if (successFunc) successFunc(response);
		
			if (typeof(Tip) != 'undefined' && typeof(addTips) != 'undefined') {
				addTips();
			}

		},
		onFailure: function() {
			if (responseid) $(responseid).update('Unable to post form '+formname+' to '+url);
		}
	});
}	

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

var ferror = 'Ui, da is leider was schief gegangen...';

function removeFromFriends(uid, friend_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_delete&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			var html = '<div><a href="#" onclick="requestFriendship('+uid+', \''+friend_name+'\', this.parentNode, '+micro+'); return false;" title="'+friend_name+' deine Freundschaft anbieten">' +
				'<img class="friendicon" src="/fileadmin/sitetemplates/i/add_as_friend'+(micro ? '_micro' : '')+'.gif" alt="" />' +
				'</a></div>';
			$(element).replace(html);
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function requestFriendship(uid, friend_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_friendship&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			var html = '<div><div><a href="#" onclick="withdrawFriendshipRequest('+uid+', \''+friend_name+'\', this.parentNode.parentNode, '+micro+'); return false;" title="'+friend_name+' deine Freundschaft nicht mehr anbieten" >' + 
				'<img class="friendicon" src="/fileadmin/sitetemplates/i/stop_request'+(micro ? '_micro' : '')+'.gif" alt="" />' +
				'</a></div>' +
				'<div><a href="#" onclick="resendFriendshipRequest('+uid+', \''+friend_name+'\', this.parentNode.parentNode, '+micro+'); return false;" title="'+friend_name+' nochmal deine Freundschaft anbieten" >' +
				'<img class="friendicon"src="/fileadmin/sitetemplates/i/rerequest'+(micro ? '_micro' : '')+'.gif" alt="" />'+
				'</a></div></div>';
			$(element).replace(html);
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function acceptFriendship(uid, friend_name, elements, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_accept&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			$(element).replace('<div><a href="#" onclick="removeFromFriends('+uid+', \''+friend_name+'\', this.parentNode, '+micro+'); return false;" title="'+friend_name+' deine Freundschaft kündigen"><img class="friendicon" src="/fileadmin/sitetemplates/i/remove_friend'+(micro ? '_micro' : '')+'.gif" alt="" /></a></div>');
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function denyFriendship(uid, friend_name, elements, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_decline&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			$(element).replace('<div><a href="#" onclick="requestFriendship('+uid+', \''+friend_name+'\', this.parentNode, '+micro+'); return false;" title="'+friend_name+' deine Freundschaft anbieten"><img class="friendicon" src="/fileadmin/sitetemplates/i/add_as_friend'+(micro ? '_micro' : '')+'.gif" alt="" /></a></div>');
		},
		onFailure: function() {
			alert(ferror);
		}
	});

}

function withdrawFriendshipRequest(uid, friend_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_cancel&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			$(element).replace('<div><a href="#" onclick="requestFriendship('+uid+', \''+friend_name+'\', this.parentNode, '+micro+'); return false;" title="'+friend_name+' deine Freundschaft anbieten"><img class="friendicon" src="/fileadmin/sitetemplates/i/add_as_friend'+(micro ? '_micro' : '')+'.gif" alt="" /></a></div>');
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function resendFriendshipRequest(uid, friend_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=request_resend&tx_cdusers_pifriends[friend_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			alert(friend_name + ' hat nun eine erneut eine Anfrage erhalten.');
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function addToMyHeroes(uid, hero_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=add_hero&tx_cdusers_pifriends[hero_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			$(element).replace('<div><a href="#" onclick="removeFromMyHeroes('+uid+',\''+hero_name+'\', this.parentNode, '+micro+'); return false;" title="'+hero_name+' aus der Liste meiner Helden entfernen"><img class="friendicon" src="/fileadmin/sitetemplates/i/remove_hero'+(micro ? '_micro' : '')+'.gif" alt="" /></a></div>');
		},
		onFailure: function() {
			alert(ferror);
		}
	});
}

function removeFromMyHeroes(uid, hero_name, element, micro) {
	if (typeof(micro) == 'undefined') micro = false;
	new Ajax.Request('/index.php?id=62&tx_cdusers_pifriends[mode]=remove_hero&tx_cdusers_pifriends[hero_uid]='+uid, {
		method: 'get',
		onSuccess: function(transport) {
			$(element).replace('<div><a href="#" onclick="addToMyHeroes('+uid+',\''+hero_name+'\', this.parentNode, '+micro+'); return false;" title="'+hero_name+' zur Liste meiner Helden hinzufügen"><img class="friendicon" src="/fileadmin/sitetemplates/i/add_as_hero'+(micro ? '_micro' : '')+'.gif" alt="" /></a></div>');
		},
		onFailure: function() {
			alert(ferror);
		}
	});

}

function getDynImgUrl(params) {
	var ser = serializeUrl(params);
	var md5 = hex_md5(ser);
	var ext = params.ext ? params.ext : 'gif';
	var path = md5.substr(0,2)+'/'+md5.substr(2,2)+'/'+md5+'.'+ext;;
	var encparams = encodeURIComponent(ser);
	url = '/dynimg/'+encparams+'/'+ path;
	return url;
}

function getTeaserTitleImageUrl(text, nocache) {
//	var params = {type:'tsr',v:6,text:text};
	var params = {type: 'txt', mw: '650', fs: 24, lh: 28, ob:4,  fg: 'ffffff', bg: '333333', text: text.toUpperCase()};
	if (nocache)
		params.nocache = 1;
	return getDynImgUrl(params);
}

function AjaxEvalScripts(node)
{
	var scs = node.getElementsByTagName("script");
	for (var i=0;i<scs.length;i++)
	{
		eval(scs[i].innerHTML);
	}
}
function next_container(prefix) {
	container_number+=1;
	//if (container_number > last_container) container_number = last_container;
	check_containers(prefix);
}

function previous_container(prefix) {
	container_number-=1;
	//if (container_number < 0) container_number=0;
	check_containers(prefix);
}

function check_containers(prefix) {

	//for (var i = 0; i <= last_container; i++) 
	var i=0;
	while($(prefix+"_container_"+i))
	{
		$(prefix+"_container_"+i).style.display = (i == container_number ? "block" : "none");
		i++;
	}
	$(prefix+"_prev").style.display = (container_number >=1 ? "inline" : "none");
	$(prefix+"_next").style.display = $(prefix+"_container_"+(container_number+1))? "inline" : "none";
}

function adjustDashboard(subtab)
{
	if (subtab == 'videos' || subtab == 'photos')
	{
		$('tabber_dashboard_content').style.height = "180px";
		return;
	}
	$('tabber_dashboard_content').style.height = "140px";
}
function changeSmallAvatar(url)
{
    var obj = document.getElementById('small_avatar');
    if (obj)
    {
        obj.src=url;
    }
}
var prevPanel = null;

function togglePanel(id,parent_obj)
{
    var obj = document.getElementById(id);
    if (prevPanel && prevPanel != obj)
    {
        prevPanel.style.display = 'none';
    }
    if (!obj) return;
    if (obj.style.display == 'none')
    {
        if (parent_obj)
        {
            obj.style.top  = (parent_obj.offsetTop+10)+'px';
            obj.style.left = (parent_obj.offsetLeft+10)+'px';
        }
        obj.style.display = '';
    } else {
		obj.style.display = 'none';
	}
    prevPanel = obj;
}

function hidePanel() {
	if (prevPanel) {
		prevPanel.style.display = 'none';
		prevPanel = null;
	}
}

// for image gallery
function jump_to_img(url) {
	var _this = this;
	new Ajax.Request(url, {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || "no response text";
			$('gallery_image_content').update(response);
		},
		onFailure: function(){ alert('Unable to jump to object') }
	});

}

// ajax password strength checker
var pwdCheckEl;
var pwdCheckTimer;
function checkPasswordStrength(el) {
	pwdCheckEl = el;
	if (pwdCheckTimer)
		clearTimeout(pwdCheckTimer);
	pwdCheckTimer = setTimeout('delayedCheckPasswordStrength()', 500);
}

function delayedCheckPasswordStrength() {
	pwdCheckTimer = null;
	var pwd = pwdCheckEl.value;
	var url = '/index.php?id='+PID_PASSWORD_STRENGTH+'&pwd='+pwd;
	new Ajax.Request(url, {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText || 0;
			var strength = parseInt(response);
			var w = Math.round(160 / 5 * strength);
			$('password_strength_div').style.width = w + 'px';
		},
		onFailure: function(){ alert('Unable to check password security') }
	});
}

window.closePmWindow = function() {
	myLightWindow.deactivate();
}

function SearchPager(el, pages, maxpages, obj) {
	this.el = $(el);
	this.pages = pages;
	this.maxpages = maxpages;
	this.obj = obj;
}

SearchPager.prototype.buildpager = function(pageat) {
	if (pageat > this.pages) return;
	
	var html = '';
	var start = Math.max(pageat - Math.floor(this.maxpages / 2), 1);
	var end = Math.min(start + this.maxpages - 1, this.pages);
	start = Math.max(1, end - this.maxpages + 1);	

	for (var i = Math.max(start - 1, 1); i <= Math.min(end + 1, this.pages); i++) {
		html += '<'+(i == pageat ? 'span' : 'a')+' onfocus="this.blur()" href="javascript:void%200" class="page_'+(i == pageat ? 'active' : 'normal')+'" onclick="mapSearch.showResultsPage('+i+');'+this.obj+'.buildpager('+i+');return false;">'+(i < start || i > end ? '...' : i)+'</'+(i == pageat ? 'span' : 'a')+'>';
	}

	this.el.update(html);
}

var parseSelector=(function(){var _1=/\s*,\s*/;var _2=/\s*([\s>+~(),]|^|$)\s*/g;var _3=/([\s>+~,]|[^(]\+|^)([#.:@])/g;var _4=/^[^\s>+~]/;var _5=/[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;function parseSelector(_6,_7){_7=_7||document.documentElement;var _8=_6.split(_1),_9=[];for(var i=0;i<_8.length;i++){var _b=[_7],_c=toStream(_8[i]);for(var j=0;j<_c.length;){var _e=_c[j++],_f=_c[j++],_10="";if(_c[j]=="("){while(_c[j++]!=")"&&j<_c.length){_10+=_c[j]}_10=_10.slice(0,-1)}_b=select(_b,_e,_f,_10)}_9=_9.concat(_b)}return _9}function toStream(_11){var _12=_11.replace(_2,"$1").replace(_3,"$1*$2");if(_4.test(_12)){_12=" "+_12}return _12.match(_5)||[]}function select(_13,_14,_15,_16){return (_17[_14])?_17[_14](_13,_15,_16):[]}var _18={toArray:function(_19){var a=[];for(var i=0;i<_19.length;i++){a.push(_19[i])}return a}};var dom={isTag:function(_1d,tag){return (tag=="*")||(tag.toLowerCase()==_1d.nodeName.toLowerCase())},previousSiblingElement:function(_1f){do{_1f=_1f.previousSibling}while(_1f&&_1f.nodeType!=1);return _1f},nextSiblingElement:function(_20){do{_20=_20.nextSibling}while(_20&&_20.nodeType!=1);return _20},hasClass:function(_21,_22){return (_22.className||"").match("(^|\\s)"+_21+"(\\s|$)")},getByTag:function(tag,_24){return _24.getElementsByTagName(tag)}};var _17={"#":function(_25,_26){for(var i=0;i<_25.length;i++){if(_25[i].getAttribute("id")==_26){return [_25[i]]}}return []}," ":function(_28,_29){var _2a=[];for(var i=0;i<_28.length;i++){_2a=_2a.concat(_18.toArray(dom.getByTag(_29,_28[i])))}return _2a},">":function(_2c,_2d){var _2e=[];for(var i=0,_30;i<_2c.length;i++){_30=_2c[i];for(var j=0,_32;j<_30.childNodes.length;j++){_32=_30.childNodes[j];if(_32.nodeType==1&&dom.isTag(_32,_2d)){_2e.push(_32)}}}return _2e},".":function(_33,_34){var _35=[];for(var i=0,_37;i<_33.length;i++){_37=_33[i];if(dom.hasClass([_34],_37)){_35.push(_37)}}return _35},":":function(_38,_39,_3a){return (pseudoClasses[_39])?pseudoClasses[_39](_38,_3a):[]}};parseSelector.selectors=_17;parseSelector.pseudoClasses={};parseSelector.util=_18;parseSelector.dom=dom;return parseSelector})();
var sIFR=new function(){var _3b=this;var _3c="sIFR-active";var _3d="sIFR-replaced";var _3e="sIFR-flash";var _3f="sIFR-ignore";var _40="sIFR-alternate";var _41="sIFR-class";var _42="sIFR-layout";var _43="sIFR-fixfocus";var _44=6;var _45=126;var _46=8;var _47="SIFR-PREFETCHED";var _48=[];var _49=5;var _4a=9999;var _4b="319";this.isActive=false;this.isEnabled=true;this.hideElements=true;this.preserveSingleWhitespace=false;this.fixWrap=true;this.fixHover=true;this.registerEvents=true;this.setPrefetchCookie=true;this.cookiePath="/";this.domains=[];this.fromLocal=false;this.forceClear=false;this.forceWidth=false;this.fitExactly=false;this.forceTextTransform=true;this.useDomContentLoaded=true;this.hasFlashClassSet=false;this.repaintOnResize=true;this.callbacks=[];var _4c=0;var _4d=false,_4e=false;var dom=new function(){var _50="http://www.w3.org/1999/xhtml";this.getBody=function(){var _51=document.getElementsByTagName("body");if(_51.length==1){return _51[0]}return null};this.addClass=function(_52,_53){if(_53){_53.className=((_53.className||"")==""?"":_53.className+" ")+_52}};this.removeClass=function(_54,_55){if(_55){_55.className=_55.className.replace(new RegExp("(^|\\s)"+_54+"(\\s|$)"),"").replace(/^\s+|(\s)\s+/g,"$1")}};this.hasClass=function(_56,_57){return new RegExp("(^|\\s)"+_56+"(\\s|$)").test(_57.className)};this.hasOneOfClassses=function(_58,_59){for(var i=0;i<_58.length;i++){if(this.hasClass(_58[i],_59)){return true}}return false};this.create=function(_5b){if(document.createElementNS){return document.createElementNS(_50,_5b)}return document.createElement(_5b)};this.setInnerHtml=function(_5c,_5d){if(ua.innerHtmlSupport){_5c.innerHTML=_5d}else{if(ua.xhtmlSupport){_5d=["<root xmlns=\"",_50,"\">",_5d,"</root>"].join("");var xml=(new DOMParser()).parseFromString(_5d,"text/xml");xml=document.importNode(xml.documentElement,true);while(_5c.firstChild){_5c.removeChild(_5c.firstChild)}while(xml.firstChild){_5c.appendChild(xml.firstChild)}}}};this.nodeFromHtml=function(_5f){var _60=this.create("div");_60.innerHTML=_5f;return _60.firstChild};this.getComputedStyle=function(_61,_62){var _63;if(document.defaultView&&document.defaultView.getComputedStyle){_63=document.defaultView.getComputedStyle(_61,null)[_62]}else{if(_61.currentStyle){_63=_61.currentStyle[_62]}}return _63||""};this.getStyleAsInt=function(_64,_65,_66){var _67=this.getComputedStyle(_64,_65);if(_66&&!/px$/.test(_67)){return 0}_67=parseInt(_67);return isNaN(_67)?0:_67};this.getWidthFromStyle=function(_68){var _69=this.getStyleAsInt(_68,"width",ua.ie);if(_69==0){var _6a=this.getStyleAsInt(_68,"paddingRight",true);var _6b=this.getStyleAsInt(_68,"paddingLeft",true);var _6c=this.getStyleAsInt(_68,"borderRightWidth",true);var _6d=this.getStyleAsInt(_68,"borderLeftWidth",true);_69=_68.offsetWidth-_6b-_6a-_6d-_6c}return _69};this.getZoom=function(){return _b2.zoom.getLatest()};this.blurElement=function(_6e){if(ua.gecko){_6e.blur();return}var _6f=dom.create("input");_6f.style.width="0px";_6f.style.height="0px";_6e.parentNode.appendChild(_6f);_6f.focus();_6f.blur();_6f.parentNode.removeChild(_6f)};this.getDimensions=function(_70){var _71=_70.offsetWidth;var _72=_70.offsetHeight;if(_71==0||_72==0){for(var i=0;i<_70.childNodes.length;i++){var _74=_70.childNodes[i];if(_74.nodeType!=1){continue}_71=Math.max(_71,_74.offsetWidth);_72=Math.max(_72,_74.offsetHeight)}}return {width:_71,height:_72}};this.contentIsLink=function(_75){var _76=false;for(var i=0;i<_75.childNodes.length;i++){var _78=_75.childNodes[i];if(_78.nodeType==3&&!_78.nodeValue.match(/^\s*$/)){return false}else{if(_78.nodeType!=1){continue}}var _79=_78.nodeName.toLowerCase()=="a";if(!_79){return false}else{_76=true}}return _76}};this.dom=dom;var ua=new function(){var ua=navigator.userAgent.toLowerCase();var _7c=(navigator.product||"").toLowerCase();this.macintosh=ua.indexOf("mac")>-1;this.windows=ua.indexOf("windows")>-1;this.quicktime=false;this.opera=ua.indexOf("opera")>-1;this.konqueror=_7c.indexOf("konqueror")>-1;this.ie=false/*@cc_on||true@*/;this.ieSupported=this.ie&&!/ppc|smartphone|iemobile|msie\s5\.5/.test(ua)/*@cc_on&&@_jscript_version>=5.5@*/;this.ieWin=this.ie&&this.windows/*@cc_on&&@_jscript_version>=5.1@*/;this.windows=this.windows&&(!this.ie||this.ieWin);this.ieMac=this.ie&&this.macintosh/*@cc_on&&@_jscript_version<5.1@*/;this.macintosh=this.macintosh&&(!this.ie||this.ieMac);this.safari=ua.indexOf("safari")>-1;this.webkit=ua.indexOf("applewebkit")>-1&&!this.konqueror;this.khtml=this.webkit||this.konqueror;this.gecko=!this.webkit&&_7c=="gecko";this.operaVersion=this.opera&&/.*opera(\s|\/)(\d+\.\d+)/.exec(ua)?parseInt(RegExp.$2):0;this.webkitVersion=this.webkit&&/.*applewebkit\/(\d+).*/.exec(ua)?parseInt(RegExp.$1):0;this.geckoBuildDate=this.gecko&&/.*gecko\/(\d{8}).*/.exec(ua)?parseInt(RegExp.$1):0;this.konquerorVersion=this.konqueror&&/.*konqueror\/(\d\.\d).*/.exec(ua)?parseInt(RegExp.$1):0;this.flashVersion=0;if(this.ieWin){var axo;var _7e=false;try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(e){try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");this.flashVersion=6;axo.AllowScriptAccess="always"}catch(e){_7e=this.flashVersion==6}if(!_7e){try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(e){}}}if(!_7e&&axo){this.flashVersion=parseFloat(/([\d,?]+)/.exec(axo.GetVariable("$version"))[1].replace(/,/g,"."))}}else{if(navigator.plugins&&navigator.plugins["Shockwave Flash"]){var _7f=navigator.plugins["Shockwave Flash"];this.flashVersion=parseFloat(/(\d+\.?\d*)/.exec(_7f.description)[1]);var i=0;while(this.flashVersion>=_46&&i<navigator.mimeTypes.length){var _81=navigator.mimeTypes[i];if(_81.type=="application/x-shockwave-flash"&&_81.enabledPlugin.description.toLowerCase().indexOf("quicktime")>-1){this.flashVersion=0;this.quicktime=true}i++}}}this.flash=this.flashVersion>=_46;this.transparencySupport=this.macintosh||this.windows;this.computedStyleSupport=this.ie||document.defaultView&&document.defaultView.getComputedStyle&&(!this.gecko||this.geckoBuildDate>=20030624);this.css=true;if(this.computedStyleSupport){try{var _82=document.getElementsByTagName("head")[0];_82.style.backgroundColor="#FF0000";var _83=dom.getComputedStyle(_82,"backgroundColor");this.css=!_83||/\#F{2}0{4}|rgb\(255,\s?0,\s?0\)/i.test(_83);_82.style.backgroundColor="";_82=null}catch(e){}}this.xhtmlSupport=!!window.DOMParser&&!!document.importNode;try{var n=dom.create("span");if(!this.ieMac){n.innerHTML="x"}this.innerHtmlSupport=n.innerHTML=="x"}catch(e){this.innerHtmlSupport=false}this.zoomSupport=!!(this.opera&&document.documentElement);this.geckoXml=this.gecko&&(document.contentType||"").indexOf("xml")>-1;this.requiresPrefetch=this.ieWin||this.khtml;this.verifiedKonqueror=false;this.supported=this.flash&&this.css&&(!this.ie||this.ieSupported)&&(!this.opera||this.operaVersion>=8)&&(!this.webkit||this.webkitVersion>=412)&&(!this.konqueror||this.konquerorVersion>3.5)&&this.computedStyleSupport&&(this.innerHtmlSupport||!this.khtml&&this.xhtmlSupport)&&(!this.gecko||this.geckoBuildDate>20040804)};this.ua=ua;var _85=new function(){var _86={leading:true,"margin-left":true,"margin-right":true,"text-indent":true};var _87=" ";function capitalize($){return $.toUpperCase()}this.normalize=function(str){if(_3b.preserveSingleWhitespace){return str.replace(/\s/g,_87)}return str.replace(/(\n|\r)+/g,_87).replace(/(\s)\s+/g,"$1").replace(/\xA0/,_87)};this.textTransform=function(_8a,str){switch(_8a){case "uppercase":str=str.toUpperCase();break;case "lowercase":str=str.toLowerCase();break;case "capitalize":var _8c=str;str=str.replace(/^\w|\s\w/g,capitalize);if(str.indexOf("function capitalize")!=-1){var _8d=_8c.replace(/(^|\s)(\w)/g,"$1$1$2$2").split(/^\w|\s\w/g);str="";for(var i=0;i<_8d.length;i++){str+=_8d[i].charAt(0).toUpperCase()+_8d[i].substring(1)}}break}return str};this.toHexString=function(str){if(typeof (str)!="string"||!str.charAt(0)=="#"||str.length!=4&&str.length!=7){return str}str=str.replace(/#/,"");if(str.length==3){str=str.replace(/(.)(.)(.)/,"$1$1$2$2$3$3")}return "0x"+str};this.toJson=function(obj){var _91="";switch(typeof (obj)){case "string":_91="\""+obj+"\"";break;case "number":case "boolean":_91=obj.toString();break;case "object":_91=[];for(var _92 in obj){if(obj[_92]==Object.prototype[_92]){continue}_91.push("\""+_92+"\":"+_85.toJson(obj[_92]))}_91="{"+_91.join(",")+"}";break}return _91};this.convertCssArg=function(arg){if(!arg){return {}}if(typeof (arg)=="object"){if(arg.constructor==Array){arg=arg.join("")}else{return arg}}var obj={};var _95=arg.split("}");for(var i=0;i<_95.length;i++){var $=_95[i].match(/([^\s{]+)\s*\{(.+)\s*;?\s*/);if(!$||$.length!=3){continue}if(!obj[$[1]]){obj[$[1]]={}}var _98=$[2].split(";");for(var j=0;j<_98.length;j++){var $2=_98[j].match(/\s*([^:\s]+)\s*\:\s*([^\s;]+)/);if(!$2||$2.length!=3){continue}obj[$[1]][$2[1]]=$2[2]}}return obj};this.extractFromCss=function(css,_9c,_9d,_9e){var _9f=null;if(css&&css[_9c]&&css[_9c][_9d]){_9f=css[_9c][_9d];if(_9e){delete css[_9c][_9d]}}return _9f};this.cssToString=function(arg){var css=[];for(var _a2 in arg){var _a3=arg[_a2];if(_a3==Object.prototype[_a2]){continue}css.push(_a2,"{");for(var _a4 in _a3){if(_a3[_a4]==Object.prototype[_a4]){continue}var _a5=_a3[_a4];if(_86[_a4]){_a5=parseInt(_a5,10)}css.push(_a4,":",_a5,";")}css.push("}")}return css.join("")};this.bind=function(_a6,_a7){return function(){_a6[_a7].apply(_a6,arguments)}};this.escape=function(str){return escape(str).replace(/\+/g,"%2B")};this.copyProperties=function(_a9,to){for(var _ab in _a9){if(to[_ab]===undefined){to[_ab]=_a9[_ab]}}return to};this.domain=function(){var _ac="";try{_ac=document.domain}catch(e){}return _ac};this.domainMatches=function(_ad,_ae){if(_ae=="*"||_ae==_ad){return true}var _af=_ae.lastIndexOf("*");if(_af>-1){_ae=_ae.substr(_af+1);var _b0=_ad.lastIndexOf(_ae);if(_b0>-1&&(_b0+_ae.length)==_ad.length){return true}}return false};this.uriEncode=function(s){return encodeURI(decodeURIComponent(s))}};this.util=_85;var _b2={};_b2.fragmentIdentifier=new function(){this.fix=true;var _b3;this.cache=function(){_b3=document.title};function doFix(){document.title=_b3}this.restore=function(){if(this.fix){setTimeout(doFix,0)}}};_b2.synchronizer=new function(){this.isBlocked=false;this.block=function(){this.isBlocked=true};this.unblock=function(){this.isBlocked=false;_b4.replaceAll()}};_b2.zoom=new function(){var _b5=100;this.getLatest=function(){return _b5};if(ua.zoomSupport&&ua.opera){var _b6=document.createElement("div");_b6.style.position="fixed";_b6.style.left="-65536px";_b6.style.top="0";_b6.style.height="100%";_b6.style.width="1px";_b6.style.zIndex="-32";document.documentElement.appendChild(_b6);function updateZoom(){if(!_b6){return}var _b7=window.innerHeight/_b6.offsetHeight;var _b8=Math.round(_b7*100)%10;if(_b8>5){_b7=Math.round(_b7*100)+10-_b8}else{_b7=Math.round(_b7*100)-_b8}_b5=isNaN(_b7)?100:_b7;_b2.synchronizer.unblock();document.documentElement.removeChild(_b6);_b6=null}_b2.synchronizer.block();setTimeout(updateZoom,54)}};this.hacks=_b2;this.errors={};var _b9={kwargs:[],replaceAll:function(_ba){for(var i=0;i<this.kwargs.length;i++){_3b.replace(this.kwargs[i])}if(!_ba){this.kwargs=[]}}};var _b4={kwargs:[],replaceAll:_b9.replaceAll};function isValidDomain(){if(_3b.domains.length==0){return true}var _bc=_85.domain();for(var i=0;i<_3b.domains.length;i++){var _be=_3b.domains[i];if(_85.domainMatches(_bc,_be)){return true}}return false}function isFile(){if(!_3b.fromLocal&&document.location.protocol=="file:"){if(_3b.debug){throw new Error(_3b.errors.isFile)}return true}return false}function resize(){var _bf=resize.viewport;resize.viewport={width:window.innerWidth||document.documentElement.clientWidth||dom.getBody().clientWidth,height:window.innerHeight||document.documentElement.clientHeight||dom.getBody().clientHeight};if(_bf&&resize.viewport.width==_bf.width&&resize.viewport.height==_bf.height){return}if(resize.timer){clearTimeout(resize.timer)}resize.timer=setTimeout(function(){delete resize.timer;for(var i=0;i<_3b.callbacks.length;i++){_3b.callbacks[i].resize()}},200)}this.activate=function(){if(!ua.supported||!this.isEnabled||this.isActive||!isValidDomain()||isFile()){return}if(arguments.length>0){this.prefetch.apply(this,arguments)}this.isActive=true;if(this.hideElements){this.setFlashClass()}if(ua.ieWin&&_b2.fragmentIdentifier.fix&&window.location.hash!=""){_b2.fragmentIdentifier.cache()}else{_b2.fragmentIdentifier.fix=false}if(!this.registerEvents){return}function handler(evt,_c2){_3b.initialize(_c2);if(evt&&evt.type=="load"){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",handler,false)}if(window.removeEventListener){window.removeEventListener("load",handler,false)}}}if(window.addEventListener){if(_3b.useDomContentLoaded&&ua.gecko){document.addEventListener("DOMContentLoaded",handler,false)}window.addEventListener("load",handler,false)}else{if(ua.ieWin){if(_3b.useDomContentLoaded){document.write("<scr"+"ipt id=__sifr_ie_onload defer src=//:></script>");document.getElementById("__sifr_ie_onload").onreadystatechange=function(){if(this.readyState=="complete"){handler(null,true);this.removeNode()}}}window.attachEvent("onload",handler)}}};this.setFlashClass=function(){if(this.hasFlashClassSet){return}dom.addClass(_3c,dom.getBody()||document.documentElement);this.hasFlashClassSet=true};this.removeFlashClass=function(){if(!this.hasFlashClassSet){return}dom.removeClass(_3c,dom.getBody());dom.removeClass(_3c,document.documentElement);this.hasFlashClassSet=false};this.initialize=function(_c3){if(!this.isActive||!this.isEnabled){return}if(_4e){if(!_c3){_b9.replaceAll(false)}return}_4e=true;_b9.replaceAll(_c3);if(_3b.repaintOnResize){if(window.addEventListener){window.addEventListener("resize",resize,false)}else{window.attachEvent("onresize",resize)}}clearPrefetch()};function getSource(src){if(typeof (src)!="string"){if(src.src){src=src.src}if(typeof (src)!="string"){var _c5=[];for(var _c6 in src){if(src[_c6]!=Object.prototype[_c6]){_c5.push(_c6)}}_c5.sort().reverse();var _c7="";var i=-1;while(!_c7&&++i<_c5.length){if(parseFloat(_c5[i])<=ua.flashVersion){_c7=src[_c5[i]]}}src=_c7}}if(!src&&_3b.debug){throw new Error(_3b.errors.getSource)}if(ua.ie&&src.charAt(0)=="/"){src=window.location.toString().replace(/([^:]+)(:\/?\/?)([^\/]+).*/,"$1$2$3")+src}return src}this.prefetch=function(){if((!ua.requiresPrefetch&&!this.isActive)||!ua.supported||!this.isEnabled||!isValidDomain()){return}if(this.setPrefetchCookie&&new RegExp(";?"+_47+"=true;?").test(document.cookie)){return}try{_4d=true;if(ua.ieWin){prefetchIexplore(arguments)}else{prefetchLight(arguments)}if(this.setPrefetchCookie){document.cookie=_47+"=true;path="+this.cookiePath}}catch(e){if(_3b.debug){throw e}}};function prefetchIexplore(_c9){for(var i=0;i<_c9.length;i++){document.write("<script defer type=\"sifr/prefetch\" src=\""+getSource(_c9[i])+"\"></script>")}}function prefetchLight(_cb){for(var i=0;i<_cb.length;i++){new Image().src=getSource(_cb[i])}}function clearPrefetch(){if(!ua.ieWin||!_4d){return}try{var _cd=document.getElementsByTagName("script");for(var i=_cd.length-1;i>=0;i--){var _cf=_cd[i];if(_cf.type=="sifr/prefetch"){_cf.parentNode.removeChild(_cf)}}}catch(e){}}function getRatio(_d0,_d1){for(var i=0;i<_d1.length;i+=2){if(_d0<=_d1[i]){return _d1[i+1]}}return _d1[_d1.length-1]||1}function getFilters(obj){var _d4=[];for(var _d5 in obj){if(obj[_d5]==Object.prototype[_d5]){continue}var _d6=obj[_d5];_d5=[_d5.replace(/filter/i,"")+"Filter"];for(var _d7 in _d6){if(_d6[_d7]==Object.prototype[_d7]){continue}_d5.push(_d7+":"+_85.escape(_85.toJson(_85.toHexString(_d6[_d7]))))}_d4.push(_d5.join(","))}return _85.escape(_d4.join(";"))}function calculate(_d8){var _d9,_da;if(!ua.ie){_d9=dom.getStyleAsInt(_d8,"lineHeight");_da=Math.floor(dom.getStyleAsInt(_d8,"height")/_d9)}else{if(ua.ie){var _db=dom.getComputedStyle(_d8,"fontSize");if(_db.indexOf("px")>0){_d9=parseInt(_db)}else{var _dc=_d8.innerHTML;_d8.style.visibility="visible";_d8.style.overflow="visible";_d8.style.position="static";_d8.style.zoom="normal";_d8.style.writingMode="lr-tb";_d8.style.width=_d8.style.height="auto";_d8.style.maxWidth=_d8.style.maxHeight=_d8.style.styleFloat="none";var _dd=_d8;var _de=_d8.currentStyle.hasLayout;if(_de){dom.setInnerHtml(_d8,"<div class=\""+_42+"\">X<br />X<br />X</div>");_dd=_d8.firstChild}else{dom.setInnerHtml(_d8,"X<br />X<br />X")}var _df=_dd.getClientRects();_d9=_df[1].bottom-_df[1].top;_d9=Math.ceil(_d9*0.8);if(_de){dom.setInnerHtml(_d8,"<div class=\""+_42+"\">"+_dc+"</div>");_dd=_d8.firstChild}else{dom.setInnerHtml(_d8,_dc)}_df=_dd.getClientRects();_da=_df.length;if(_de){dom.setInnerHtml(_d8,_dc)}_d8.style.visibility=_d8.style.width=_d8.style.height=_d8.style.maxWidth=_d8.style.maxHeight=_d8.style.overflow=_d8.style.styleFloat=_d8.style.position=_d8.style.zoom=_d8.style.writingMode=""}}}return {lineHeight:_d9,lines:_da}}this.replace=function(_e0,_e1){if(!ua.supported){return}if(_e1){_e0=_85.copyProperties(_e0,_e1)}if(!_4e){return _b9.kwargs.push(_e0)}if(_b2.synchronizer.isBlocked){return _b4.kwargs.push(_e0)}var _e2=_e0.elements;if(!_e2&&parseSelector){_e2=parseSelector(_e0.selector)}if(_e2.length==0){return}this.setFlashClass();var src=getSource(_e0.src);var css=_85.convertCssArg(_e0.css);var _e5=getFilters(_e0.filters);var _e6=(_e0.forceClear==null)?_3b.forceClear:_e0.forceClear;var _e7=_e0.forceSingleLine===true;var _e8=_e7||((_e0.fitExactly==null)?_3b.fitExactly:_e0.fitExactly);var _e9=_e8||(_e0.forceWidth==null?_3b.forceWidth:_e0.forceWidth);var _ea=parseInt(_85.extractFromCss(css,".sIFR-root","leading"))||0;var _eb=_85.extractFromCss(css,".sIFR-root","font-size",true)||0;var _ec=_85.extractFromCss(css,".sIFR-root","background-color",true)||"#FFFFFF";var _ed=_85.extractFromCss(css,".sIFR-root","kerning",true)||"";var _ee=_e0.gridFitType||_85.extractFromCss(css,".sIFR-root","text-align")=="right"?"subpixel":"pixel";var _ef=_3b.forceTextTransform?_85.extractFromCss(css,".sIFR-root","text-transform",true)||"none":"none";var _f0=_85.extractFromCss(css,".sIFR-root","opacity",true)||"100";var _f1=_e0.pixelFont||false;var _f2=_e0.ratios||_48;var _f3=parseInt(_e0.tuneHeight)||0;if(parseInt(_eb).toString()!=_eb&&_eb.indexOf("px")==-1){_eb=0}else{_eb=parseInt(_eb)}if(parseFloat(_f0)<1){_f0=100*parseFloat(_f0)}var _f4="";if(_e8){_85.extractFromCss(css,".sIFR-root","text-align",true)}if(!_e0.modifyCss){_f4=_85.cssToString(css)}var _f5=_e0.wmode||"";if(!_f5){if(_e0.transparent){_f5="transparent"}else{if(_e0.opaque){_f5="opaque"}}}if(_f5=="transparent"){if(!ua.transparencySupport){_f5="opaque"}else{_ec="transparent"}}for(var i=0;i<_e2.length;i++){var _f7=_e2[i];if(!ua.verifiedKonqueror){if(dom.getComputedStyle(_f7,"lineHeight").match(/e\+08px/)){ua.supported=_3b.isEnabled=false;this.removeFlashClass();return}ua.verifiedKonqueror=true}if(dom.hasOneOfClassses([_3d,_3f,_40],_f7)){continue}var _f8=dom.getDimensions(_f7);var _f9=_f8.height;var _fa=_e7?_4a:_f8.width;var _fb=dom.getComputedStyle(_f7,"display");if(!_f9||!_fa||_fb==null||_fb=="none"){continue}if(_e6&&ua.gecko){_f7.style.clear="both"}var _fc=null;if(_3b.fixWrap&&ua.ie&&_fb=="block"){_fc=_f7.innerHTML;dom.setInnerHtml(_f7,"X")}_fa=_e7?_4a:dom.getWidthFromStyle(_f7);if(_fc&&_3b.fixWrap&&ua.ie){dom.setInnerHtml(_f7,_fc)}var _fd,_fe;if(!_eb){var _ff=calculate(_f7);_fd=Math.min(_45,Math.max(_44,_ff.lineHeight));if(_f1){_fd=Math.max(8,8*Math.round(_fd/8))}_fe=_ff.lines;if(isNaN(_fe)||!isFinite(_fe)||_fe==0){_fe=1}if(_fe>1&&_ea){_f9+=Math.round((_fe-1)*_ea)}}else{_fd=_eb;_fe=1}_f9=Math.round(_fe*_fd);if(_e6&&ua.gecko){_f7.style.clear=""}var _100=dom.create("span");_100.className=_40;var _101=_f7.cloneNode(true);_f7.parentNode.appendChild(_101);for(var j=0,l=_101.childNodes.length;j<l;j++){_100.appendChild(_101.childNodes[j].cloneNode(true))}if(_e0.modifyContent){_e0.modifyContent(_101,_e0.selector)}if(_e0.modifyCss){_f4=_e0.modifyCss(css,_101,_e0.selector)}var _104=_3b.fixHover&&dom.contentIsLink(_101);var _105=handleContent(_101,_ef,_e0.uriEncode);_101.parentNode.removeChild(_101);if(_e0.modifyContentString){_105.text=_e0.modifyContentString(_105.text,_e0.selector)}if(_105.text==""){continue}var vars=["content="+_85.escape(_105.text),"antialiastype="+(_e0.antiAliasType||""),"width="+_fa,"height="+_f9,"fitexactly="+_e8,"tunewidth="+(_e0.tuneWidth||""),"tuneheight="+_f3,"offsetleft="+(_e0.offsetLeft||""),"offsettop="+(_e0.offsetTop||""),"thickness="+(_e0.thickness||""),"sharpness="+(_e0.sharpness||""),"kerning="+_ed,"gridfittype="+_ee,"zoomsupport="+ua.zoomSupport,"flashfilters="+_e5,"opacity="+_f0,"blendmode="+(_e0.blendMode||""),"size="+_fd,"zoom="+dom.getZoom(),"css="+_85.escape(_f4),"selectable="+(_e0.selectable==null?"true":_e0.selectable),"fixhover="+_104,"preventwrap="+_e0.preventWrap,"link="+_85.escape(_105.primaryLink[0]||""),"target="+_85.escape(_105.primaryLink[1]||""),"version="+_4b];var _107=encodeVars(vars);var _108="sIFR_callback_"+_4c++;var _109=new CallbackInfo(_108,vars,_e0.onReplacement);window[_108+"_DoFSCommand"]=(function(_10a){return function(info,arg){_10a.handle(info,arg)}})(_109);_100.setAttribute("id",_108+"_alternate");_f9=Math.round(_fe*getRatio(_fd,_f2)*_fd)+_49+_f3;var _10d=_e9?_fa:"100%";var _10e;if(ua.ie){_10e=["<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" id=\"",_108,"\" sifr=\"true\" width=\"",_10d,"\" height=\"",_f9,"\" class=\"",_3e,"\">","<param name=\"movie\" value=\"",src,"\"></param>","<param name=\"flashvars\" value=\"",_107,"\"></param>","<param name=\"allowScriptAccess\" value=\"always\"></param>","<param name=\"quality\" value=\"best\"></param>","<param name=\"wmode\" value=\"",_f5,"\"></param>","<param name=\"bgcolor\" value=\"",_ec,"\"></param>","<param name=\"name\" value=\"",_108,"\"></param>","</object>","<scr","ipt event=FSCommand(info,args) for=",_108,">",_108,"_DoFSCommand(info, args);","</","script>"].join("")}else{_10e=["<embed type=\"application/x-shockwave-flash\" class=\""+_3e+"\" src=\"",src,"\" quality=\"best\" flashvars=\"",_107,"\" width=\"",_10d,"\" height=\"",_f9,"\" wmode=\"",_f5,"\" bgcolor=\"",_ec,"\" name=\"",_108,"\" id=\"",_108,"\" allowScriptAccess=\"always\" sifr=\"true\"></embed>"].join("")}var _10f=_e0.fixFocus?"<div class=\""+_43+"\">"+_10e+"</div>":_10e;dom.setInnerHtml(_f7,_10f);_109.html=_10e;_3b.callbacks.push(_109);if(_e0.selector){if(!_3b.callbacks[_e0.selector]){_3b.callbacks[_e0.selector]=[_109]}else{_3b.callbacks[_e0.selector].push(_109)}}_f7.appendChild(_100);dom.addClass(_3d,_f7)}_b2.fragmentIdentifier.restore()};this.getCallbackByFlashElement=function(node){for(var i=0;i<_3b.callbacks.length;i++){if(_3b.callbacks[i].id==node.getAttribute("id")){return _3b.callbacks[i]}}};this.redraw=function(){for(var i=0;i<_3b.callbacks.length;i++){_3b.callbacks[i].resetMovie()}};function encodeVars(vars){return vars.join("&amp;").replace(/%/g,"%25")}function handleContent(_114,_115,_116){_116=_116||_85.uriEncode;var _117=[],_118=[],_119=[];var _11a=_114.childNodes;var i=0;while(i<_11a.length){var node=_11a[i];if(node.nodeType==3){var text=_85.normalize(node.nodeValue);text=_85.textTransform(_115,text);text=text.replace(/</g,"&lt;");_118.push(text)}if(node.nodeType==1){var _11e=[];var _11f=node.nodeName.toLowerCase();var _120=node.className||"";if(/\s+/.test(_120)){if(_120.indexOf(_41)>-1){_120=_120.match("(\\s|^)"+_41+"-([^\\s$]*)(\\s|$)")[2]}else{_120=_120.match(/^([^\s]+)/)[1]}}if(_120!=""){_11e.push("class=\""+_120+"\"")}if(_11f=="a"){var href=_116(node.getAttribute("href")||"");var _122=node.getAttribute("target")||"";_11e.push("href=\""+href+"\"","target=\""+_122+"\"");if(_119.length==0){_119=[href,_122]}}_118.push("<"+_11f+(_11e.length>0?" ":"")+_11e.join(" ")+">");if(node.hasChildNodes()){_117.push(i);i=0;_11a=node.childNodes;continue}else{if(!/^(br|img)$/i.test(node.nodeName)){_118.push("</",node.nodeName.toLowerCase(),">")}}}if(_117.length>0&&!node.nextSibling){do{i=_117.pop();_11a=node.parentNode.parentNode.childNodes;node=_11a[i];if(node){_118.push("</",node.nodeName.toLowerCase(),">")}}while(i==_11a.length-1&&_117.length>0)}i++}return {text:_118.join("").replace(/\n|\r/g,""),primaryLink:_119}}function CallbackInfo(id,vars,_125,_126){this.id=id;this.vars=vars;this._replacementHandler=_125;this._firedReplacementEvent=!(this._replacementHandler!=null);this._fixHover=_126;this.html=""}CallbackInfo.prototype.getFlashElement=function(){return document.getElementById(this.id)};CallbackInfo.prototype.available=function(){var _127=this.getFlashElement();return _127&&_127.parentNode};CallbackInfo.prototype.handle=function(info,arg){if(!this.available()){return}if(/(FSCommand\:)?resize/.test(info)){var _12a=this.getFlashElement();var $=arg.split(/\:|,/);_12a.setAttribute($[0],$[1]);if($.length>2){_12a.setAttribute($[2],$[3])}if(ua.khtml){var _12c=_12a.offsetHeight}if(!this._firedReplacementEvent){this._replacementHandler(this);this._firedReplacementEvent=true}}else{if(/(FSCommand\:)?resetmovie/.test(info)){this.resetMovie()}else{if(/(FSCommand\:)?blur/.test(info)){dom.blurElement(this.getFlashElement())}else{if(this.debugHandler&&/(FSCommand\:)?debug/.test(info)){this.debugHandler(info,arg)}}}}};CallbackInfo.prototype.call=function(type,_12e){if(!this.available()){return false}var _12f=this.getFlashElement();try{_12f.SetVariable("callbackType",type);_12f.SetVariable("callbackValue",_12e);_12f.SetVariable("callbackTrigger",true)}catch(e){return false}return true};CallbackInfo.prototype.replaceText=function(_130){var _131=_85.escape(_130);this.injectVars("content",_131);if(this.call("replacetext",_131)){dom.setInnerHtml(this.getAlternate(),_130);return true}return false};CallbackInfo.prototype.injectVars=function(name,_133){for(var i=0;i<this.vars.length;i++){if(this.vars[i].split("=")[0]==name){this.vars[i]=name+"="+_133;break}}this.html=this.html.replace(/(flashvars(=|\"\svalue=)\")[^\"]+/,"$1"+encodeVars(this.vars))};CallbackInfo.prototype.resetMovie=function(){if(!this.available()){return}var _135=this.getFlashElement();var node=_135.parentNode;node.replaceChild(dom.nodeFromHtml(this.html),_135)};CallbackInfo.prototype.resize=function(){if(!this.available()){return}var _137=this.getFlashElement();var _138=_137.parentNode;_137.style.width="0px";_137.style.height="0px";var _139=this.getAlternate().childNodes;var _13a=[];for(var i=0;i<_139.length;i++){var node=_139[i].cloneNode(true);_13a.push(node);_138.appendChild(node)}var _13d=dom.getWidthFromStyle(_138);for(var i=0;i<_13a.length;i++){_138.removeChild(_13a[i])}_137.style.width="";_137.style.height="";if(_13d>0){this.call("resize",_13d)}};CallbackInfo.prototype.changeCSS=function(css){css=_85.escape(_85.cssToString(_85.convertCssArg(css)));this.injectVars("css",css);return this.call("changecss",css)};CallbackInfo.prototype.getAlternate=function(){return document.getElementById(this.id+"_alternate")}};

var dbg_enabled = false;

var dbg_buffer = '';
var dbg_timer = null;

function dbg(msg)
{
	if (! dbg_enabled)
		return;
	msg += '<br />';
	if (dbg_buffer !== null) {
		dbg_buffer += msg;
	} else {
		var d = document.getElementById('dbg_div');
		d.innerHTML += msg;
		d.scrollTop = 1000000;
	}
}

function dbg_obj(obj) {
	if (! dbg_enabled)
		return;

	var msg = '{';
	for (key in obj) {
		msg += '  ' + key + ' => ' + obj[key] + '<br>\n';
	}
	msg += '}\n';
	dbg(msg);
}

function dbg_toggle() {
	var e = document.getElementById('dbg_div');
	
	var display = e.style.display;
	display = (display == 'block') ? 'none' : 'block';
	e.style.display = display;
	if (display == 'block')
		e.scrollTop = 1000000;
}

function dbg_init() {
	// as long as body element is not available do nothing
	if (! document.body || ! document.body.firstChild)
		return;

	// clear timer
	clearTimeout(dbg_timer);
	dbg_timer = null;

	var target = document.body;
	var div = document.createElement('div');
	div.innerHTML =
		'<div style="position:absolute; top:0px; left:100px;">'+
			'<a href="#" style="position:absolute; top:0px; left:0px; z-index:1000; color:red;" onclick="dbg_toggle(); return false">+</a>'+
			'<a href="#" style="position:absolute; top:16px; left:0px; z-index:1000; color:red;" onclick="dbg_clear(); return false">C</a>'+
			'<div id="dbg_div" style="position:absolute; top:0px; left:0px; background-color:#FFAAAA; border:1px solid blue; color:black; width:800px; height:80px; overflow-y:auto; padding-left:20px; display:none"></div>'+
		'</div>';

	target.insertBefore(div, target.firstChild);

	// insert collected debug content
	document.getElementById('dbg_div').innerHTML = dbg_buffer;
	dbg_buffer = null;
}

function dbg_clear() {
	document.getElementById('dbg_div').innerHTML = '';
}

var dbg_timer;
if (dbg_enabled)
	dbg_timer = setInterval('dbg_init()', 500);

// script.aculo.us effects.js v1.7.1_beta2, Sat Apr 28 15:20:12 CEST 2007

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

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

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

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

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

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

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

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

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

Array.prototype.call = function() {
  var args = arguments;
  this.each(function(f){ f.apply(this, args) });
}

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

var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  tagifyText: function(element) {
    if(typeof Builder == 'undefined')
      throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
      
    var tagifyStyle = 'position:relative';
    if(Prototype.Browser.IE) tagifyStyle += ';zoom:1';
    
    element = $(element);
    $A(element.childNodes).each( function(child) {
      if(child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            Builder.node('span',{style: tagifyStyle},
              character == ' ' ? String.fromCharCode(160) : character), 
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if(((typeof element == 'object') || 
        (typeof element == 'function')) && 
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;
      
    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || {});
    var masterDelay = options.delay;

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

var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {
  linear: Prototype.K,
  sinoidal: function(pos) {
    return (-Math.cos(pos*Math.PI)/2) + 0.5;
  },
  reverse: function(pos) {
    return 1-pos;
  },
  flicker: function(pos) {
    var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
    return (pos > 1 ? 1 : pos);
  },
  wobble: function(pos) {
    return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
  },
  pulse: function(pos, pulses) { 
    pulses = pulses || 5; 
    return (
      Math.round((pos % (1/pulses)) * pulses) == 0 ? 
            ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : 
        1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
      );
  },
  none: function(pos) {
    return 0;
  },
  full: function(pos) {
    return 1;
  }
};

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

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
  initialize: function() {
    this.effects  = [];
    this.interval = null;    
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();
    
    var position = (typeof effect.options.queue == 'string') ? 
      effect.options.queue : effect.options.queue.position;
    
    switch(position) {
      case 'front':
        // move unstarted effects after this effect  
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'with-last':
        timestamp = this.effects.pluck('startOn').max() || timestamp;
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }
    
    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

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

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if(typeof queueName != 'string') return queueName;
    
    if(!this.instances[queueName])
      this.instances[queueName] = new Effect.ScopedQueue();
      
    return this.instances[queueName];
  }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
  transition: Effect.Transitions.sinoidal,
  duration:   1.0,   // seconds
  fps:        100,   // 100= assume 66fps max.
  sync:       false, // true for combining
  from:       0.0,
  to:         1.0,
  delay:      0.0,
  queue:      'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
  position: null,
  start: function(options) {
    function codeForEvent(options,eventName){
      return (
        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
        (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
      );
    }
    if(options.transition === false) options.transition = Effect.Transitions.linear;
    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn+(this.options.duration*1000);
    this.fromToDelta  = this.options.to-this.options.from;
    this.totalTime    = this.finishOn-this.startOn;
    this.totalFrames  = this.options.fps*this.options.duration;
    
    eval('this.render = function(pos){ '+
      'if(this.state=="idle"){this.state="running";'+
      codeForEvent(options,'beforeSetup')+
      (this.setup ? 'this.setup();':'')+ 
      codeForEvent(options,'afterSetup')+
      '};if(this.state=="running"){'+
      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
      'this.position=pos;'+
      codeForEvent(options,'beforeUpdate')+
      (this.update ? 'this.update(pos);':'')+
      codeForEvent(options,'afterUpdate')+
      '}}');
    
    this.event('beforeStart');
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if(timePos >= this.startOn) {
      if(timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if(this.finish) this.finish(); 
        this.event('afterFinish');
        return;  
      }
      var pos   = (timePos - this.startOn) / this.totalTime,
          frame = Math.round(pos * this.totalFrames);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  cancel: function() {
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    var data = $H();
    for(property in this)
      if(typeof this[property] != 'function') data[property] = this[property];
    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
}

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

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

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

Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Bug in Opera: Opera returns the "real" position of a static element or
    // relative element that does not have top/left explicitly set.
    // ==> Always set top and left for position relative elements in your stylesheets 
    // (to 0 if you do not need them) 
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if(this.options.mode == 'absolute') {
      // absolute movement, so we need to calc deltaX and deltaY
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: Math.round(this.options.x  * position + this.originalLeft) + 'px',
      top:  Math.round(this.options.y  * position + this.originalTop)  + 'px'
    });
  }
});

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

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');
    
    this.originalStyle = {};
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
    
    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].each( function(fontSizeType) {
      if(fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));
    
    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
    
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if(this.options.scaleContent && this.fontSize)
      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = {};
    if(this.options.scaleX) d.width = Math.round(width) + 'px';
    if(this.options.scaleY) d.height = Math.round(height) + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

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

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    this.start(arguments[1] || {});
  },
  setup: function() {
    Position.prepare();
    var offsets = Position.cumulativeOffset(this.element);
    if(this.options.offset) offsets[1] += this.options.offset;
    var max = window.innerHeight ? 
      window.height - window.innerHeight :
      document.body.scrollHeight - 
        (document.documentElement.clientHeight ? 
          document.documentElement.clientHeight : document.body.clientHeight);
    this.scrollStart = Position.deltaY;
    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
  },
  update: function(position) {
    Position.prepare();
    window.scrollTo(Position.deltaX, 
      this.scrollStart + (position*this.delta));
  }
});

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

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

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

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

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

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

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

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

Effect.Shake = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element, 
      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
        effect.element.undoPositioned().setStyle(oldStyle);
  }}) }}) }}) }}) }}) }});
}

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

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

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

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

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

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

  var dims = element.getDimensions();
  var moveX, moveY;
  
  switch (options.direction) {
    case 'top-left':
      moveX = moveY = 0;
      break;
    case 'top-right':
      moveX = dims.width;
      moveY = 0;
      break;
    case 'bottom-left':
      moveX = 0;
      moveY = dims.height;
      break;
    case 'bottom-right':
      moveX = dims.width;
      moveY = dims.height;
      break;
    case 'center':  
      moveX = dims.width / 2;
      moveY = dims.height / 2;
      break;
  }
  
  return new Effect.Parallel(
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
    ], Object.extend({            
         beforeStartInternal: function(effect) {
           effect.effects[0].element.makePositioned().makeClipping(); 
         },
         afterFinishInternal: function(effect) {
           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
       }, options)
  );
}

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || {};
  var oldOpacity = element.getInlineOpacity();
  var transition = options.transition || Effect.Transitions.sinoidal;
  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
  reverser.bind(transition);
  return new Effect.Opacity(element, 
    Object.extend(Object.extend({  duration: 2.0, from: 0,
      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
    }, options), {transition: reverser}));
}

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

Effect.Morph = Class.create();
Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      style: {}
    }, arguments[1] || {});
    if (typeof options.style == 'string') {
      if(options.style.indexOf(':') == -1) {
        var cssText = '', selector = '.' + options.style;
        $A(document.styleSheets).reverse().each(function(styleSheet) {
          if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
          else if (styleSheet.rules) cssRules = styleSheet.rules;
          $A(cssRules).reverse().each(function(rule) {
            if (selector == rule.selectorText) {
              cssText = rule.style.cssText;
              throw $break;
            }
          });
          if (cssText) throw $break;
        });
        this.style = cssText.parseStyle();
        options.afterFinishInternal = function(effect){
          effect.element.addClassName(effect.options.style);
          effect.transforms.each(function(transform) {
            if(transform.style != 'opacity')
              effect.element.style[transform.style] = '';
          });
        }
      } else this.style = options.style.parseStyle();
    } else this.style = $H(options.style)
    this.start(options);
  },
  setup: function(){
    function parseColor(color){
      if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
      color = color.parseColor();
      return $R(0,2).map(function(i){
        return parseInt( color.slice(i*2+1,i*2+3), 16 ) 
      });
    }
    this.transforms = this.style.map(function(pair){
      var property = pair[0], value = pair[1], unit = null;

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

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

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

Element.CSS_PROPERTIES = $w(
  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  'fontSize fontWeight height left letterSpacing lineHeight ' +
  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  'right textIndent top width wordSpacing zIndex');
  
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.prototype.parseStyle = function(){
  var element = document.createElement('div');
  element.innerHTML = '<div style="' + this + '"></div>';
  var style = element.childNodes[0].style, styleRules = $H();
  
  Element.CSS_PROPERTIES.each(function(property){
    if(style[property]) styleRules[property] = style[property]; 
  });
  if(Prototype.Browser.IE && this.indexOf('opacity') > -1) {
    styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
  }
  return styleRules;
};

Element.morph = function(element, style) {
  new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
  return element;
};

['getInlineOpacity','forceRerendering','setContentZoom',
 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( 
  function(f) { Element.Methods[f] = Element[f]; }
);

Element.Methods.visualEffect = function(element, effect, options) {
  s = effect.dasherize().camelize();
  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
  new Effect[effect_class](element, options);
  return $(element);
};

Element.addMethods();// lightwindow.js v2.0
//
// Copyright (c) 2007 stickmanlabs
// Author: Kevin P Miller | http://www.stickmanlabs.com
// 
// LightWindow is freely distributable under the terms of an MIT-style license.
//
// I don't care what you think about the file size...
//   Be a pro: 
//      http://www.thinkvitamin.com/features/webapps/serving-javascript-fast
//      http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files
//

/*-----------------------------------------------------------------------------------------------*/

if(typeof Effect == 'undefined')
  throw("lightwindow.js requires including script.aculo.us' effects.js library!");

// This will stop image flickering in IE6 when elements with images are moved
try {
  document.execCommand("BackgroundImageCache", false, true);
} catch(e) {}

var lightwindow = Class.create(); 
lightwindow.prototype = {
  //
  //  Setup Variables
  //
  element : null,
  contentToFetch : null,
  windowActive : false,
  dataEffects : [],
  dimensions : {
    cruft : null,
    container : null,
    viewport : {
      height : null,
      width : null,
      offsetTop : null,
      offsetLeft : null
    }
  },
  pagePosition : {
    x : 0,
    y : 0
  },
  pageDimensions : {
    width : null,
    height : null
  },
  preloadImage : [],
  preloadedImage : [],
  galleries : [],
  resizeTo : {
    height : null,
    heightPercent : null,
    width : null,
    widthPercent : null,
    fixedTop : null,
    fixedLeft : null
  },
  scrollbarOffset : 18,
  navigationObservers : {
    previous : null,
    next : null
  },
  containerChange : {
    height : 0,
    width : 0
  },
  activeGallery : false,
  galleryLocation : {
    current : 0,
    total : 0
  },
  //
  //  Initialize the lightwindow.
  //
  initialize : function(options) {
    this.options = Object.extend({
      resizeSpeed : 8,
      contentOffset : {
        height : 0,
        width : 0
      },
      dimensions : {
        image : {height : 250, width : 250},
        page : {height : 250, width : 250},
        inline : {height : 250, width : 250},
        media : {height : 250, width : 250},
        external : {height : 250, width : 250},
        titleHeight : 25
      },
      classNames : {  
        standard : 'lightwindow',
        action : 'lightwindow_action'
      },
      fileTypes : {
        page : ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php4', 'php3', 'php', 'php5', 'phtml', 'rhtml', 'shtml', 'txt', 'vbs', 'rb'],
        media : ['aif', 'aiff', 'asf', 'avi', 'divx', 'm1v', 'm2a', 'm2v', 'm3u', 'mid', 'midi', 'mov', 'moov', 'movie', 'mp2', 'mp3', 'mpa', 'mpa', 'mpe', 'mpeg', 'mpg', 'mpg', 'mpga', 'pps', 'qt', 'rm', 'ram', 'swf', 'viv', 'vivo', 'wav'],
        image : ['bmp', 'gif', 'jpg', 'png', 'tiff']
      },
      mimeTypes : {
        avi : 'video/avi',
        aif : 'audio/aiff',
        aiff : 'audio/aiff',
        gif : 'image/gif',
        bmp : 'image/bmp',
        jpeg : 'image/jpeg',
        m1v : 'video/mpeg',
        m2a : 'audio/mpeg',
        m2v : 'video/mpeg',
        m3u : 'audio/x-mpequrl',
        mid : 'audio/x-midi',
        midi : 'audio/x-midi',
        mjpg : 'video/x-motion-jpeg',
        moov : 'video/quicktime',
        mov : 'video/quicktime',
        movie : 'video/x-sgi-movie',
        mp2 : 'audio/mpeg',
        mp3 : 'audio/mpeg3',
        mpa : 'audio/mpeg',
        mpa : 'video/mpeg',
        mpe : 'video/mpeg',
        mpeg : 'video/mpeg',
        mpg : 'audio/mpeg',
        mpg : 'video/mpeg',
        mpga : 'audio/mpeg',
        pdf : 'application/pdf',
        png : 'image/png',
        pps : 'application/mspowerpoint',
        qt : 'video/quicktime',
        ram : 'audio/x-pn-realaudio-plugin',
        rm : 'application/vnd.rn-realmedia',
        swf : 'application/x-shockwave-flash',
        tiff : 'image/tiff',
        viv : 'video/vivo',
        vivo : 'video/vivo',
        wav : 'audio/wav',
        wmv : 'application/x-mplayer2'      
      },  
      classids : {
        mov : 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
        swf : 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000',
        wmv : 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6'
      },
      codebases : {
        mov : 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
        swf : 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0',
        wmv : 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715'
      },  
      viewportPadding : 0,
      EOLASFix : 'swf,wmv,fla,flv',
      overlay : {
        opacity : 0.7,
        image : '/fileadmin/js/lightwindow/images/black.png',
        presetImage : '/fileadmin/js/lightwindow/images/black-70.png'
      },
      skin :  {
        main :  '<div id="lightwindow_container" >'+
              '<div id="lightwindow_title_bar" >'+
                '<div id="lightwindow_title_bar_inner" >'+
                  '<span id="lightwindow_title_bar_title"></span>'+
                  '<a id="lightwindow_title_bar_close_link" >schließen</a>'+
                '</div>'+
              '</div>'+
              '<div id="lightwindow_stage" >'+
                '<div id="lightwindow_contents" >'+
                '</div>'+
                '<div id="lightwindow_navigation" >'+
                  '<a href="#" id="lightwindow_previous" >'+
                    '<span id="lightwindow_previous_title"></span>'+
                  '</a>'+
                  '<a href="#" id="lightwindow_next" >'+
                    '<span id="lightwindow_next_title"></span>'+
                  '</a>'+
                  '<iframe name="lightwindow_navigation_shim" id="lightwindow_navigation_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>'+
                '</div>'+               
                '<div id="lightwindow_galleries">'+
                  '<div id="lightwindow_galleries_tab_container" >'+
                    '<a href="#" id="lightwindow_galleries_tab" >'+
                      '<span id="lightwindow_galleries_tab_span" class="up" >Galleries</span>'+
                    '</a>'+
                  '</div>'+
                  '<div id="lightwindow_galleries_list" >'+
                  '</div>'+
                '</div>'+
              '</div>'+
              '<div id="lightwindow_data_slide" >'+
                '<div id="lightwindow_data_slide_inner" >'+
                  '<div id="lightwindow_data_details" >'+
                    '<div id="lightwindow_data_gallery_container" >'+
                      '<span id="lightwindow_data_gallery_current"></span>'+
                      ' of '+
                      '<span id="lightwindow_data_gallery_total"></span>'+
                    '</div>'+
                    '<div id="lightwindow_data_author_container" >'+
                      'by <span id="lightwindow_data_author"></span>'+
                    '</div>'+
                  '</div>'+
                  '<div id="lightwindow_data_caption" >'+
                  '</div>'+
                '</div>'+
              '</div>'+
            '</div>', 
        loading : '<div id="lightwindow_loading" >'+
                '<img src="/fileadmin/js/lightwindow/images/ajax-loading.gif" alt="loading" />'+
                '<span>Bitte warten... <a href="javascript: myLightWindow.deactivate();">abbrechen</a></span>'+
                '<iframe name="lightwindow_loading_shim" id="lightwindow_loading_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>'+
              '</div>',
        iframe :  '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'+
              '<html xmlns="http://www.w3.org/1999/xhtml">'+
                '<body>'+
                  '{body_replace}'+
                '</body>'+
              '</html>',
        gallery : {
          top :   '<div class="lightwindow_galleries_list">'+
                  '<h1>{gallery_title_replace}</h1>'+
                  '<ul>',
          middle :      '<li>'+
                      '{gallery_link_replace}'+
                    '</li>',
          bottom :    '</ul>'+
                '</div>'
        }
      },
      formMethod : 'post',
      hideFlash : true,
      hideGalleryTab : false,
      showTitleBar : true,
      animationHandler : false,
      navigationHandler : false,
      transitionHandler : false,
      finalAnimationHandler : false,
      formHandler : false,
      galleryAnimationHandler : false,
      showGalleryCount : true
    }, options || {});
    this.duration = ((11-this.options.resizeSpeed)*0.15);
    this._setupLinks();
    this._getScroll();
    this._getPageDimensions();
    this._browserDimensions();
    this._addLightWindowMarkup(false);
    this._setupDimensions(); 
    this.buildGalleryList();
  },
  //
  //  Activate the lightwindow.
  //
  activate : function(e, link){   
    // Clear out the window Contents
    this._clearWindowContents(true);
      
    // Add back in out loading panel
    this._addLoadingWindowMarkup();

    // Setup the element properties
    this._setupWindowElements(link);
    
    // Setup everything
    this._getScroll();
    this._browserDimensions();
    this._setupDimensions();
    this._toggleTroubleElements('hidden', false);
    this._displayLightWindow('block', 'hidden');
    this._setStatus(true);
    this._monitorKeyboard(true);
    this._prepareIE(true);
    this._loadWindow();
  },
  //
  //  Turn off the window
  //
  deactivate : function(){
    // The window is not active
    this.windowActive = false;
    
    // There is no longer a gallery active
    this.activeGallery = false;
    if (!this.options.hideGalleryTab) {
      this._handleGalleryAnimation(false);
    }
    
    // Kill the animation
    this.animating = false;
    
    // Clear our element
    this.element = null;
    
    // hide the window.
    this._displayLightWindow('none', 'visible');
    
    // Clear out the window Contents
    this._clearWindowContents(false);
    
    // Stop all animation
    var queue = Effect.Queues.get('lightwindowAnimation').each(function(e){e.cancel();});
    
    // Undo the setup
    this._prepareIE(false);
    this._setupDimensions();
    this._toggleTroubleElements('visible', false);
    this._monitorKeyboard(false);

	if (window.showEmbeds) {
		window.showEmbeds(true);
	}
  },
  //
  //  Initialize specific window
  //
  createWindow : function(element, attributes) {
    this._processLink($(element));
  },
  //
  //  Open a Window from a hash of attributes
  //
  activateWindow : function(options) {
    this.element = Object.extend({
      href : null,
      title : null,
      author : null,
      caption : null,
      rel : null,
      top : null,
      left : null,
      type : null,
      showImages : null,
      height : null,
      width : null,
      loadingAnimation : null,
      iframeEmbed : null,
      form : null
    }, options || {});
    
    // Set the window type
    this.contentToFetch = this.element.href;
    this.windowType = this.element.type ? this.element.type : this._fileType(this.element.href);  
    
    // Clear out the window Contents
    this._clearWindowContents(true);
      
    // Add back in out loading panel
    this._addLoadingWindowMarkup();
    
    // Setup everything
    this._getScroll();
    this._browserDimensions();
    this._setupDimensions();
    this._toggleTroubleElements('hidden', false);
    this._displayLightWindow('block', 'hidden');
    this._setStatus(true);
    this._monitorKeyboard(true);
    this._prepareIE(true);
    this._loadWindow();
  },
  //
  //  Fire off our Form handler
  //
  submitForm : function(e) {
    if (this.options.formHandler) {
      this.options.formHandler(e);
    } else {
      this._defaultFormHandler(e);
    }
  },
  //
  //  Reload the window with another location
  //
  openWindow : function(element) {
    var element = $(element);

    // The window is active
    this.windowActive = true;
    
    // Clear out the window Contents
    this._clearWindowContents(true);
    
    // Add back in out loading panel
    this._addLoadingWindowMarkup();
    
    // Setup the element properties
    this._setupWindowElements(element);

    this._setStatus(true);
    this._handleTransition();
  },
  //
  //  Navigate the window
  //
  navigateWindow : function(direction) {
    this._handleNavigation(false);
    if (direction == 'previous') {
      this.openWindow(this.navigationObservers.previous);
    } else if (direction == 'next'){ 
      this.openWindow(this.navigationObservers.next);
    }
  },
  //
  //  Build the Gallery List and Load it
  //
  buildGalleryList : function() {
    var output = '';
    var galleryLink;
    for (i in this.galleries) {
      if (typeof this.galleries[i] == 'object') {
        output += (this.options.skin.gallery.top).replace('{gallery_title_replace}', unescape(i));
        for (j in this.galleries[i]) {
          if (typeof this.galleries[i][j] == 'object') {            
            galleryLink = '<a href="#" id="lightwindow_gallery_'+i+'_'+j+'" >'+unescape(j)+'</a>';
            output += (this.options.skin.gallery.middle).replace('{gallery_link_replace}', galleryLink);
          }
        }
        output += this.options.skin.gallery.bottom;
      }
    }
    new Insertion.Top('lightwindow_galleries_list', output);
    
    // Attach Events
    for (i in this.galleries) {
      if (typeof this.galleries[i] == 'object') {
        for (j in this.galleries[i]) {
          if (typeof this.galleries[i][j] == 'object') {
            Event.observe($('lightwindow_gallery_'+i+'_'+j), 'click', this.openWindow.bind(this, this.galleries[i][j][0]), false);
            $('lightwindow_gallery_'+i+'_'+j).onclick = function() {return false;}; 
          }
        }
      }
    }
  },
  // 
  //  Set Links Up
  //
  _setupLinks : function() {
    var links = $$('.'+this.options.classNames.standard);
    links.each(function(link) {
      this._processLink(link);
    }.bind(this));  
  },
  //
  //  Process a Link
  //
  _processLink : function(link) {
    if ((this._fileType(link.getAttribute('href')) == 'image' || this._fileType(link.getAttribute('href')) == 'media')) {
      if (gallery = this._getGalleryInfo(link.rel)) {
        if (!this.galleries[gallery[0]]) {
          this.galleries[gallery[0]] = new Array();
        }
        if (!this.galleries[gallery[0]][gallery[1]]) {
          this.galleries[gallery[0]][gallery[1]] = new Array();
        }
        this.galleries[gallery[0]][gallery[1]].push(link);
      }
    }
    
    // Take care of our inline content
    var url = link.getAttribute('href');
    if (url.indexOf('?') > -1) {
      url = url.substring(0, url.indexOf('?'));
    }
    
    var container = url.substring(url.indexOf('#')+1);
    if($(container)) {
      $(container).setStyle({
        display : 'none'
      });
    }
    
    Event.observe(link, 'click', this.activate.bindAsEventListener(this, link), false);
    link.onclick = function() {return false;};    
  },
  //
  //  Setup our actions
  //
  _setupActions : function() {
    var links = $$('#lightwindow_container .'+this.options.classNames.action);
    links.each(function(link) {
      Event.observe(link, 'click', this[link.getAttribute('rel')].bindAsEventListener(this, link), false);
      link.onclick = function() {return false;};
    }.bind(this));
  },
  //
  //  Add the markup to the page.
  //
  _addLightWindowMarkup : function(rebuild) {
    var overlay = Element.extend(document.createElement('div'));
    overlay.setAttribute('id', 'lightwindow_overlay');    
    // FF Mac has a problem with putting Flash above a layer without a 100% opacity background, so we need to use a pre-made
    if (Prototype.Browser.Gecko) {
      overlay.setStyle({
        backgroundImage: 'url('+this.options.overlay.presetImage+')',
        backgroundRepeat: 'repeat',
        height: (this.pageDimensions.height+500)+'px'
      });     
    } else {
      overlay.setStyle({
        opacity: this.options.overlay.opacity,
        backgroundImage: 'url('+this.options.overlay.image+')',
        backgroundRepeat: 'repeat',
        height: (this.pageDimensions.height+500)+'px'
      });
    }
    
    var lw = document.createElement('div');
    lw.setAttribute('id', 'lightwindow');
    lw.innerHTML = this.options.skin.main;
    
    var body = document.getElementsByTagName('body')[0];
    body.appendChild(overlay);
    body.appendChild(lw); 
        
    if ($('lightwindow_title_bar_close_link')) {
      Event.observe('lightwindow_title_bar_close_link', 'click', this.deactivate.bindAsEventListener(this));
      $('lightwindow_title_bar_close_link').onclick = function() {return false;};
    }
      
    Event.observe($('lightwindow_previous'), 'click', this.navigateWindow.bind(this, 'previous'), false);
    $('lightwindow_previous').onclick = function() {return false;};   
    Event.observe($('lightwindow_next'), 'click', this.navigateWindow.bind(this, 'next'), false);
    $('lightwindow_next').onclick = function() {return false;};

    if (!this.options.hideGalleryTab) {
      Event.observe($('lightwindow_galleries_tab'), 'click', this._handleGalleryAnimation.bind(this, true), false);
      $('lightwindow_galleries_tab').onclick = function() {return false;};
    }
    
    // Because we use position absolute, kill the scroll Wheel on animations
    if (Prototype.Browser.IE) {
      Event.observe(document, 'mousewheel', this._stopScrolling.bindAsEventListener(this), false);
    } else {
      Event.observe(window, 'DOMMouseScroll', this._stopScrolling.bindAsEventListener(this), false);
    }
        
    Event.observe(overlay, 'click', this.deactivate.bindAsEventListener(this), false);
    overlay.onclick = function() {return false;};
  },
  //
  //  Add loading window markup
  //
  _addLoadingWindowMarkup : function() {
    $('lightwindow_contents').innerHTML += this.options.skin.loading;
  },
  //
  //  Setup the window elements
  //
  _setupWindowElements : function(link) {
    this.element = link;
    this.element.title = null ? '' : link.getAttribute('title');
    this.element.author = null ? '' : link.getAttribute('author');
    this.element.caption = null ? '' : link.getAttribute('caption');
    this.element.rel = null ? '' : link.getAttribute('rel');
    this.element.params = null ? '' : link.getAttribute('params');

    // Set the window type
    this.contentToFetch = this.element.href;
    this.windowType = this._getParameter('lightwindow_type') ? this._getParameter('lightwindow_type') : this._fileType(this.contentToFetch);  
  },
  //
  //  Clear the window contents out
  //
  _clearWindowContents : function(contents) {
    // If there is an iframe, its got to go
    if ($('lightwindow_iframe')) {
      Element.remove($('lightwindow_iframe'));
    }

    // Stop playing an object if its still around
    if ($('lightwindow_media_primary')) {
      try {
        $('lightwindow_media_primary').Stop();
      } catch(e) {}
      Element.remove($('lightwindow_media_primary'));
    }

    // Stop playing an object if its still around   
    if ($('lightwindow_media_secondary')) {
      try {
        $('lightwindow_media_secondary').Stop();
      } catch(e) {}
      Element.remove($('lightwindow_media_secondary'));
    }
    
    this.activeGallery = false;
    this._handleNavigation(this.activeGallery);
    
    if (contents) {
      // Empty the contents
      $('lightwindow_contents').innerHTML = '';
      
      // Reset the scroll bars
      $('lightwindow_contents').setStyle({
        overflow: 'hidden'
      });   
      
      if (!this.windowActive) {
        $('lightwindow_data_slide_inner').setStyle({
          display: 'none'
        });

        $('lightwindow_title_bar_title').innerHTML = '';
      }

      // Because of browser differences and to maintain flexible captions we need to reset this height at close
      $('lightwindow_data_slide').setStyle({
        height: 'auto'
      });
    }
    
    this.resizeTo.height = null;
    this.resizeTo.width = null;
  },
  //
  //  Set the status of our animation to keep things from getting clunky
  //
  _setStatus : function(status) {
    this.animating = status;
    if (status) {
      Element.show('lightwindow_loading');
    }
    if (!(/MSIE 6./i.test(navigator.userAgent))) {
      this._fixedWindow(status);
    }
  },
  //
  //  Make this window Fixed
  //
  _fixedWindow : function(status) {
    if (status) {
      if (this.windowActive) {
        this._getScroll();
        $('lightwindow').setStyle({
          position: 'absolute',
          top: parseFloat($('lightwindow').getStyle('top'))+this.pagePosition.y+'px',
          left: parseFloat($('lightwindow').getStyle('left'))+this.pagePosition.x+'px'
        });   
      } else {
        $('lightwindow').setStyle({
          position: 'absolute'
        });           
      }
    } else {
      if (this.windowActive) {
        this._getScroll();
        $('lightwindow').setStyle({
          position: 'fixed',
          top: parseFloat($('lightwindow').getStyle('top'))-this.pagePosition.y+'px',
          left: parseFloat($('lightwindow').getStyle('left'))-this.pagePosition.x+'px'
        });   
      } else {
        if ($('lightwindow_iframe')) {
          // Ideally here we would set a 50% value for top and left, but Safari rears it ugly head again and we need to do it by pixels
          this._browserDimensions();
        }
        $('lightwindow').setStyle({
          position: 'fixed',
          top: (parseFloat(this._getParameter('lightwindow_top')) ? parseFloat(this._getParameter('lightwindow_top'))+'px' : this.dimensions.viewport.height/2+'px'),
          left: (parseFloat(this._getParameter('lightwindow_left')) ? parseFloat(this._getParameter('lightwindow_left'))+'px' : this.dimensions.viewport.width/2+'px')
        });
      }
    }
  },
  //
  //  Prepare the window for IE.
  //
  _prepareIE : function(setup) {
    if (Prototype.Browser.IE) {
      var height, overflowX, overflowY;
      if (setup) { 
        var height = '100%';
      } else {
        var height = 'auto';
      }
      var body = document.getElementsByTagName('body')[0];
      var html = document.getElementsByTagName('html')[0];
      html.style.height = body.style.height = height;
    }
  },
  _stopScrolling : function(e) {
    if (this.animating) {
      if (e.preventDefault) {
        e.preventDefault();
      }
      e.returnValue = false;    
    }
  },
  //
  //  Get the scroll for the page.
  //
  _getScroll : function(){
        if(typeof(window.pageYOffset) == 'number') {
          this.pagePosition.x = window.pageXOffset;
          this.pagePosition.y = window.pageYOffset;
        } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
          this.pagePosition.x = document.body.scrollLeft;
          this.pagePosition.y = document.body.scrollTop;
    } else if(document.documentElement) {
          this.pagePosition.x = document.documentElement.scrollLeft;
          this.pagePosition.y = document.documentElement.scrollTop;
        }
  },
  //
  //  Reset the scroll.
  //
  _setScroll : function(x, y) {
    document.documentElement.scrollLeft = x; 
    document.documentElement.scrollTop = y; 
  },
  //
  //  Hide Selects from the page because of IE.
  //     We could use iframe shims instead here but why add all the extra markup for one browser when this is much easier and cleaner
  //
  _toggleTroubleElements : function(visibility, content){
    
    if (content) {
      var selects = $('lightwindow_contents').getElementsByTagName('select');
    } else {
      var selects = document.getElementsByTagName('select');
    }
    
    for(var i = 0; i < selects.length; i++) {
      selects[i].style.visibility = visibility;
    }
    
    if (!content) {
      if (this.options.hideFlash){
        var objects = document.getElementsByTagName('object');
        for (i = 0; i != objects.length; i++) {
          objects[i].style.visibility = visibility;
        }
        var embeds = document.getElementsByTagName('embed');
        for (i = 0; i != embeds.length; i++) {
          embeds[i].style.visibility = visibility;
        }
      }
      var iframes = document.getElementsByTagName('iframe');
      for (i = 0; i != iframes.length; i++) {
        iframes[i].style.visibility = visibility;
      }
    }
  },
  // 
  //  Get the actual page size
  //
  _getPageDimensions : function() {
    var xScroll, yScroll;
    if (window.innerHeight && window.scrollMaxY) {  
      xScroll = document.body.scrollWidth;
      yScroll = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight){ 
      xScroll = document.body.scrollWidth;
      yScroll = document.body.scrollHeight;
    } else { 
      xScroll = document.body.offsetWidth;
      yScroll = document.body.offsetHeight;
    }

    var windowWidth, windowHeight;
    if (self.innerHeight) { 
      windowWidth = self.innerWidth;
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { 
      windowWidth = document.documentElement.clientWidth;
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { 
      windowWidth = document.body.clientWidth;
      windowHeight = document.body.clientHeight;
    } 

    if(yScroll < windowHeight){
      this.pageDimensions.height = windowHeight;
    } else { 
      this.pageDimensions.height = yScroll;
    }

    if(xScroll < windowWidth){  
      this.pageDimensions.width = windowWidth;
    } else {
      this.pageDimensions.width = xScroll;
    }
  },
  //
  //  Display the lightWindow.
  //
  _displayLightWindow : function(display, visibility) {
    $('lightwindow_overlay').style.display = $('lightwindow').style.display = $('lightwindow_container').style.display = display; 
    $('lightwindow_overlay').style.visibility = $('lightwindow').style.visibility = $('lightwindow_container').style.visibility = visibility;
  },
  //
  //  Setup Dimensions of lightwindow.

  //
  _setupDimensions : function() {

    var originalHeight, originalWidth;
    switch (this.windowType) {
      case 'page' :
        originalHeight = this.options.dimensions.page.height;
        originalWidth = this.options.dimensions.page.width;
        break;

      case 'image' :
        originalHeight = this.options.dimensions.image.height;
        originalWidth = this.options.dimensions.image.width;
        break;
        
      case 'media' :
        originalHeight = this.options.dimensions.media.height;
        originalWidth = this.options.dimensions.media.width;
        break;
      
      case 'external' : 
        originalHeight = this.options.dimensions.external.height;
        originalWidth = this.options.dimensions.external.width;
        break;
        
      case 'inline' :
        originalHeight = this.options.dimensions.inline.height;
        originalWidth = this.options.dimensions.inline.width;
        break;
        
      default :
        originalHeight = this.options.dimensions.page.height;
        originalWidth = this.options.dimensions.page.width;
        break;
        
    }

    var offsetHeight = this._getParameter('lightwindow_top') ? parseFloat(this._getParameter('lightwindow_top'))+this.pagePosition.y : this.dimensions.viewport.height/2+this.pagePosition.y;
    var offsetWidth = this._getParameter('lightwindow_left') ? parseFloat(this._getParameter('lightwindow_left'))+this.pagePosition.x : this.dimensions.viewport.width/2+this.pagePosition.x;
    
    // So if a theme has say shadowed edges, they should be consistant and take care of in the contentOffset
    $('lightwindow').setStyle({
      top: offsetHeight+'px',
      left: offsetWidth+'px'
    });
    
    $('lightwindow_container').setStyle({
      height: originalHeight+'px',
      width: originalWidth+'px',
      left: -(originalWidth/2)+'px',
      top: -(originalHeight/2)+'px'
    });

    $('lightwindow_contents').setStyle({
      height: originalHeight+'px',
      width: originalWidth+'px'
    });
  },
  //
  //  Get the type of file.
  //
  _fileType : function(url) {
    var image = new RegExp("[^\.]\.("+this.options.fileTypes.image.join('|')+")\s*$", "i");
    if (image.test(url)) return 'image';
    if (url.indexOf('#') > -1 && (document.domain == this._getDomain(url))) return 'inline';    
    if (url.indexOf('?') > -1) url = url.substring(0, url.indexOf('?'));
    var type = 'unknown';
    var page = new RegExp("[^\.]\.("+this.options.fileTypes.page.join('|')+")\s*$", "i");
    var media = new RegExp("[^\.]\.("+this.options.fileTypes.media.join('|')+")\s*$", "i");
    if (document.domain != this._getDomain(url)) type = 'external';
      if (media.test(url)) type = 'media';
    if (type == 'external' || type == 'media') return type;
      if (page.test(url) || url.substr((url.length-1), url.length) == '/') type = 'page';
    return type;
  },
  //
  //  Get file Extension
  //
  _fileExtension : function(url) {
    if (url.indexOf('?') > -1) {
      url = url.substring(0, url.indexOf('?'));
    }
    var extenstion = '';
    for (var x = (url.length-1); x > -1; x--) {
      if (url.charAt(x) == '.') {
        return extenstion;
      }
      extenstion = url.charAt(x)+extenstion;
    }
  },
  //
  //  Monitor the keyboard while this lightwindow is up
  //
  _monitorKeyboard : function(status) {
    if (status) document.onkeydown = this._eventKeypress.bind(this); 
    else document.onkeydown = '';
  },
  //
  //  Perform keyboard actions
  //
  _eventKeypress : function(e) {
    if (e == null) {
      var keycode = event.keyCode;
    } else {
      var keycode = e.which;
    }
    
    switch (keycode) { 
      case 27: 
        this.deactivate(); 
        break;
      
      case 13:
        return;
        
      default:
        break;
    }
  
    // Gotta stop those quick fingers
    if (this.animating) {
      return false;
    }
    
    switch (String.fromCharCode(keycode).toLowerCase()) {
      case 'p':
        if (this.navigationObservers.previous) {
          this.navigateWindow('previous');
        }
        break;
        
      case 'n':
        if (this.navigationObservers.next) {
          this.navigateWindow('next');
        }
        break;
        
      default:
        break;
    }
  },
  //
  //  Get Gallery Information
  //
  _getGalleryInfo : function(rel) {
    if (!rel) return false;
    if (rel.indexOf('[') > -1) {
      return new Array(escape(rel.substring(0, rel.indexOf('['))), escape(rel.substring(rel.indexOf('[')+1, rel.indexOf(']'))));
    } else {
      return false;
    }
  },
  //
  //  Get the domain from a string.
  //
  _getDomain : function(url) {    
        var leadSlashes = url.indexOf('//');
        var domainStart = leadSlashes+2;
        var withoutResource = url.substring(domainStart, url.length);
        var nextSlash = withoutResource.indexOf('/');
        var domain = withoutResource.substring(0, nextSlash);
    if (domain.indexOf(':') > -1){
      var portColon = domain.indexOf(':');
      domain = domain.substring(0, portColon);
        }
    return domain;
    },
  //
  //  Get the value from the params attribute string.
  //
  _getParameter : function(parameter, parameters) {
    if (!this.element) return false;
    if (parameter == 'lightwindow_top' && this.element.top) {
      return unescape(this.element.top);
    } else if (parameter == 'lightwindow_left' && this.element.left) {
      return unescape(this.element.left);
    } else if (parameter == 'lightwindow_type' && this.element.type) {
      return unescape(this.element.type);
    } else if (parameter == 'lightwindow_show_images' && this.element.showImages) {
      return unescape(this.element.showImages);
    } else if (parameter == 'lightwindow_height' && this.element.height) {
      return unescape(this.element.height);
    } else if (parameter == 'lightwindow_width' && this.element.width) {
      return unescape(this.element.width);
    } else if (parameter == 'lightwindow_loading_animation' && this.element.loadingAnimation) {
      return unescape(this.element.loadingAnimation);
    } else if (parameter == 'lightwindow_iframe_embed' && this.element.iframeEmbed) {
      return unescape(this.element.iframeEmbed);
    } else if (parameter == 'lightwindow_form' && this.element.form) {
      return unescape(this.element.form);
    } else {
      if (!parameters) {
        if (this.element.params) parameters = this.element.params;
        else return;
      }
      var value;
      var parameterArray = parameters.split(',');
      var compareString = parameter+'=';
      var compareLength = compareString.length;
      for (var i = 0; i < parameterArray.length; i++) {
        if (parameterArray[i].substr(0, compareLength) == compareString) {
          var currentParameter = parameterArray[i].split('=');
          value = currentParameter[1];
          break;
        }
      }
      if (!value) return false;
      else return unescape(value);
    }
  },
  //
  //  Get the Browser Viewport Dimensions
  //
  _browserDimensions : function() {
    if (Prototype.Browser.IE) {
            this.dimensions.viewport.height = document.documentElement.clientHeight;
            this.dimensions.viewport.width = document.documentElement.clientWidth;   
        } else {
            this.dimensions.viewport.height = window.innerHeight;
            this.dimensions.viewport.width = document.width || document.body.offsetWidth;
        }
  },
  //
  //  Get the scrollbar offset, I don't like this method but there is really no other way I can find.
  //
  _getScrollerWidth : function() {
      var scrollDiv = Element.extend(document.createElement('div'));
    scrollDiv.setAttribute('id', 'lightwindow_scroll_div');
    scrollDiv.setStyle({
      position: 'absolute',
      top: '-10000px',
      left: '-10000px',
      width: '100px',
      height: '100px',
      overflow: 'hidden'
    });



      var contentDiv = Element.extend(document.createElement('div'));
    contentDiv.setAttribute('id', 'lightwindow_content_scroll_div');
    contentDiv.setStyle({
      width: '100%',
      height: '200px'
    });

      scrollDiv.appendChild(contentDiv);

    var body = document.getElementsByTagName('body')[0];
    body.appendChild(scrollDiv);

      var noScroll = $('lightwindow_content_scroll_div').offsetWidth;
      scrollDiv.style.overflow = 'auto';
      var withScroll = $('lightwindow_content_scroll_div').offsetWidth;

      Element.remove($('lightwindow_scroll_div'));

      this.scrollbarOffset = noScroll-withScroll;
  },
  

  //
  //  Add a param to an object dynamically created
  //
  _addParamToObject : function(name, value, object, id) {
    var param = document.createElement('param');
    param.setAttribute('value', value);
    param.setAttribute('name', name);
    if (id) {
      param.setAttribute('id', id);
    }
    object.appendChild(param);
    return object;
  },
  //
  //  Get the outer HTML of an object CROSS BROWSER
  //
  _outerHTML : function(object) {
    if (Prototype.Browser.IE) {
      return object.outerHTML;
    } else {
      var clone = object.cloneNode(true);
      var cloneDiv = document.createElement('div');
      cloneDiv.appendChild(clone);
      return cloneDiv.innerHTML;
    }
  },
  //
  //  Convert an object to markup
  //
  _convertToMarkup : function(object, closeTag) {
    var markup = this._outerHTML(object).replace('</'+closeTag+'>', '');
    if (Prototype.Browser.IE) {
      for (var i = 0; i < object.childNodes.length; i++){
        markup += this._outerHTML(object.childNodes[i]);
      }
      markup += '</'+closeTag+'>';
    }
    return markup;
  },
  //
  //  Depending what type of browser it is we have to append the object differently... DAMN YOU IE!!
  //
  _appendObject : function(object, closeTag, appendTo) {
    if (Prototype.Browser.IE) {
      appendTo.innerHTML += this._convertToMarkup(object, closeTag);
      
      // Fix the Eolas activate thing but only for specified media, for example doing this to a quicktime film breaks it.
      if (this.options.EOLASFix.indexOf(this._fileType(this.element.href)) > -1) {
        var objectElements = document.getElementsByTagName('object');
        for (var i = 0; i < objectElements.length; i++) {
          if (objectElements[i].getAttribute("data")) objectElements[i].removeAttribute('data');
          objectElements[i].outerHTML = objectElements[i].outerHTML;
          objectElements[i].style.visibility = "visible";
        }
      }
    } else {
      appendTo.appendChild(object); 
    } 
  },
  //
  //  Add in iframe
  //
  _appendIframe : function(scroll) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('id', 'lightwindow_iframe');
    iframe.setAttribute('name', 'lightwindow_iframe');
    iframe.setAttribute('src', 'about:blank');
    iframe.setAttribute('height', '100%');
    iframe.setAttribute('width', '100%');
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('marginwidth', '0');
    iframe.setAttribute('marginheight', '0');
    iframe.setAttribute('scrolling', scroll); 
    
    this._appendObject(iframe, 'iframe', $('lightwindow_contents'));
  },
  //
  //  Write Content to the iframe using the skin
  //
  _writeToIframe : function(content) {
    var template = this.options.skin.iframe;
    template = template.replace('{body_replace}', content); 
    if ($('lightwindow_iframe').contentWindow){
      $('lightwindow_iframe').contentWindow.document.open();
      $('lightwindow_iframe').contentWindow.document.write(template);
      $('lightwindow_iframe').contentWindow.document.close();
    } else {
      $('lightwindow_iframe').contentDocument.open();
      $('lightwindow_iframe').contentDocument.write(template);
      $('lightwindow_iframe').contentDocument.close();
    }
  },
  //
  //  Load the window Information
  //  
  _loadWindow : function() {
    switch (this.windowType) {
      case 'image' :

        var current = 0;
        var images = [];
        this.checkImage = [];
        this.resizeTo.height = this.resizeTo.width = 0;
        this.imageCount = this._getParameter('lightwindow_show_images') ? parseInt(this._getParameter('lightwindow_show_images')) : 1;

        // If there is a gallery get it
        if (gallery = this._getGalleryInfo(this.element.rel)) { 
          for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
            if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > -1) {
              break;
            }
          }
          if (this.galleries[gallery[0]][gallery[1]][current-this.imageCount]) {
            this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current-this.imageCount];
          } else {
            this.navigationObservers.previous = false;
          }
          if (this.galleries[gallery[0]][gallery[1]][current+this.imageCount]) {
            this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current+this.imageCount];
          } else {
            this.navigationObservers.next = false;
          }
          
          this.activeGallery = true;
        } else {
          this.navigationObservers.previous = false;
          this.navigationObservers.next = false;          

          this.activeGallery = false;
        }
        
        for (var i = current; i < (current+this.imageCount); i++) {
    
          if (gallery && this.galleries[gallery[0]][gallery[1]][i]) {
            this.contentToFetch = this.galleries[gallery[0]][gallery[1]][i].href;
            
            this.galleryLocation = {current: (i+1)/this.imageCount, total: (this.galleries[gallery[0]][gallery[1]].length)/this.imageCount};
                      
            if (!this.galleries[gallery[0]][gallery[1]][i+this.imageCount]) {
              $('lightwindow_next').setStyle({
                display: 'none'
              });
            } else {
              $('lightwindow_next').setStyle({
                display: 'block'
              });
              $('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i+this.imageCount].title;
            }
            
            if (!this.galleries[gallery[0]][gallery[1]][i-this.imageCount]) {
              $('lightwindow_previous').setStyle({
                display: 'none'
              });
            } else {
              $('lightwindow_previous').setStyle({
                display: 'block'
              });
              $('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i-this.imageCount].title;
            }
          }

          images[i] = document.createElement('img');
          images[i].setAttribute('id', 'lightwindow_image_'+i);
          images[i].setAttribute('border', '0');
          images[i].setAttribute('src', this.contentToFetch);
          $('lightwindow_contents').appendChild(images[i]);

          // We have to do this instead of .onload 
          this.checkImage[i] = new PeriodicalExecuter(function(i) {
            if (!(typeof $('lightwindow_image_'+i).naturalWidth != "undefined" && $('lightwindow_image_'+i).naturalWidth == 0)) {
  
              this.checkImage[i].stop();
  
              var imageHeight = $('lightwindow_image_'+i).getHeight();
              if (imageHeight > this.resizeTo.height) {
                this.resizeTo.height = imageHeight;
              }
              this.resizeTo.width += $('lightwindow_image_'+i).getWidth();
              this.imageCount--;
  
              $('lightwindow_image_'+i).setStyle({
                height: '100%'
              });
  
              if (this.imageCount == 0) {
                this._processWindow();
              }
            }
          
          }.bind(this, i), 1);      
        }


      break;
    
    case 'media' :      
    
      var current = 0;
      this.resizeTo.height = this.resizeTo.width = 0;

      // If there is a gallery get it
      if (gallery = this._getGalleryInfo(this.element.rel)) { 
        for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
          if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > -1) {
            break;
          }
        }
        
        if (this.galleries[gallery[0]][gallery[1]][current-1]) {
          this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current-1];
        } else {
          this.navigationObservers.previous = false;
        }
        if (this.galleries[gallery[0]][gallery[1]][current+1]) {
          this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current+1];
        } else {
          this.navigationObservers.next = false;
        }
    
        this.activeGallery = true;
      } else {
        this.navigationObservers.previous = false;
        this.navigationObservers.next = false;
        
        this.activeGallery = false;
      }
    

      if (gallery && this.galleries[gallery[0]][gallery[1]][current]) {
        this.contentToFetch = this.galleries[gallery[0]][gallery[1]][current].href;

        this.galleryLocation = {current: current+1, total: this.galleries[gallery[0]][gallery[1]].length};
        
        if (!this.galleries[gallery[0]][gallery[1]][current+1]) {
          $('lightwindow_next').setStyle({
            display: 'none'
          });
        } else {
          $('lightwindow_next').setStyle({
            display: 'block'
          });
          $('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current+1].title;
        }
        
        if (!this.galleries[gallery[0]][gallery[1]][current-1]) {
          $('lightwindow_previous').setStyle({
            display: 'none'
          });
        } else {
          $('lightwindow_previous').setStyle({
            display: 'block'
          });
          $('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current-1].title;
        }
      }
      
      if (this._getParameter('lightwindow_iframe_embed')) {
        this.resizeTo.height = this.dimensions.viewport.height;
        this.resizeTo.width = this.dimensions.viewport.width; 
      } else {
        this.resizeTo.height = this._getParameter('lightwindow_height');
        this.resizeTo.width = this._getParameter('lightwindow_width');        
      }
      
      this._processWindow();
      
      break;

    case 'external' :   

      this._appendIframe('auto');

      this.resizeTo.height = this.dimensions.viewport.height;
      this.resizeTo.width = this.dimensions.viewport.width;
            
      this._processWindow();

      break;
        
    case 'page' : 
      
      var newAJAX = new Ajax.Request(
        this.contentToFetch, {
          method: 'get', 
          parameters: '', 
          onComplete: function(response) {
            $('lightwindow_contents').innerHTML += response.responseText;
            this.resizeTo.height = $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
            this.resizeTo.width = $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
            this._processWindow();
          }.bind(this)
        }
      );
      
      break;
      
    case 'inline' : 
    
      var content = this.contentToFetch;
      if (content.indexOf('?') > -1) {
        content = content.substring(0, content.indexOf('?'));
      }
      content = content.substring(content.indexOf('#')+1);
      
      new Insertion.Top($('lightwindow_contents'), $(content).innerHTML);
      
      this.resizeTo.height = $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
      this.resizeTo.width = $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
      
      this._toggleTroubleElements('hidden', true);      
      this._processWindow();
      
      break;

    case 'direct' : 
        
            var content = this.contentToFetch;
            
            new Insertion.Top($('lightwindow_contents'), content);

			this.resizeTo.height = $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
            this.resizeTo.width = $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
            
            this._toggleTroubleElements('hidden', true);             
            this._processWindow();
            
            break;
      
    default : 
      throw("Page Type could not be determined, please amend this lightwindow URL "+this.contentToFetch);
      break;
    }
  },
  //
  //  Resize the Window to fit the viewport if necessary
  //
  _resizeWindowToFit : function() {
    if (this.resizeTo.height+this.dimensions.cruft.height > this.dimensions.viewport.height) {
      var heightRatio = this.resizeTo.height/this.resizeTo.width;
      this.resizeTo.height = this.dimensions.viewport.height-this.dimensions.cruft.height-(2*this.options.viewportPadding);
      // We only care about ratio's with this window type     
      if (this.windowType == 'image' || (this.windowType == 'media' && !this._getParameter('lightwindow_iframe_embed'))) {
        this.resizeTo.width = this.resizeTo.height/heightRatio;
        $('lightwindow_data_slide_inner').setStyle({
          width: this.resizeTo.width+'px'
        });     
      }
    } 
    if (this.resizeTo.width+this.dimensions.cruft.width > this.dimensions.viewport.width) {
      var widthRatio = this.resizeTo.width/this.resizeTo.height;
      this.resizeTo.width = this.dimensions.viewport.width-2*this.dimensions.cruft.width-(2*this.options.viewportPadding);
      // We only care about ratio's with this window type
      if (this.windowType == 'image' || (this.windowType == 'media' && !this._getParameter('lightwindow_iframe_embed'))) {
        this.resizeTo.height = this.resizeTo.width/widthRatio;
        $('lightwindow_data_slide_inner').setStyle({
          height: this.resizeTo.height+'px'
        });
      }
    }
      
  },
  //
  //  Set the Window to a preset size
  //
  _presetWindowSize : function() {
    if (this._getParameter('lightwindow_height')) {
      this.resizeTo.height = parseFloat(this._getParameter('lightwindow_height'));
    }
    if (this._getParameter('lightwindow_width')) {
      this.resizeTo.width = parseFloat(this._getParameter('lightwindow_width'));
    }
  },
  //
  //  Process the Window
  //
  _processWindow : function() {
    // Clean out our effects
    this.dimensions.dataEffects = [];

    // Set up the data-slide if we have caption information
    if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
      if (this.element.caption) {
        $('lightwindow_data_caption').innerHTML = this.element.caption;
        $('lightwindow_data_caption').setStyle({
          display: 'block'
        });
      } else {
        $('lightwindow_data_caption').setStyle({
          display: 'none'
        });       
      }
      if (this.element.author) {
        $('lightwindow_data_author').innerHTML = this.element.author;
        $('lightwindow_data_author_container').setStyle({
          display: 'block'
        });
      } else {
        $('lightwindow_data_author_container').setStyle({
          display: 'none'
        });       
      }
      if (this.activeGallery && this.options.showGalleryCount) {
        $('lightwindow_data_gallery_current').innerHTML = this.galleryLocation.current;
        $('lightwindow_data_gallery_total').innerHTML = this.galleryLocation.total;
        $('lightwindow_data_gallery_container').setStyle({
          display: 'block'
        });
      } else {
        $('lightwindow_data_gallery_container').setStyle({
          display: 'none'
        });       
      }

      $('lightwindow_data_slide_inner').setStyle({
        width: this.resizeTo.width+'px',
        height: 'auto',
        visibility: 'visible',
        display: 'block'
      });
      $('lightwindow_data_slide').setStyle({
        height: $('lightwindow_data_slide').getHeight()+'px',
        width: '1px',
        overflow: 'hidden',
        display: 'block'
      });
    } else {
      $('lightwindow_data_slide').setStyle({
        display: 'none',
        width: 'auto'
      });
      $('lightwindow_data_slide_inner').setStyle({
        display: 'none',
        visibility: 'hidden',
        width: this.resizeTo.width+'px',
        height: '0px'
      });
    }
        
    if (this.element.title != 'null') {   
      $('lightwindow_title_bar_title').innerHTML = this.element.title;
    } else {
      $('lightwindow_title_bar_title').innerHTML = '';
    }
    
    var originalContainerDimensions = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
    // Position the window
      $('lightwindow_container').setStyle({
      height: 'auto',
      // We need to set the width to a px not auto as opera has problems with it
      width: $('lightwindow_container').getWidth()+this.options.contentOffset.width-(this.windowActive ? this.options.contentOffset.width : 0)+'px'
    });
    var newContainerDimensions = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
    
    // We need to record the container dimension changes
    this.containerChange = {height: originalContainerDimensions.height-newContainerDimensions.height, width: originalContainerDimensions.width-newContainerDimensions.width};

    // Get out general dimensions
    this.dimensions.container = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
    this.dimensions.cruft = {height: this.dimensions.container.height-$('lightwindow_contents').getHeight()+this.options.contentOffset.height, width: this.dimensions.container.width-$('lightwindow_contents').getWidth()+this.options.contentOffset.width};
    
    // Set Sizes if we need too
    this._presetWindowSize();
    this._resizeWindowToFit(); // Even if the window is preset we still don't want it to go outside of the viewport

    if (!this.windowActive) {
      // Position the window
        $('lightwindow_container').setStyle({
        left: -(this.dimensions.container.width/2)+'px',
        top: -(this.dimensions.container.height/2)+'px'
      });
    }
      $('lightwindow_container').setStyle({
      height: this.dimensions.container.height+'px',
      width: this.dimensions.container.width+'px'
    });
    
    // We are ready, lets show this puppy off!
    this._displayLightWindow('block', 'visible');
    this._animateLightWindow();
	// process on load event
	this._onLoad();
  },
  //
  //  Fire off our animation handler
  //
  _animateLightWindow : function() {
    if (this.options.animationHandler) {
      this.options.animationHandler().bind(this);
    } else {
      this._defaultAnimationHandler();
    }
  },
  //
  //  Fire off our transition handler
  //
  _handleNavigation : function(display) {
    if (this.options.navigationHandler) {
      this.options.navigationHandler().bind(this, display);
    } else {
      this._defaultDisplayNavigation(display);
    }
  },
  //
  //  Fire off our transition handler
  //
  _handleTransition : function() {
    if (this.options.transitionHandler) {
      this.options.transitionHandler().bind(this);
    } else {
      this._defaultTransitionHandler();
    }
  },
  //
  //  Handle the finish of the window animation
  // 
  _handleFinalWindowAnimation : function(delay) {
    if (this.options.finalAnimationHandler) {
      this.options.finalAnimationHandler().bind(this, delay);
    } else {
      this._defaultfinalWindowAnimationHandler(delay);
    }   
  },
  //
  //  Handle the gallery Animation
  // 
  _handleGalleryAnimation : function(list) {
    if (this.options.galleryAnimationHandler) {
      this.options.galleryAnimationHandler().bind(this, list);
    } else {
      this._defaultGalleryAnimationHandler(list);
    }   
  },
  //
  //  Display the navigation 
  //
  _defaultDisplayNavigation : function(display) {
    if (display) {
      $('lightwindow_navigation').setStyle({
        display: 'block',
        height: $('lightwindow_contents').getHeight()+'px',
        width: '100%',
        marginTop: this.options.dimensions.titleHeight+'px'
      });     
    } else {
      $('lightwindow_navigation').setStyle({
        display: 'none',
        height: 'auto',
        width: 'auto'
      });     
    }
  },
  //
  //  This is the default animation handler for LightWindow
  //
  _defaultAnimationHandler : function() { 
    // Now that we have figures out the cruft lets make the caption go away and add its effects
    if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
      $('lightwindow_data_slide').setStyle({
        display: 'none',
        width: 'auto'
      });
      this.dimensions.dataEffects.push(
        new Effect.SlideDown('lightwindow_data_slide', {sync: true}),
        new Effect.Appear('lightwindow_data_slide', {sync: true, from: 0.0, to: 1.0})
      );
    }

    // Set up the Title if we have one
    $('lightwindow_title_bar_inner').setStyle({
      height: '0px',
      marginTop: this.options.dimensions.titleHeight+'px'
    });
    
    // We always want the title bar as well
    this.dimensions.dataEffects.push(
      new Effect.Morph('lightwindow_title_bar_inner', {sync: true, style: {height: this.options.dimensions.titleHeight+'px', marginTop: '0px'}}),
      new Effect.Appear('lightwindow_title_bar_inner', {sync: true, from: 0.0, to: 1.0})
    );    
    
    if (!this.options.hideGalleryTab) {
      this._handleGalleryAnimation(false);
      if ($('lightwindow_galleries_tab_container').getHeight() == 0) {
        this.dimensions.dataEffects.push(
          new Effect.Morph('lightwindow_galleries_tab_container', {sync: true, style: {height: '20px', marginTop: '0px'}})
        );
        $('lightwindow_galleries').setStyle({
          width: '0px'
        });
      }
    }
    
    var resized = false;
    var ratio = this.dimensions.container.width-$('lightwindow_contents').getWidth()+this.resizeTo.width+this.options.contentOffset.width;
    if (ratio != $('lightwindow_container').getWidth()) {
      new Effect.Parallel([
          new Effect.Scale('lightwindow_contents', 100*(this.resizeTo.width/$('lightwindow_contents').getWidth()), {scaleFrom: 100*($('lightwindow_contents').getWidth()/($('lightwindow_contents').getWidth()+(this.options.contentOffset.width))), sync: true,  scaleY: false, scaleContent: false}),
          new Effect.Scale('lightwindow_container', 100*(ratio/(this.dimensions.container.width)), {sync: true, scaleY: false, scaleFromCenter: true, scaleContent: false})
        ], {
          duration: this.duration, 
          delay: 0.25,
          queue: {position: 'end', scope: 'lightwindowAnimation'}
        }
      );    
    }
    
    ratio = this.dimensions.container.height-$('lightwindow_contents').getHeight()+this.resizeTo.height+this.options.contentOffset.height;
    if (ratio != $('lightwindow_container').getHeight()) {
      new Effect.Parallel([
          new Effect.Scale('lightwindow_contents', 100*(this.resizeTo.height/$('lightwindow_contents').getHeight()), {scaleFrom: 100*($('lightwindow_contents').getHeight()/($('lightwindow_contents').getHeight()+(this.options.contentOffset.height))), sync: true, scaleX: false, scaleContent: false}),
          new Effect.Scale('lightwindow_container', 100*(ratio/(this.dimensions.container.height)), {sync: true, scaleX: false, scaleFromCenter: true, scaleContent: false})
        ], {
          duration: this.duration, 
          afterFinish: function() {       
            if (this.dimensions.dataEffects.length > 0) {
              if (!this.options.hideGalleryTab) {
                $('lightwindow_galleries').setStyle({
                  width: this.resizeTo.width+'px'
                });
              }
              new Effect.Parallel(this.dimensions.dataEffects, {
                  duration: this.duration,
                  afterFinish: function() {
                    this._finishWindow();
                  }.bind(this),
                  queue: {position: 'end', scope: 'lightwindowAnimation'} 
                }
              );
            }
          }.bind(this), 
          queue: {position: 'end', scope: 'lightwindowAnimation'} 
        }
      );
      resized = true;
    }
    
    // We need to do our data effect since there was no resizing
    if (!resized && this.dimensions.dataEffects.length > 0) { 
      new Effect.Parallel(this.dimensions.dataEffects, {
          duration: this.duration,
          beforeStart: function() {
            if (!this.options.hideGalleryTab) {
              $('lightwindow_galleries').setStyle({
                width: this.resizeTo.width+'px'
              });
            }
            if (this.containerChange.height != 0 || this.containerChange.width != 0) {
              new Effect.MoveBy('lightwindow_container', this.containerChange.height, this.containerChange.width, {transition: Effect.Transitions.sinoidal});
            }
          }.bind(this),     
          afterFinish: function() {
            this._finishWindow();
          }.bind(this),
          queue: {position: 'end', scope: 'lightwindowAnimation'} 
        }
      );
    }     
    
  },
  //
  //  Finish up Window Animation
  //
  _defaultfinalWindowAnimationHandler : function(delay) {
    if (this.windowType == 'media' || this._getParameter('lightwindow_loading_animation')) {  
      // Because of major flickering with the overlay we just hide it in this case
      Element.hide('lightwindow_loading');
      this._handleNavigation(this.activeGallery);
      this._setStatus(false);
    } else {
      Effect.Fade('lightwindow_loading', {
        duration: 0.75,
        delay: 1.0, 
        afterFinish: function() {
          // Just in case we need some scroll goodness (this also avoids the swiss cheese effect)
          if (this.windowType != 'image' && this.windowType != 'media' && this.windowType != 'external') {
            $('lightwindow_contents').setStyle({
              overflow: 'auto'
            });
          }
          this._handleNavigation(this.activeGallery);
          this._defaultGalleryAnimationHandler();
          this._setStatus(false);
        }.bind(this),
        queue: {position: 'end', scope: 'lightwindowAnimation'}
      });
    }
  },
  //
  //  Handle the gallery Animation
  //
  _defaultGalleryAnimationHandler : function(list) {
    if (this.activeGallery) {
      $('lightwindow_galleries').setStyle({
        display: 'block',
        marginBottom: $('lightwindow_data_slide').getHeight()+this.options.contentOffset.height/2+'px'
      });
      $('lightwindow_navigation').setStyle({
        height: $('lightwindow_contents').getHeight()-20+'px'
      });
    } else {
      $('lightwindow_galleries').setStyle({
        display: 'none'
      }); 
      $('lightwindow_galleries_tab_container').setStyle({
        height: '0px',
        marginTop: '20px'
      });
      $('lightwindow_galleries_list').setStyle({
        height: '0px'
      });
      return false;
    }
    
    if (list) {
      if ($('lightwindow_galleries_list').getHeight() == 0) {
        var height = $('lightwindow_contents').getHeight()*0.80;
        $('lightwindow_galleries_tab_span').className = 'down';
      } else {
        var height = 0;
        $('lightwindow_galleries_tab_span').className = 'up';
      }

      new Effect.Morph('lightwindow_galleries_list', {
        duration: this.duration,
        transition: Effect.Transitions.sinoidal,
        style: {height: height+'px'},
        beforeStart: function() {
          $('lightwindow_galleries_list').setStyle({
            overflow: 'hidden'
          });         
        },
        afterFinish: function() {
          $('lightwindow_galleries_list').setStyle({
            overflow: 'auto'
          });
        },
        queue: {position: 'end', scope: 'lightwindowAnimation'}
      }); 
    }
    
    
  },
  //
  //  Default Transition Handler
  //
  _defaultTransitionHandler : function() {
    // Clean out our effects
    this.dimensions.dataEffects = [];

    // Now that we have figures out the cruft lets make the caption go away and add its effects
    if ($('lightwindow_data_slide').getStyle('display') != 'none') {
      this.dimensions.dataEffects.push(
        new Effect.SlideUp('lightwindow_data_slide', {sync: true}),
        new Effect.Fade('lightwindow_data_slide', {sync: true, from: 1.0, to: 0.0})
      );
    }
    
    if (!this.options.hideGalleryTab) {
      if ($('lightwindow_galleries').getHeight() != 0 && !this.options.hideGalleryTab) {
        this.dimensions.dataEffects.push(
          new Effect.Morph('lightwindow_galleries_tab_container', {sync: true, style: {height: '0px', marginTop: '20px'}})
        );
      }
      
      if ($('lightwindow_galleries_list').getHeight() != 0) {
        $('lightwindow_galleries_tab_span').className = 'up';
        this.dimensions.dataEffects.push(
          new Effect.Morph('lightwindow_galleries_list', {
            sync: true, 
            style: {height: '0px'},
            transition: Effect.Transitions.sinoidal,
            beforeStart: function() {
              $('lightwindow_galleries_list').setStyle({
                overflow: 'hidden'
              });         
            },
            afterFinish: function() {
              $('lightwindow_galleries_list').setStyle({
                overflow: 'auto'
              });
            }
          })
        );
      }
    }
    
    // We always want the title bar as well
    this.dimensions.dataEffects.push(
      new Effect.Morph('lightwindow_title_bar_inner', {sync: true, style: {height: '0px', marginTop: this.options.dimensions.titleHeight+'px'}}),
      new Effect.Fade('lightwindow_title_bar_inner', {sync: true, from: 1.0, to: 0.0})
    );

    new Effect.Parallel(this.dimensions.dataEffects, {
        duration: this.duration,
        afterFinish: function() {
          this._loadWindow();
        }.bind(this),
        queue: {position: 'end', scope: 'lightwindowAnimation'} 
      }
    );  
  },
  //
  //  Default Form handler for LightWindow
  //
  _defaultFormHandler : function(e) {
    var element = Event.element(e).parentNode;
    var parameterString = Form.serialize(this._getParameter('lightwindow_form', element.getAttribute('params')));
    if (this.options.formMethod == 'post') {
      var newAJAX = new Ajax.Request(element.href, { 
        method: 'post', 
        postBody: parameterString, 
        onComplete: this.openWindow.bind(this, element)
      });
    } else if (this.options.formMethod == 'get') {
      var newAJAX = new Ajax.Request(element.href, { 
        method: 'get', 
        parameters: parameterString, 
        onComplete: this.openWindow.bind(this, element)
      });
    }
  },
  // 
  //  Wrap everything up
  //
  _finishWindow : function() {
    if (this.windowType == 'external') {
      // We set the externals source here because it allows for a much smoother animation
      $('lightwindow_iframe').setAttribute('src', this.element.href);
      this._handleFinalWindowAnimation(1);  
    } else if (this.windowType == 'media') {

      var outerObject = document.createElement('object');
      outerObject.setAttribute('classid', this.options.classids[this._fileExtension(this.contentToFetch)]);
      outerObject.setAttribute('codebase', this.options.codebases[this._fileExtension(this.contentToFetch)]);
      outerObject.setAttribute('id', 'lightwindow_media_primary');
      outerObject.setAttribute('name', 'lightwindow_media_primary');
      outerObject.setAttribute('width', this.resizeTo.width);
      outerObject.setAttribute('height', this.resizeTo.height);
      outerObject = this._addParamToObject('movie', this.contentToFetch, outerObject);
      outerObject = this._addParamToObject('src', this.contentToFetch, outerObject);
      outerObject = this._addParamToObject('controller', 'true', outerObject);
      outerObject = this._addParamToObject('wmode', 'transparent', outerObject);
      outerObject = this._addParamToObject('cache', 'false', outerObject);
      outerObject = this._addParamToObject('quality', 'high', outerObject);

      if (!Prototype.Browser.IE) {
        var innerObject = document.createElement('object');
        innerObject.setAttribute('type', this.options.mimeTypes[this._fileExtension(this.contentToFetch)]);
        innerObject.setAttribute('data', this.contentToFetch);
        innerObject.setAttribute('id', 'lightwindow_media_secondary');
        innerObject.setAttribute('name', 'lightwindow_media_secondary');
        innerObject.setAttribute('width', this.resizeTo.width);
        innerObject.setAttribute('height', this.resizeTo.height);
        innerObject = this._addParamToObject('controller', 'true', innerObject);
        innerObject = this._addParamToObject('wmode', 'transparent', innerObject);
        innerObject = this._addParamToObject('cache', 'false', innerObject);
        innerObject = this._addParamToObject('quality', 'high', innerObject);
      
        outerObject.appendChild(innerObject);
      } 
      
      if (this._getParameter('lightwindow_iframe_embed')) {
        this._appendIframe('no');
        this._writeToIframe(this._convertToMarkup(outerObject, 'object'));
      } else {
        this._appendObject(outerObject, 'object', $('lightwindow_contents'));
      }

      this._handleFinalWindowAnimation(0);
    } else {
      this._handleFinalWindowAnimation(0);
    }

    // Initialize any actions
	this._setupActions();

	 $('lightwindow_title_bar').setStyle({
      width: $('lightwindow_contents').offsetWidth+'px'
	 });

	 $('lightwindow_title_bar').setStyle({
      display:'block'
	 });

	 	
  },
  
  _onLoad : function ()	{
	var scripts = $('lightwindow_contents').getElementsByTagName('script');
	for(var i=0;i<scripts.length;i++)
	{
		window.eval(scripts[i].innerHTML);
	}
	 if (window.showEmbeds) {
	  window.showEmbeds(false);
	 }
	doSIFR();
	if (Prototype.Browser.Gecko && $('login_btn'))
	{
        $('login_btn_ff').style.display = '';
        $('login_btn').style.display = 'none';
	}
  }
}

/*-----------------------------------------------------------------------------------------------*/

/* moved to onPageLoad by GB */
// Event.observe(window, 'load', lightwindowInit, false);

//
//  Set up all of our links
//
var myLightWindow = null;
function lightwindowInit() {
  //myLightWindow = new lightwindow();
  myLightWindow = new lightwindow({formHandler : singleFormCall}); // -- new
}

//
// -- update the lightwindow with the response
//
function updatePageWithResponse(lw_pointer, element, response) {
    // -- we are going to emulate the whole openWindow funky call this is also an excellent place to put in 
    //      logic to make sense of the returned text. if say you're returning a json string containing 
    //      validation results for the user-input, this is where you'd put in the code to notify the user.
    
    // The window is active
    lw_pointer.windowActive = true;
    
    // Clear out the window Contents
    lw_pointer._clearWindowContents(true);
    
    // Add back in out loading panel
    lw_pointer._addLoadingWindowMarkup();
    
    // Setup the element properties
    // -- swapped out this line: this._setupWindowElements(element);
    //    for code block below since this is really what we are overriding
    lw_pointer.element = element;
    lw_pointer.element.title = null ? '' : element.getAttribute('title');
    lw_pointer.element.author = null ? '' : element.getAttribute('author');
    lw_pointer.element.caption = null ? '' : element.getAttribute('caption');
    lw_pointer.element.rel = null ? '' : element.getAttribute('rel');
    lw_pointer.element.params = null ? '' : element.getAttribute('params');
    
    // Set the window type, these are the lines we're hacking
    lw_pointer.contentToFetch = response;
    lw_pointer.windowType = 'direct'; // -- this the actual line we want to hack
    
    lw_pointer._setStatus(true);
    lw_pointer._handleTransition();
}
//
// -- single form call
//
function singleFormCall(e) {
	var lw_pointer = myLightWindow; // -- set to your myLightWindow variable
   var element = Event.element(e);
	if (!element.getAttribute('params')) {
		element = element.parentNode;
	}

	var formelement = $(lw_pointer._getParameter('lightwindow_form', element.getAttribute('params')));
	if (!formelement) return;
	if (formelement.onsubmit) {
		formelement.onsubmit();
	} else if (formelement.readAttribute('onsubmit')) {
		eval(formelement.readAttribute('onsubmit'));
	}

	var parameterString = formelement.serialize();
	if (lw_pointer.options.formMethod == 'post') {
		  var newAJAX = new Ajax.Request(element.href, { 
            method: 'post', 
            postBody: parameterString, 
            onComplete: function(response) {
					if (response.responseText == '') {
						lw_pointer.openWindow.bind(this, element);
					} else {
						updatePageWithResponse(lw_pointer, element, response.responseText);
					}
				}
			});
		} else if (lw_pointer.options.formMethod == 'get') {
			var newAJAX = new Ajax.Request(element.href, { 
            method: 'get', 
            parameters: parameterString, 
            onComplete: function(response) {
                if (response.responseText == '') {
                    lw_pointer.openWindow.bind(this, element);
				}
                else {
                    updatePageWithResponse(lw_pointer, element, response.responseText);
				}
			}
        });
    }
}


function processOnLoad(obj) {
	obj._onLoad();
}
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/*
 * Perform a simple self-test to see if the VM is working
 */
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}
// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008

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

var Scriptaculous = {
  Version: '1.8.1',
  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
  },
  REQUIRED_PROTOTYPE: '1.6.0',
  load: function() {
    function convertVersionString(versionString){
      var r = versionString.split('.');
      return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
    }
 
    if((typeof Prototype=='undefined') || 
       (typeof Element == 'undefined') || 
       (typeof Element.Methods=='undefined') ||
       (convertVersionString(Prototype.Version) < 
        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
        Scriptaculous.REQUIRED_PROTOTYPE);
    
    $A(document.getElementsByTagName("script")).findAll( function(s) {
      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
    }).each( function(s) {
      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
      var includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
       function(include) { Scriptaculous.require(path+include+'.js') });
    });
  }
}

Scriptaculous.load();//  Prototip 2.0.4 - 05-08-2008
//  Copyright (c) 2008 Nick Stakenburg (http://www.nickstakenburg.com)
//
//  Licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License
//  http://creativecommons.org/licenses/by-nc-nd/3.0/

//  More information on this project:
//  http://www.nickstakenburg.com/projects/prototip2/

var Prototip = {
  Version: '2.0.4'
};

var Tips = {
  options: {
    images: '../images/prototip/', // image path, can be relative to this file or an absolute url
    zIndex: 6000                   // raise if required
  }
};

Prototip.Styles = {
  // The default style every other style will inherit from.
  // Used when no style is set through the options on a tooltip.
  'default': {
    border: 6,
    borderColor: '#c7c7c7',
    className: 'default',
    closeButton: false,
    hideAfter: false,
    hideOn: 'mouseleave',
    hook: false,
	//images: 'styles/creamy/',    // Example: different images. An absolute url or relative to the images url defined above.
    radius: 6,
	showOn: 'mousemove',
    stem: {
      //position: 'topLeft',       // Example: optional default stem position, this will also enable the stem
      height: 12,
      width: 15
    }
  },

  'protoblue': {
    className: 'protoblue',
    border: 6,
    borderColor: '#116497',
    radius: 6,
    stem: { height: 12, width: 15 }
  },

  'darkgrey': {
    className: 'darkgrey',
    border: 6,
    borderColor: '#363636',
    radius: 6,
    stem: { height: 12, width: 15 }
  },

  'creamy': {
    className: 'creamy',
    border: 6,
    borderColor: '#ebe4b4',
    radius: 6,
    stem: { height: 12, width: 15 }
  },

  'protogrey': {
    className: 'protogrey',
    border: 6,
    borderColor: '#606060',
    radius: 6,
    stem: { height: 12, width: 15 }
  }
};

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('O.11(V,{5F:"1.6.0.2",3R:b(){3.3D("1Y");9(/^(6v?:\\/\\/|\\/)/.6d(c.8.W)){c.W=c.8.W}10{e A=/1Q(?:-[\\w\\d.]+)?\\.4D(.*)/;c.W=(($$("4z 4w[2c]").3v(b(B){N B.2c.2a(A)})||{}).2c||"").3j(A,"")+c.8.W}9(1Y.2r.3d&&!1a.3Y.v){1a.3Y.37("v","5B:5s-5n-5g:59");1a.1e("3I:33",b(){1a.4M().4G("v\\\\:*","4E: 30(#2Z#4B);")})}c.2o();q.1e(2U,"2T",3.2T)},3D:b(A){9((4u 2U[A]=="4q")||(3.2Q(2U[A].4l)<3.2Q(3["4k"+A]))){4i("V 6l "+A+" >= "+3["4k"+A]);}},2Q:b(A){e B=A.3j(/4f.*|\\./g,"");B=6b(B+"0".66(4-B.3f));N A.5S("4f")>-1?B-1:B},46:$w("44 5K"),24:b(A){9(1Y.2r.3d){N A}A=A.2t(b(G,F){e E=O.2z(3)?3:3.k,B=F.5A;5v{e D=E.2x,C=B.2x}5j(H){N}9(V.46.2F(E.2x.1Z())){9(B!=E&&!B.56(E)){G(F)}}10{9(B!=E&&!$A(E.2M("*")).2F(B)){G(F)}}});N A},3g:b(A){N(A>0)?(-1*A):(A).4X()},2T:b(){c.3G()}});O.11(c,{1H:[],18:[],2o:b(){3.2L=3.1r},1o:(b(A){N{1l:(A?"1V":"1l"),15:(A?"1J":"15"),1V:(A?"1V":"1l"),1J:(A?"1J":"15")}})(1Y.2r.3d),3B:{1l:"1l",15:"15",1V:"1l",1J:"15"},2e:{j:"2X",2X:"j",h:"1u",1u:"h",1U:"1U",1f:"1g",1g:"1f"},3y:{p:"1f",o:"1g"},3s:b(A){N!!28[1]?3.2e[A]:A},1j:(b(B){e A=r 4o("4n ([\\\\d.]+)").4m(B);N A?(3u(A[1])<7):Y})(6r.6p),3p:(1Y.2r.6k&&!1a.6i),37:b(A){3.1H.2K(A)},1G:b(A){e B=3.1H.3v(b(C){N C.k==$(A)});9(B){B.4e();9(B.1c){B.n.1G();9(c.1j){B.1p.1G()}}3.1H=3.1H.4c(B)}A.1Q=2i},3G:b(){3.1H.3h(b(A){3.1G(A.k)}.1i(3))},2I:b(C){9(C==3.49){N}9(3.18.3f===0){3.2L=3.8.1r;3e(e B=0,A=3.1H.3f;B<A;B++){3.1H[B].n.f({1r:3.8.1r})}}C.n.f({1r:3.2L++});9(C.T){C.T.f({1r:3.2L})}3.49=C},45:b(A){3.31(A);3.18.2K(A)},31:b(A){3.18=3.18.4c(A)},42:b(){c.18.1S("U")},X:b(B,F){B=$(B),F=$(F);e K=O.11({1d:{x:0,y:0},Q:Y},28[2]||{});e D=K.1x||F.2v();D.j+=K.1d.x;D.h+=K.1d.y;e C=K.1x?[0,0]:F.3T(),A=1a.1F.2A(),G=K.1x?"20":"1b";D.j+=(-1*(C[0]-A[0]));D.h+=(-1*(C[1]-A[1]));9(K.1x){e E=[0,0];E.p=0;E.o=0}e I={k:B.21()},J={k:O.2h(D)};I[G]=K.1x?E:F.21();J[G]=O.2h(D);3e(e H 3P J){3M(K[H]){S"5p":S"5o":J[H].j+=I[H].p;19;S"5k":J[H].j+=(I[H].p/2);19;S"5i":J[H].j+=I[H].p;J[H].h+=(I[H].o/2);19;S"5h":S"5f":J[H].h+=I[H].o;19;S"5d":S"5c":J[H].j+=I[H].p;J[H].h+=I[H].o;19;S"5a":J[H].j+=(I[H].p/2);J[H].h+=I[H].o;19;S"58":J[H].h+=(I[H].o/2);19}}D.j+=-1*(J.k.j-J[G].j);D.h+=-1*(J.k.h-J[G].h);9(K.Q){B.f({j:D.j+"i",h:D.h+"i"})}N D}});c.2o();e 55=54.3J({2o:b(C,E){3.k=$(C);9(!3.k){4i("V: q 53 51, 4Y 3J a 1c.");N}c.1G(3.k);e A=(O.2s(E)||O.2z(E)),B=A?28[2]||[]:E;3.1s=A?E:2i;9(B.1T){B=O.11(O.2h(V.3q[B.1T]),B)}3.8=O.11(O.11({1m:Y,1h:0,3o:"#4L",1n:0,u:c.8.u,13:c.8.4F,1v:!(B.17&&B.17=="1W")?0.14:Y,1A:Y,1K:"1J",3C:Y,X:B.X,1d:B.X?{x:0,y:0}:{x:16,y:16},1I:(B.X&&!B.X.1x)?1k:Y,17:"2p",m:Y,1T:"2Z",1b:3.k,12:Y,1F:(B.X&&!B.X.1x)?Y:1k,p:Y},V.3q["2Z"]),B);3.1b=$(3.8.1b);3.1n=3.8.1n;3.1h=(3.1n>3.8.1h)?3.1n:3.8.1h;9(3.8.W){3.W=3.8.W.2Y("://")?3.8.W:c.W+3.8.W}10{3.W=c.W+"4C/"+(3.8.1T||"")+"/"}9(!3.W.4A("/")){3.W+="/"}9(O.2s(3.8.m)){3.8.m={Q:3.8.m}}9(3.8.m.Q){3.8.m=O.11(O.2h(V.3q[3.8.1T].m)||{},3.8.m);3.8.m.Q=[3.8.m.Q.2a(/[a-z]+/)[0].1Z(),3.8.m.Q.2a(/[A-Z][a-z]+/)[0].1Z()];3.8.m.1C=["j","2X"].2F(3.8.m.Q[0])?"1f":"1g";3.1t={1f:Y,1g:Y}}9(3.8.1m){3.8.1m.8=O.11({2V:1Y.4y},3.8.1m.8||{})}3.1o=$w("4x 44").2F(3.k.2x.1Z())?c.3B:c.1o;9(3.8.X.1x){e D=3.8.X.1q.2a(/[a-z]+/)[0].1Z();3.20=c.2e[D]+c.2e[3.8.X.1q.2a(/[A-Z][a-z]+/)[0].1Z()].2n()}3.3A=(c.3p&&3.1n);3.3z();c.37(3);3.3x();V.11(3)},3z:b(){3.n=r q("R",{u:"1Q"}).f({1r:c.8.1r});9(3.3A){3.n.U=b(){3.f("j:-3w;h:-3w;1N:2m;");N 3};3.n.P=b(){3.f("1N:18");N 3};3.n.18=b(){N(3.2S("1N")=="18"&&3u(3.2S("h").3j("i",""))>-4v)}}3.n.U();9(c.1j){3.1p=r q("4t",{u:"1p",2c:"4s:Y;",4r:0}).f({2l:"2b",1r:c.8.1r-1,4p:0})}9(3.8.1m){3.23=3.23.2t(3.2R)}3.1q=r q("R",{u:"1s"});3.12=r q("R",{u:"12"}).U();9(3.8.13||(3.8.1K.k&&3.8.1K.k=="13")){3.13=r q("R",{u:"2k"}).26(3.W+"2k.2j")}},2G:b(){9(1a.33){3.2P();3.3t=1k;N 1k}10{9(!3.3t){1a.1e("3I:33",3.2P);N Y}}},2P:b(){$(1a.2O).s(3.n);9(c.1j){$(1a.2O).s(3.1p)}9(3.8.1m){$(1a.2O).s(3.T=r q("R",{u:"6u"}).26(3.W+"T.6t").U())}e G="n";9(3.8.m.Q){3.m=r q("R",{u:"6q"}).f({o:3.8.m[3.8.m.1C=="1g"?"o":"p"]+"i"});e B=3.8.m.1C=="1f";3[G].s(3.3r=r q("R",{u:"6n 2N"}).s(3.4h=r q("R",{u:"6m 2N"})));3.m.s(3.1R=r q("R",{u:"6j"}).f({o:3.8.m[B?"p":"o"]+"i",p:3.8.m[B?"o":"p"]+"i"}));9(c.1j&&!3.8.m.Q[1].4g().2Y("6h")){3.1R.f({2l:"6f"})}G="4h"}9(3.1h){e D=3.1h,F;3[G].s(3.27=r q("6e",{u:"27"}).s(3.25=r q("3m",{u:"25 3l"}).f("o: "+D+"i").s(r q("R",{u:"2J 6c"}).s(r q("R",{u:"29"}))).s(F=r q("R",{u:"6a"}).f({o:D+"i"}).s(r q("R",{u:"4d"}).f({1y:"0 "+D+"i",o:D+"i"}))).s(r q("R",{u:"2J 65"}).s(r q("R",{u:"29"})))).s(3.2W=r q("3m",{u:"2W 3l"}).s(3.3i=r q("R",{u:"3i"}).f("2q: 0 "+D+"i"))).s(3.4b=r q("3m",{u:"4b 3l"}).f("o: "+D+"i").s(r q("R",{u:"2J 64"}).s(r q("R",{u:"29"}))).s(F.63(1k)).s(r q("R",{u:"2J 62"}).s(r q("R",{u:"29"})))));G="3i";e C=3.27.2M(".29");$w("5Z 5Y 5X 5W").3h(b(I,H){9(3.1n>0){V.48(C[H],I,{1L:3.8.3o,1h:D,1n:3.8.1n})}10{C[H].2H("47")}C[H].f({p:D+"i",o:D+"i"}).2H("29"+I.2n())}.1i(3));3.27.2M(".4d",".2W",".47").1S("f",{1L:3.8.3o})}3[G].s(3.1c=r q("R",{u:"1c "+3.8.u}).s(3.1X=r q("R",{u:"1X"}).s(3.12)));9(3.8.p){e E=3.8.p;9(O.5O(E)){E+="i"}3.1c.f("p:"+E)}9(3.m){e A={};A[3.8.m.1C=="1f"?"h":"1u"]=3.m;3.n.s(A);3.2f()}3.1c.s(3.1q);9(!3.8.1m){3.3c({12:3.8.12,1s:3.1s})}},3c:b(E){e A=3.n.2S("1N");3.n.f("o:1M;p:1M;1N:2m").P();9(3.1h){3.25.f("o:0");3.25.f("o:0")}9(E.12){3.12.P().43(E.12);3.1X.P()}10{9(!3.13){3.12.U();3.1X.U()}}9(O.2z(E.1s)){E.1s.P()}9(O.2s(E.1s)||O.2z(E.1s)){3.1q.43(E.1s)}3.1c.f({p:3.1c.3F()+"i"});3.n.f("1N:18").P();3.1c.P();e C=3.1c.21(),B={p:C.p+"i"},D=[3.n];9(c.1j){D.2K(3.1p)}9(3.13){3.12.P().s({h:3.13});3.1X.P()}9(E.12||3.13){3.1X.f("p: 34%")}B.o=2i;3.n.f({1N:A});3.1q.2H("2N");9(E.12||3.13){3.12.2H("2N")}9(3.1h){3.25.f("o:"+3.1h+"i");3.25.f("o:"+3.1h+"i");B="p: "+(C.p+2*3.1h)+"i";D.2K(3.27)}D.1S("f",B);9(3.m){3.2f();9(3.8.m.1C=="1f"){3.n.f({p:3.n.3F()+3.8.m.o+"i"})}}3.n.U()},3x:b(){3.3b=3.23.1z(3);3.41=3.U.1z(3);9(3.8.1I&&3.8.17=="2p"){3.8.17="1l"}9(3.8.17==3.8.1K){3.1P=3.40.1z(3);3.k.1e(3.8.17,3.1P)}9(3.13){3.13.1e("1l",b(E){E.26(3.W+"5J.2j")}.1i(3,3.13)).1e("15",b(E){E.26(3.W+"2k.2j")}.1i(3,3.13))}e C={k:3.1P?[]:[3.k],1b:3.1P?[]:[3.1b],1q:3.1P?[]:[3.n],13:[],2b:[]},A=3.8.1K.k;3.3a=A||(!3.8.1K?"2b":"k");3.1O=C[3.3a];9(!3.1O&&A&&O.2s(A)){3.1O=3.1q.2M(A)}e D={1V:"1l",1J:"15"};$w("P U").3h(b(H){e G=H.2n(),F=(3.8[H+"3X"].35||3.8[H+"3X"]);3[H+"3W"]=F;9(["1V","1J","1l","15"].2Y(F)){3[H+"3W"]=(3.1o[F]||F);3["35"+G]=V.24(3["35"+G])}}.1i(3));9(!3.1P){3.k.1e(3.8.17,3.3b)}9(3.1O){3.1O.1S("1e",3.5I,3.41)}9(!3.8.1I&&3.8.17=="1W"){3.2u=3.Q.1z(3);3.k.1e("2p",3.2u)}3.3V=3.U.2t(b(G,F){e E=F.5H(".2k");9(E){E.5G();F.5E();G(F)}}).1z(3);9(3.13){3.n.1e("1W",3.3V)}9(3.8.17!="1W"&&(3.3a!="k")){3.2D=V.24(b(){3.1E("P")}).1z(3);3.k.1e(3.1o.15,3.2D)}e B=[3.k,3.n];3.39=V.24(b(){c.2I(3);3.2C()}).1z(3);3.38=V.24(3.1A).1z(3);B.1S("1e",3.1o.1l,3.39).1S("1e",3.1o.15,3.38);9(3.8.1m&&3.8.17!="1W"){3.2B=V.24(3.3S).1z(3);3.k.1e(3.1o.15,3.2B)}},4e:b(){9(3.8.17==3.8.1K){3.k.1w(3.8.17,3.1P)}10{3.k.1w(3.8.17,3.3b);9(3.1O){3.1O.1S("1w")}}9(3.2u){3.k.1w("2p",3.2u)}9(3.2D){3.k.1w("15",3.2D)}3.n.1w();3.k.1w(3.1o.1l,3.39).1w(3.1o.15,3.38);9(3.2B){3.k.1w(3.1o.15,3.2B)}},2R:b(C,B){9(!3.1c){9(!3.2G()){N}}3.Q(B);9(3.2w){N}10{9(3.3Q){C(B);N}}3.2w=1k;e D={2g:{1D:22.1D(B),1B:22.1B(B)}};e A=O.2h(3.8.1m.8);A.2V=A.2V.2t(b(F,E){3.3c({12:3.8.12,1s:E.5C});3.Q(D);(b(){F(E);e G=(3.T&&3.T.18());9(3.T){3.1E("T");3.T.1G();3.T=2i}9(G){3.P()}3.3Q=1k;3.2w=2i}.1i(3)).1v(0.6)}.1i(3));3.5z=q.P.1v(3.8.1v,3.T);3.n.U();3.2w=1k;3.T.P();3.5y=(b(){r 5x.5w(3.8.1m.30,A)}.1i(3)).1v(3.8.1v);N Y},3S:b(){3.1E("T")},23:b(A){9(!3.1c){9(!3.2G()){N}}3.Q(A);9(3.n.18()){N}3.1E("P");3.5u=3.P.1i(3).1v(3.8.1v)},1E:b(A){9(3[A+"3N"]){5t(3[A+"3N"])}},P:b(){9(3.n.18()){N}9(c.1j){3.1p.P()}9(3.8.3C){c.42()}c.45(3);3.1c.P();3.n.P();9(3.m){3.m.P()}3.k.3O("1Q:5r")},1A:b(A){9(3.8.1m){9(3.T&&3.8.17!="1W"){3.T.U()}}9(!3.8.1A){N}3.2C();3.5q=3.U.1i(3).1v(3.8.1A)},2C:b(){9(3.8.1A){3.1E("1A")}},U:b(){3.1E("P");3.1E("T");9(!3.n.18()){N}3.3L()},3L:b(){9(c.1j){3.1p.U()}9(3.T){3.T.U()}3.n.U();(3.27||3.1c).P();c.31(3);3.k.3O("1Q:2m")},40:b(A){9(3.n&&3.n.18()){3.U(A)}10{3.23(A)}},2f:b(){e C=3.8.m,B=28[0]||3.1t,D=c.3s(C.Q[0],B[C.1C]),F=c.3s(C.Q[1],B[c.2e[C.1C]]),A=3.1n||0;3.1R.26(3.W+D+F+".2j");9(C.1C=="1f"){e E=(D=="j")?C.o:0;3.3r.f("j: "+E+"i;");3.1R.f({"2y":D});3.m.f({j:0,h:(F=="1u"?"34%":F=="1U"?"50%":0),5D:(F=="1u"?-1*C.p:F=="1U"?-0.5*C.p:0)+(F=="1u"?-1*A:F=="h"?A:0)+"i"})}10{3.3r.f(D=="h"?"1y: 0; 2q: "+C.o+"i 0 0 0;":"2q: 0; 1y: 0 0 "+C.o+"i 0;");3.m.f(D=="h"?"h: 0; 1u: 1M;":"h: 1M; 1u: 0;");3.1R.f({1y:0,"2y":F!="1U"?F:"2b"});9(F=="1U"){3.1R.f("1y: 0 1M;")}10{3.1R.f("1y-"+F+": "+A+"i;")}9(c.3p){9(D=="1u"){3.m.f({Q:"3U",5m:"5l",h:"1M",1u:"1M","2y":"j",p:"34%",1y:(-1*C.o)+"i 0 0 0"});3.m.1T.2l="3K"}10{3.m.f({Q:"3Z","2y":"2b",1y:0})}}}3.1t=B},Q:b(B){9(!3.1c){9(!3.2G()){N}}c.2I(3);9(c.1j){e A=3.n.21();9(!3.2E||3.2E.o!=A.o||3.2E.p!=A.p){3.1p.f({p:A.p+"i",o:A.o+"i"})}3.2E=A}9(3.8.X){e J,H;9(3.20){e K=1a.1F.2A(),C=B.2g||{};e G,I=2;3M(3.20.4g()){S"5L":S"5M":G={x:0-I,y:0-I};19;S"5N":G={x:0,y:0-I};19;S"5e":S"5P":G={x:I,y:0-I};19;S"5Q":G={x:I,y:0};19;S"5R":S"5b":G={x:I,y:I};19;S"5T":G={x:0,y:I};19;S"5U":S"5V":G={x:0-I,y:I};19;S"57":G={x:0-I,y:0};19}G.x+=3.8.1d.x;G.y+=3.8.1d.y;J=O.11({1d:G},{k:3.8.X.1q,20:3.20,1x:{h:C.1B||22.1B(B)-K.h,j:C.1D||22.1D(B)-K.j}});H=c.X(3.n,3.1b,J);9(3.8.1F){e M=3.36(H),L=M.1t;H=M.Q;H.j+=L.1g?2*V.3g(G.x-3.8.1d.x):0;H.h+=L.1g?2*V.3g(G.y-3.8.1d.y):0;9(3.m&&(3.1t.1f!=L.1f||3.1t.1g!=L.1g)){3.2f(L)}}H={j:H.j+"i",h:H.h+"i"};3.n.f(H)}10{J=O.11({1d:3.8.1d},{k:3.8.X.1q,1b:3.8.X.1b});H=c.X(3.n,3.1b,O.11({Q:1k},J));H={j:H.j+"i",h:H.h+"i"}}9(3.T){e E=c.X(3.T,3.1b,O.11({Q:1k},J))}9(c.1j){3.1p.f(H)}}10{e F=3.1b.2v(),C=B.2g||{},H={j:((3.8.1I)?F[0]:C.1D||22.1D(B))+3.8.1d.x,h:((3.8.1I)?F[1]:C.1B||22.1B(B))+3.8.1d.y};9(!3.8.1I&&3.k!==3.1b){e D=3.k.2v();H.j+=-1*(D[0]-F[0]);H.h+=-1*(D[1]-F[1])}9(!3.8.1I&&3.8.1F){e M=3.36(H),L=M.1t;H=M.Q;9(3.m&&(3.1t.1f!=L.1f||3.1t.1g!=L.1g)){3.2f(L)}}H={j:H.j+"i",h:H.h+"i"};3.n.f(H);9(3.T){3.T.f(H)}9(c.1j){3.1p.f(H)}}},36:b(C){e E={1f:Y,1g:Y},D=3.n.21(),B=1a.1F.2A(),A=1a.1F.21(),G={j:"p",h:"o"};3e(e F 3P G){9((C[F]+D[G[F]]-B[F])>A[G[F]]){C[F]=C[F]-(D[G[F]]+(2*3.8.1d[F=="j"?"x":"y"]));9(3.m){E[c.3y[G[F]]]=1k}}}N{Q:C,1t:E}}});O.11(V,{48:b(G,H){e F=28[2]||3.8,B=F.1n,E=F.1h,D=r q("60",{u:"61"+H.2n(),p:E+"i",o:E+"i"}),A={h:(H.4a(0)=="t"),j:(H.4a(1)=="l")};9(D&&D.3k&&D.3k("2d")){G.s(D);e C=D.3k("2d");C.52=F.1L;C.4Z((A.j?B:E-B),(A.h?B:E-B),B,0,67.68*2,1k);C.69();C.3H((A.j?B:0),0,E-B,E);C.3H(0,(A.h?B:0),E,E-B)}10{G.s(r q("R").f({p:E+"i",o:E+"i",1y:0,2q:0,2l:"3K",Q:"3U",4W:"2m"}).s(r q("v:4V",{4U:F.1L,4T:"4S",4R:F.1L,6g:(B/E*0.5).4Q(2)}).f({p:2*E-1+"i",o:2*E-1+"i",Q:"3Z",j:(A.j?0:(-1*E))+"i",h:(A.h?0:(-1*E))+"i"})))}}});q.4P({26:b(C,B){C=$(C);e A=O.11({3E:"h j",3n:"4O-3n",32:"4N",1L:""},28[2]||{});C.f(c.1j?{6o:"4K:4J.4I.6s(2c=\'"+B+"\'\', 32=\'"+A.32+"\')"}:{4H:A.1L+" 30("+B+") "+A.3E+" "+A.3n});N C}});V.4j={P:b(){c.2I(3);3.2C();e D={};9(3.8.X){D.2g={1D:0,1B:0}}10{e A=3.1b.2v(),C=3.1b.3T(),B=1a.1F.2A();A.j+=(-1*(C[0]-B[0]));A.h+=(-1*(C[1]-B[1]));D.2g={1D:A.j,1B:A.h}}9(3.8.1m){3.2R(D)}10{3.23(D)}3.1A()}};V.11=b(A){A.k.1Q={};O.11(A.k.1Q,{P:V.4j.P.1i(A),U:A.U.1i(A),1G:c.1G.1i(c,A.k)})};V.3R();',62,404,'|||this|||||options|if||function|Tips||var|setStyle||top|px|left|element||stem|wrapper|height|width|Element|new|insert||className|||||||||||||||||||return|Object|show|position|div|case|loader|hide|Prototip|images|hook|false||else|extend|title|closeButton||mouseout||showOn|visible|break|document|target|tooltip|offset|observe|horizontal|vertical|border|bind|fixIE|true|mouseover|ajax|radius|useEvent|iframeShim|tip|zIndex|content|stemInverse|bottom|delay|stopObserving|mouse|margin|bindAsEventListener|hideAfter|pointerY|orientation|pointerX|clearTimer|viewport|remove|tips|fixed|mouseleave|hideOn|backgroundColor|auto|visibility|hideTargets|eventToggle|prototip|stemImage|invoke|style|middle|mouseenter|click|toolbar|Prototype|toLowerCase|mouseHook|getDimensions|Event|showDelayed|capture|borderTop|setPngBackground|borderFrame|arguments|prototip_Corner|match|none|src||_inverse|positionStem|fakePointer|clone|null|png|close|display|hidden|capitalize|initialize|mousemove|padding|Browser|isString|wrap|eventPosition|cumulativeOffset|ajaxContentLoading|tagName|float|isElement|getScrollOffsets|ajaxHideEvent|cancelHideAfter|eventCheckDelay|iframeShimDimensions|member|build|addClassName|raise|prototip_CornerWrapper|push|zIndexTop|select|clearfix|body|_build|convertVersionString|ajaxShow|getStyle|unload|window|onComplete|borderMiddle|right|include|default|url|removeVisible|sizingMethod|loaded|100|event|getPositionWithinViewport|add|activityLeave|activityEnter|hideElement|eventShow|_update|IE|for|length|toggleInt|each|borderCenter|replace|getContext|borderRow|li|repeat|borderColor|WebKit419|Styles|stemWrapper|inverseStem|_isBuilding|parseFloat|find|9500px|activate|_stemTranslation|setup|fixSafari2|specialEvent|hideOthers|require|align|getWidth|removeAll|fillRect|dom|create|block|afterHide|switch|Timer|fire|in|ajaxContentLoaded|start|ajaxHide|cumulativeScrollOffset|relative|buttonEvent|Action|On|namespaces|absolute|toggle|eventHide|hideAll|update|input|addVisibile|_captureTroubleElements|prototip_Fill|createCorner|_highest|charAt|borderBottom|without|prototip_Between|deactivate|_|toUpperCase|stemBox|throw|Methods|REQUIRED_|Version|exec|MSIE|RegExp|opacity|undefined|frameBorder|javascript|iframe|typeof|9500|script|area|emptyFunction|head|endsWith|VML|styles|js|behavior|closeButtons|addRule|background|Microsoft|DXImageTransform|progid|000000|createStyleSheet|scale|no|addMethods|toFixed|strokeColor|1px|strokeWeight|fillcolor|roundrect|overflow|abs|cannot|arc||available|fillStyle|not|Class|Tip|descendantOf|LEFTMIDDLE|leftMiddle|vml|bottomMiddle|BOTTOMRIGHT|rightBottom|bottomRight|TOPRIGHT|leftBottom|com|bottomLeft|rightMiddle|catch|topMiddle|both|clear|microsoft|rightTop|topRight|hideAfterTimer|shown|schemas|clearTimeout|showTimer|try|Request|Ajax|ajaxTimer|loaderTimer|relatedTarget|urn|responseText|marginTop|stop|REQUIRED_Prototype|blur|findElement|hideAction|close_hover|textarea|LEFTTOP|TOPLEFT|TOPMIDDLE|isNumber|RIGHTTOP|RIGHTMIDDLE|RIGHTBOTTOM|indexOf|BOTTOMMIDDLE|BOTTOMLEFT|LEFTBOTTOM|br|bl|tr|tl|canvas|cornerCanvas|prototip_CornerWrapperBottomRight|cloneNode|prototip_CornerWrapperBottomLeft|prototip_CornerWrapperTopRight|times|Math|PI|fill|prototip_BetweenCorners|parseInt|prototip_CornerWrapperTopLeft|test|ul|inline|arcSize|MIDDLE|evaluate|prototip_StemImage|WebKit|requires|prototip_StemBox|prototip_StemWrapper|filter|userAgent|prototip_Stem|navigator|AlphaImageLoader|gif|prototipLoader|https'.split('|'),0,{}));var minigals = new Object();

function minigals_convert(partymode) {
	if (minigals.imggals) {
		var imggals = $$('div.minigals_imgg');
		for (var i = 0; i < imggals.length; i++) {
			if (imggals[i].converted) continue;
			var galid = imggals[i].readAttribute('uid');
			
			if (minigals.imggals['uid'+galid].items.length == 0) continue;
			
			var pos = parseInt(minigals.imggals['uid'+galid].pos);
			var html = '';
			
			html += '<img class="minigals_imgg_title" src="'+minigals.imggals['uid'+galid].titleurl+'" />';
			
			if (minigals.imggals['uid'+galid].items.length > 1) {
				html += '<div class="minigals_imgg_next"><img '+(pos < minigals.imggals['uid'+galid].items.length - 1 ? '' : 'style="display:none" ')+'src="/fileadmin/sitetemplates/i/image_next'+(partymode ? '_p' : '')+'.gif" id="minigals_imgg_next'+galid+'" onclick="minigals_imgg_go('+galid+', 1);return false;" /></div>';
				html += '<div class="minigals_imgg_prev"><img '+(pos > 0 ? '' : 'style="display: none" ')+'src="/fileadmin/sitetemplates/i/image_prev'+(partymode ? '_p' : '')+'.gif" id="minigals_imgg_prev'+galid+'" onclick="minigals_imgg_go('+galid+', -1);return false;" /></div>';
				html += '<div class="minigals_imgg_count"><span id="minigals_imgg_count'+galid+'">'+ (pos + 1) + '</span> / ' + (minigals.imggals['uid'+galid].items.length) + '</div>';
			}

			html += '<div class="minigals_imgg_img_cont">';
			html += '<img id="minigals_imgg_img'+galid+'" class="minigals_imgg_img" src="'+minigals.imggals['uid'+galid].items[pos].thumb+'" title="'+minigals.imggals['uid'+galid].items[pos].title+'" alt="'+minigals.imggals['uid'+galid].items[pos].title+'" style="width:'+minigals.imggals['uid'+galid].items[pos].width+'px" />';
			html += '</div>';
	
			if (minigals.imggals['uid'+galid].items.length > 1) {
				html += '<div class="minigals_imgg_img_title" id="minigals_imgg_img_title'+galid+'">'+minigals.imggals['uid'+galid].items[pos].title+'</div>';
				html += '<div class="minigals_imgg_img_desc" id="minigals_imgg_img_desc'+galid+'">'+minigals.imggals['uid'+galid].items[pos].desc+'</div>';
				html += '<div class="cbfs0"></div>';
			}

			imggals[i].setStyle({'display' : 'block'});
			imggals[i].update(html);	
			imggals[i].converted = true;
		}
	}

	if (minigals.vidgals) {
		var vidgals = $$('div.minigals_vidg');
		for (var i = 0; i < vidgals.length; i++) {
			if (vidgals[i].converted) continue;
			var galid = vidgals[i].readAttribute('uid');

			if (minigals.vidgals['uid'+galid].items.length == 0) continue;

			var pos = parseInt(minigals.vidgals['uid'+galid].pos);
			var html = '';
			
			html += '<div class="minigals_vidg_vid" id="minigals_vidg'+galid+'"></div>';
			
			if (minigals.vidgals['uid'+galid].items.length > 1) {
				html += '<div class="minigals_vidg_next"><img '+(pos < minigals.vidgals['uid'+galid].items.length - 1 ? '' : 'style="display:none" ')+'src="/fileadmin/sitetemplates/i/image_next'+(partymode ? '_p' : '')+'.gif" id="minigals_vidg_next'+galid+'" onclick="minigals_vidg_go('+galid+', 1);return false;" /></div>';
				html += '<div class="minigals_vidg_prev"><img '+(pos > 0 ? '' : 'style="display: none" ')+'src="/fileadmin/sitetemplates/i/image_prev'+(partymode ? '_p' : '')+'.gif" id="minigals_vidg_prev'+galid+'" onclick="minigals_vidg_go('+galid+', -1);return false;" /></div>';
				html += '<div class="minigals_vidg_count"><span id="mingals_vidg_count'+galid+'">' + (pos + 1) + '</span> / '+ minigals.vidgals['uid'+galid].items.length + '</div>';
				
				html += '<div class="minigals_vidg_vid_title" id="minigals_vidg_vid_title'+galid+'">'+minigals.vidgals['uid'+galid].items[pos].title+'</div>';
				html += '<div class="minigals_vidg_vid_desc" id="minigals_vidg_vid_desc'+galid+'">'+minigals.vidgals['uid'+galid].items[pos].desc+'</div>';
				html += '<div class="cbfs0"></div>';
			}

			vidgals[i].setStyle({'display' : 'block'});

			vidgals[i].update(html);
		
			vidgals[i].so = new SWFObject("/fileadmin/swf/mediaplayer.swf", minigals.vidgals['uid'+galid].items[pos].title, 450, 330, 7);
			vidgals[i].so.addParam("allowfullscreen","true");
			vidgals[i].so.addVariable("width","450");
			vidgals[i].so.addVariable("height","330");
			vidgals[i].so.addVariable("file",minigals.vidgals['uid'+galid].items[pos].file);
			vidgals[i].so.addVariable("image",minigals.vidgals['uid'+galid].items[pos].thumb);
			vidgals[i].so.write('minigals_vidg'+galid);
			vidgals[i].converted = true;
		}

	}
}

function minigals_imgg_go (uid, dir) {
	minigals.imggals['uid'+uid].pos += dir;
	$('minigals_imgg_img'+uid).writeAttribute('src', minigals.imggals['uid'+uid].items[minigals.imggals['uid'+uid].pos].thumb);
	$('minigals_imgg_next'+uid).setStyle({'display' : minigals.imggals['uid'+uid].pos < (minigals.imggals['uid'+uid].items.length - 1) ? 'inline' : 'none' });
	$('minigals_imgg_prev'+uid).setStyle({'display' : minigals.imggals['uid'+uid].pos > 0 ? 'inline' : 'none' });
	$('minigals_imgg_img'+uid).setStyle({'width': minigals.imggals['uid'+uid].items[minigals.imggals['uid'+uid].pos].width + 'px'});
	$('minigals_imgg_img_title'+uid).update(minigals.imggals['uid'+uid].items[minigals.imggals['uid'+uid].pos].title);
	$('minigals_imgg_img_desc'+uid).update(minigals.imggals['uid'+uid].items[minigals.imggals['uid'+uid].pos].desc);

	$('minigals_imgg_count'+uid).update(minigals.imggals['uid'+uid].pos + 1);
}

function minigals_vidg_go (uid, dir) {
	minigals.vidgals['uid'+uid].pos += dir;
	var el = $$('div.minigals_vidg[uid=\''+uid+'\']')[0];
	
	el.so.addVariable('file', minigals.vidgals['uid'+uid].items[minigals.vidgals['uid'+uid].pos].file);
	el.so.addVariable('image', minigals.vidgals['uid'+uid].items[minigals.vidgals['uid'+uid].pos].thumb);
	el.so.write('minigals_vidg'+uid);

	$('minigals_vidg_next'+uid).setStyle({'display' : minigals.vidgals['uid'+uid].pos < (minigals.vidgals['uid'+uid].items.length - 1) ? 'inline' : 'none' });
	$('minigals_vidg_prev'+uid).setStyle({'display' : minigals.vidgals['uid'+uid].pos > 0 ? 'inline' : 'none' });
	$('minigals_vidg_vid_title'+uid).update(minigals.vidgals['uid'+uid].items[minigals.vidgals['uid'+uid].pos].title);
	$('minigals_vidg_vid_desc'+uid).update(minigals.vidgals['uid'+uid].items[minigals.vidgals['uid'+uid].pos].desc);

	$('minigals_vidg_count'+uid).update(minigals.vidgals['uid'+uid].pos + 1);
}
/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;function RBTabber(conf) {
	this.conf = {
		tabContainers: (typeof(conf.tabContainers) == 'string' ? $$(conf.tabContainers) : conf.tabContainers),
		itemSelector: conf.itemSelector,
		itemsPerPage: conf.itemsPerPage,
		css: (conf.css ? conf.css : {}),
		images: (conf.images ? conf.images : {})
	};

	if (!this.conf.tabContainers || this.conf.tabContainers.length == 0) return;

	this.tabberMenue = { linknames:[], links:[] };
	
	this.conf.tabContainers.each((function(element) { 
		element.setStyle({display : 'none' }); 
		element.items = element.select(this.conf.itemSelector); 
		element.pageAt = 0; 
		element.conf = this.conf; 
		this.tabberMenue.linknames.push(element.readAttribute('title'));
		if (element.items && element.items.length > this.conf.itemsPerPage) {
			element.nav = { 
				container: (new Element('div')).addClassName('rbtabber_nav'),
				next: (new Element('a'))
					.writeAttribute('href', '#')
					.writeAttribute('onclick', 'blur(this);')
					.observe('click', (function(e) { e.preventDefault(); this.goPage(1); }).bindAsEventListener(this))
					.addClassName('rbtabber_nav_next'),
				prev: (new Element('a'))
					.setStyle({ 'display' : 'none' })
					.writeAttribute('href', '#')
					.writeAttribute('onclick', 'blur(this);')
					.observe('click', (function(e) { e.preventDefault(); this.goPage(-1); }).bindAsEventListener(this))
					.addClassName('rbtabber_nav_prev')
			}

			if (this.conf.images.prev) {
				element.nav.prev.insert((new Element('img')).writeAttribute('src', this.conf.images.prev));
			} else {
				element.nav.prev.update('zurück');
			}

			if (this.conf.images.next) {
				element.nav.next.insert((new Element('img')).writeAttribute('src', this.conf.images.next));
			} else {
				element.nav.next.update('weiter');
			}

			element.insert(element.nav.container.insert(element.nav.prev).insert(element.nav.next));
			
			for (var i = this.conf.itemsPerPage; i < element.items.length; i++) {
				element.items[i].setStyle({ 'display' : 'none' });	
			}
		}
	}).bind(this));
	
	this.tabberMenue.element = (new Element('div')).addClassName('rbtabber_menue');
	if (this.conf.css.menue) this.tabberMenue.element.setStyle(this.conf.css.menue);

	var link = null;

	for (var i = 0; i < this.tabberMenue.linknames.length; i++) {
		link = (new Element('a'))
			.writeAttribute('href', '#')
			.writeAttribute('onclick', 'blur(this);')
			.observe('click', (function(e, tabnumber){ 
				e.preventDefault(); 
				this.switchTo(tabnumber);  
			}).bindAsEventListener(this, i))
			.addClassName('rbtabber_tab')
			.update(this.tabberMenue.linknames[i]);
		this.tabberMenue.links.push(link);
		this.tabberMenue.element.insert(link);
	}

	this.conf.tabContainers[0].insert({ before: this.tabberMenue.element });

	this.switchTo(0);
}

RBTabber.prototype.switchTo = function(tabnumber) {
	if (typeof(this.tab)!='undefined') {
		this.conf.tabContainers[this.tab].setStyle({ display: 'none' });
		this.tabberMenue.links[this.tab].removeClassName('rbtabber_tab_active');	
	}

	this.tab = tabnumber;
	this.conf.tabContainers[tabnumber].setStyle({ display: '' });
	this.tabberMenue.links[tabnumber].addClassName('rbtabber_tab_active');
}

RBTabber.prototype.goPage = function(c) {
	
	for (var i = this.conf.tabContainers[this.tab].pageAt * this.conf.itemsPerPage; i < (this.conf.tabContainers[this.tab].pageAt + 1) * this.conf.itemsPerPage && i < this.conf.tabContainers[this.tab].items.length; i++) {
		this.conf.tabContainers[this.tab].items[i].setStyle({ 'display' : 'none' });
	}

	this.conf.tabContainers[this.tab].pageAt += c;

	for (var i = this.conf.tabContainers[this.tab].pageAt * this.conf.itemsPerPage; i < (this.conf.tabContainers[this.tab].pageAt + 1) * this.conf.itemsPerPage && i < this.conf.tabContainers[this.tab].items.length; i++) {
		this.conf.tabContainers[this.tab].items[i].setStyle({ 'display' : '' });
	}

	this.conf.tabContainers[this.tab].nav.next.setStyle({ 'display' : ((Math.ceil(this.conf.tabContainers[this.tab].items.length / this.conf.itemsPerPage) - 1) > this.conf.tabContainers[this.tab].pageAt ? '' : 'none') });
	this.conf.tabContainers[this.tab].nav.prev.setStyle({ 'display' : (this.conf.tabContainers[this.tab].pageAt > 0 ? '' : 'none') });
}

function mplayerPopup() {
	var w = 480;
	var h = 300;
	var tmp = window.open("http://redbullmusicacademyradio.com/fileadmin/frontpage_swf/player.html", "RBMAFenster","width="+w+",height="+h+",toolbar=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no");
/*	new Ajax.Request('/fileadmin/kitzplayer_offline.html', {
		method:'get',
		onSuccess: function(transport) {
			var response = transport.responseText
			tmp.document.write(response);
			tmp.document.close();
		}
	});
*/	return false;
}

