

/*  Prototype JavaScript framework, version 1.6.0 *  (c) 2005-2007 Sam Stephenson * *  Prototype is freely distributable under the terms of an MIT-style license. *  For details, see the Prototype web site: http://www.prototypejs.org/ * *--------------------------------------------------------------------------*/var Prototype = {  Version: '1.6.0',  Browser: {    IE:     !!(window.attachEvent && !window.opera),    Opera:  !!window.opera,    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)  },  BrowserFeatures: {    XPath: !!document.evaluate,    ElementExtensions: !!window.HTMLElement,    SpecificElementExtensions:      document.createElement('div').__proto__ &&      document.createElement('div').__proto__ !==        document.createElement('form').__proto__  },  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,  emptyFunction: function() { },  K: function(x) { return x }};if (Prototype.Browser.MobileSafari)  Prototype.BrowserFeatures.SpecificElementExtensions = false;if (Prototype.Browser.WebKit)  Prototype.BrowserFeatures.XPath = false;/* Based on Alex Arnell's inheritance implementation. */var Class = {  create: function() {    var parent = null, properties = $A(arguments);    if (Object.isFunction(properties[0]))      parent = properties.shift();    function klass() {      this.initialize.apply(this, arguments);    }    Object.extend(klass, Class.Methods);    klass.superclass = parent;    klass.subclasses = [];    if (parent) {      var subclass = function() { };      subclass.prototype = parent.prototype;      klass.prototype = new subclass;      parent.subclasses.push(klass);    }    for (var i = 0; i < properties.length; i++)      klass.addMethods(properties[i]);    if (!klass.prototype.initialize)      klass.prototype.initialize = Prototype.emptyFunction;    klass.prototype.constructor = klass;    return klass;  }};Class.Methods = {  addMethods: function(source) {    var ancestor   = this.superclass && this.superclass.prototype;    var properties = Object.keys(source);    if (!Object.keys({ toString: true }).length)      properties.push("toString", "valueOf");    for (var i = 0, length = properties.length; i < length; i++) {      var property = properties[i], value = source[property];      if (ancestor && Object.isFunction(value) &&          value.argumentNames().first() == "$super") {        var method = value, value = Object.extend((function(m) {          return function() { return ancestor[m].apply(this, arguments) };        })(property).wrap(method), {          valueOf:  function() { return method },          toString: function() { return method.toString() }        });      }      this.prototype[property] = value;    }    return this;  }};var Abstract = { };Object.extend = function(destination, source) {  for (var property in source)    destination[property] = source[property];  return destination;};Object.extend(Object, {  inspect: function(object) {    try {      if (object === undefined) return 'undefined';      if (object === null) return 'null';      return object.inspect ? object.inspect() : object.toString();    } catch (e) {      if (e instanceof RangeError) return '...';      throw e;    }  },  toJSON: function(object) {    var type = typeof object;    switch (type) {      case 'undefined':      case 'function':      case 'unknown': return;      case 'boolean': return object.toString();    }    if (object === null) return 'null';    if (object.toJSON) return object.toJSON();    if (Object.isElement(object)) return;    var results = [];    for (var property in object) {      var value = Object.toJSON(object[property]);      if (value !== undefined)        results.push(property.toJSON() + ': ' + value);    }    return '{' + results.join(', ') + '}';  },  toQueryString: function(object) {    return $H(object).toQueryString();  },  toHTML: function(object) {    return object && object.toHTML ? object.toHTML() : String.interpret(object);  },  keys: function(object) {    var keys = [];    for (var property in object)      keys.push(property);    return keys;  },  values: function(object) {    var values = [];    for (var property in object)      values.push(object[property]);    return values;  },  clone: function(object) {    return Object.extend({ }, object);  },  isElement: function(object) {    return object && object.nodeType == 1;  },  isArray: function(object) {    return object && object.constructor === Array;  },  isHash: function(object) {    return object instanceof Hash;  },  isFunction: function(object) {    return typeof object == "function";  },  isString: function(object) {    return typeof object == "string";  },  isNumber: function(object) {    return typeof object == "number";  },  isUndefined: function(object) {    return typeof object == "undefined";  }});Object.extend(Function.prototype, {  argumentNames: function() {    var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");    return names.length == 1 && !names[0] ? [] : names;  },  bind: function() {    if (arguments.length < 2 && arguments[0] === undefined) return this;    var __method = this, args = $A(arguments), object = args.shift();    return function() {      return __method.apply(object, args.concat($A(arguments)));    }  },  bindAsEventListener: function() {    var __method = this, args = $A(arguments), object = args.shift();    return function(event) {      return __method.apply(object, [event || window.event].concat(args));    }  },  curry: function() {    if (!arguments.length) return this;    var __method = this, args = $A(arguments);    return function() {      return __method.apply(this, args.concat($A(arguments)));    }  },  delay: function() {    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;    return window.setTimeout(function() {      return __method.apply(__method, args);    }, timeout);  },  wrap: function(wrapper) {    var __method = this;    return function() {      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));    }  },  methodize: function() {    if (this._methodized) return this._methodized;    var __method = this;    return this._methodized = function() {      return __method.apply(null, [this].concat($A(arguments)));    };  }});Function.prototype.defer = Function.prototype.delay.curry(0.01);Date.prototype.toJSON = function() {  return '"' + this.getUTCFullYear() + '-' +    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +    this.getUTCDate().toPaddedString(2) + 'T' +    this.getUTCHours().toPaddedString(2) + ':' +    this.getUTCMinutes().toPaddedString(2) + ':' +    this.getUTCSeconds().toPaddedString(2) + 'Z"';};var Try = {  these: function() {    var returnValue;    for (var i = 0, length = arguments.length; i < length; i++) {      var lambda = arguments[i];      try {        returnValue = lambda();        break;      } catch (e) { }    }    return returnValue;  }};RegExp.prototype.match = RegExp.prototype.test;RegExp.escape = function(str) {  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');};/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create({  initialize: function(callback, frequency) {    this.callback = callback;    this.frequency = frequency;    this.currentlyExecuting = false;    this.registerCallback();  },  registerCallback: function() {    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);  },  execute: function() {    this.callback(this);  },  stop: function() {    if (!this.timer) return;    clearInterval(this.timer);    this.timer = null;  },  onTimerEvent: function() {    if (!this.currentlyExecuting) {      try {        this.currentlyExecuting = true;        this.execute();      } finally {        this.currentlyExecuting = false;      }    }  }});Object.extend(String, {  interpret: function(value) {    return value == null ? '' : String(value);  },  specialChar: {    '\b': '\\b',    '\t': '\\t',    '\n': '\\n',    '\f': '\\f',    '\r': '\\r',    '\\': '\\\\'  }});Object.extend(String.prototype, {  gsub: function(pattern, replacement) {    var result = '', source = this, match;    replacement = arguments.callee.prepareReplacement(replacement);    while (source.length > 0) {      if (match = source.match(pattern)) {        result += source.slice(0, match.index);        result += String.interpret(replacement(match));        source  = source.slice(match.index + match[0].length);      } else {        result += source, source = '';      }    }    return result;  },  sub: function(pattern, replacement, count) {    replacement = this.gsub.prepareReplacement(replacement);    count = count === undefined ? 1 : count;    return this.gsub(pattern, function(match) {      if (--count < 0) return match[0];      return replacement(match);    });  },  scan: function(pattern, iterator) {    this.gsub(pattern, iterator);    return String(this);  },  truncate: function(length, truncation) {    length = length || 30;    truncation = truncation === undefined ? '...' : truncation;    return this.length > length ?      this.slice(0, length - truncation.length) + truncation : String(this);  },  strip: function() {    return this.replace(/^\s+/, '').replace(/\s+$/, '');  },  stripTags: function() {    return this.replace(/<\/?[^>]+>/gi, '');  },  stripScripts: function() {    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');  },  extractScripts: function() {    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');    return (this.match(matchAll) || []).map(function(scriptTag) {      return (scriptTag.match(matchOne) || ['', ''])[1];    });  },  evalScripts: function() {    return this.extractScripts().map(function(script) { return eval(script) });  },  escapeHTML: function() {    var self = arguments.callee;    self.text.data = this;    return self.div.innerHTML;  },  unescapeHTML: function() {    var div = new Element('div');    div.innerHTML = this.stripTags();    return div.childNodes[0] ? (div.childNodes.length > 1 ?      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :      div.childNodes[0].nodeValue) : '';  },  toQueryParams: function(separator) {    var match = this.strip().match(/([^?#]*)(#.*)?$/);    if (!match) return { };    return match[1].split(separator || '&').inject({ }, function(hash, pair) {      if ((pair = pair.split('='))[0]) {        var key = decodeURIComponent(pair.shift());        var value = pair.length > 1 ? pair.join('=') : pair[0];        if (value != undefined) value = decodeURIComponent(value);        if (key in hash) {          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];          hash[key].push(value);        }        else hash[key] = value;      }      return hash;    });  },  toArray: function() {    return this.split('');  },  succ: function() {    return this.slice(0, this.length - 1) +      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);  },  times: function(count) {    return count < 1 ? '' : new Array(count + 1).join(this);  },  camelize: function() {    var parts = this.split('-'), len = parts.length;    if (len == 1) return parts[0];    var camelized = this.charAt(0) == '-'      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)      : parts[0];    for (var i = 1; i < len; i++)      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);    return camelized;  },  capitalize: function() {    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();  },  underscore: function() {    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();  },  dasherize: function() {    return this.gsub(/_/,'-');  },  inspect: function(useDoubleQuotes) {    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {      var character = String.specialChar[match[0]];      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);    });    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';    return "'" + escapedString.replace(/'/g, '\\\'') + "'";  },  toJSON: function() {    return this.inspect(true);  },  unfilterJSON: function(filter) {    return this.sub(filter || Prototype.JSONFilter, '#{1}');  },  isJSON: function() {    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);  },  evalJSON: function(sanitize) {    var json = this.unfilterJSON();    try {      if (!sanitize || json.isJSON()) return eval('(' + json + ')');    } catch (e) { }    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());  },  include: function(pattern) {    return this.indexOf(pattern) > -1;  },  startsWith: function(pattern) {    return this.indexOf(pattern) === 0;  },  endsWith: function(pattern) {    var d = this.length - pattern.length;    return d >= 0 && this.lastIndexOf(pattern) === d;  },  empty: function() {    return this == '';  },  blank: function() {    return /^\s*$/.test(this);  },  interpolate: function(object, pattern) {    return new Template(this, pattern).evaluate(object);  }});if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {  escapeHTML: function() {    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');  },  unescapeHTML: function() {    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');  }});String.prototype.gsub.prepareReplacement = function(replacement) {  if (Object.isFunction(replacement)) return replacement;  var template = new Template(replacement);  return function(match) { return template.evaluate(match) };};String.prototype.parseQuery = String.prototype.toQueryParams;Object.extend(String.prototype.escapeHTML, {  div:  document.createElement('div'),  text: document.createTextNode('')});with (String.prototype.escapeHTML) div.appendChild(text);var Template = Class.create({  initialize: function(template, pattern) {    this.template = template.toString();    this.pattern = pattern || Template.Pattern;  },  evaluate: function(object) {    if (Object.isFunction(object.toTemplateReplacements))      object = object.toTemplateReplacements();    return this.template.gsub(this.pattern, function(match) {      if (object == null) return '';      var before = match[1] || '';      if (before == '\\') return match[2];      var ctx = object, expr = match[3];      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);      if (match == null) return before;      while (match != null) {        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];        ctx = ctx[comp];        if (null == ctx || '' == match[3]) break;        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);        match = pattern.exec(expr);      }      return before + String.interpret(ctx);    }.bind(this));  }});Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;var $break = { };var Enumerable = {  each: function(iterator, context) {    var index = 0;    iterator = iterator.bind(context);    try {      this._each(function(value) {        iterator(value, index++);      });    } catch (e) {      if (e != $break) throw e;    }    return this;  },  eachSlice: function(number, iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var index = -number, slices = [], array = this.toArray();    while ((index += number) < array.length)      slices.push(array.slice(index, index+number));    return slices.collect(iterator, context);  },  all: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var result = true;    this.each(function(value, index) {      result = result && !!iterator(value, index);      if (!result) throw $break;    });    return result;  },  any: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var result = false;    this.each(function(value, index) {      if (result = !!iterator(value, index))        throw $break;    });    return result;  },  collect: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var results = [];    this.each(function(value, index) {      results.push(iterator(value, index));    });    return results;  },  detect: function(iterator, context) {    iterator = iterator.bind(context);    var result;    this.each(function(value, index) {      if (iterator(value, index)) {        result = value;        throw $break;      }    });    return result;  },  findAll: function(iterator, context) {    iterator = iterator.bind(context);    var results = [];    this.each(function(value, index) {      if (iterator(value, index))        results.push(value);    });    return results;  },  grep: function(filter, iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var results = [];    if (Object.isString(filter))      filter = new RegExp(filter);    this.each(function(value, index) {      if (filter.match(value))        results.push(iterator(value, index));    });    return results;  },  include: function(object) {    if (Object.isFunction(this.indexOf))      if (this.indexOf(object) != -1) return true;    var found = false;    this.each(function(value) {      if (value == object) {        found = true;        throw $break;      }    });    return found;  },  inGroupsOf: function(number, fillWith) {    fillWith = fillWith === undefined ? null : fillWith;    return this.eachSlice(number, function(slice) {      while(slice.length < number) slice.push(fillWith);      return slice;    });  },  inject: function(memo, iterator, context) {    iterator = iterator.bind(context);    this.each(function(value, index) {      memo = iterator(memo, value, index);    });    return memo;  },  invoke: function(method) {    var args = $A(arguments).slice(1);    return this.map(function(value) {      return value[method].apply(value, args);    });  },  max: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var result;    this.each(function(value, index) {      value = iterator(value, index);      if (result == undefined || value >= result)        result = value;    });    return result;  },  min: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var result;    this.each(function(value, index) {      value = iterator(value, index);      if (result == undefined || value < result)        result = value;    });    return result;  },  partition: function(iterator, context) {    iterator = iterator ? iterator.bind(context) : Prototype.K;    var trues = [], falses = [];    this.each(function(value, index) {      (iterator(value, index) ?        trues : falses).push(value);    });    return [trues, falses];  },  pluck: function(property) {    var results = [];    this.each(function(value) {      results.push(value[property]);    });    return results;  },  reject: function(iterator, context) {    iterator = iterator.bind(context);    var results = [];    this.each(function(value, index) {      if (!iterator(value, index))        results.push(value);    });    return results;  },  sortBy: function(iterator, context) {    iterator = iterator.bind(context);    return this.map(function(value, index) {      return {value: value, criteria: iterator(value, index)};    }).sort(function(left, right) {      var a = left.criteria, b = right.criteria;      return a < b ? -1 : a > b ? 1 : 0;    }).pluck('value');  },  toArray: function() {    return this.map();  },  zip: function() {    var iterator = Prototype.K, args = $A(arguments);    if (Object.isFunction(args.last()))      iterator = args.pop();    var collections = [this].concat(args).map($A);    return this.map(function(value, index) {      return iterator(collections.pluck(index));    });  },  size: function() {    return this.toArray().length;  },  inspect: function() {    return '#<Enumerable:' + this.toArray().inspect() + '>';  }};Object.extend(Enumerable, {  map:     Enumerable.collect,  find:    Enumerable.detect,  select:  Enumerable.findAll,  filter:  Enumerable.findAll,  member:  Enumerable.include,  entries: Enumerable.toArray,  every:   Enumerable.all,  some:    Enumerable.any});function $A(iterable) {  if (!iterable) return [];  if (iterable.toArray) return iterable.toArray();  var length = iterable.length, results = new Array(length);  while (length--) results[length] = iterable[length];  return results;}if (Prototype.Browser.WebKit) {  function $A(iterable) {    if (!iterable) return [];    if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&        iterable.toArray) return iterable.toArray();    var length = iterable.length, results = new Array(length);    while (length--) results[length] = iterable[length];    return results;  }}Array.from = $A;Object.extend(Array.prototype, Enumerable);if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, {  _each: function(iterator) {    for (var i = 0, length = this.length; i < length; i++)      iterator(this[i]);  },  clear: function() {    this.length = 0;    return this;  },  first: function() {    return this[0];  },  last: function() {    return this[this.length - 1];  },  compact: function() {    return this.select(function(value) {      return value != null;    });  },  flatten: function() {    return this.inject([], function(array, value) {      return array.concat(Object.isArray(value) ?        value.flatten() : [value]);    });  },  without: function() {    var values = $A(arguments);    return this.select(function(value) {      return !values.include(value);    });  },  reverse: function(inline) {    return (inline !== false ? this : this.toArray())._reverse();  },  reduce: function() {    return this.length > 1 ? this : this[0];  },  uniq: function(sorted) {    return this.inject([], function(array, value, index) {      if (0 == index || (sorted ? array.last() != value : !array.include(value)))        array.push(value);      return array;    });  },  intersect: function(array) {    return this.uniq().findAll(function(item) {      return array.detect(function(value) { return item === value });    });  },  clone: function() {    return [].concat(this);  },  size: function() {    return this.length;  },  inspect: function() {    return '[' + this.map(Object.inspect).join(', ') + ']';  },  toJSON: function() {    var results = [];    this.each(function(object) {      var value = Object.toJSON(object);      if (value !== undefined) results.push(value);    });    return '[' + results.join(', ') + ']';  }});// use native browser JS 1.6 implementation if availableif (Object.isFunction(Array.prototype.forEach))  Array.prototype._each = Array.prototype.forEach;if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {  i || (i = 0);  var length = this.length;  if (i < 0) i = length + i;  for (; i < length; i++)    if (this[i] === item) return i;  return -1;};if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;  var n = this.slice(0, i).reverse().indexOf(item);  return (n < 0) ? n : i - n - 1;};Array.prototype.toArray = Array.prototype.clone;function $w(string) {  if (!Object.isString(string)) return [];  string = string.strip();  return string ? string.split(/\s+/) : [];}if (Prototype.Browser.Opera){  Array.prototype.concat = function() {    var array = [];    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);    for (var i = 0, length = arguments.length; i < length; i++) {      if (Object.isArray(arguments[i])) {        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)          array.push(arguments[i][j]);      } else {        array.push(arguments[i]);      }    }    return array;  };}Object.extend(Number.prototype, {  toColorPart: function() {    return this.toPaddedString(2, 16);  },  succ: function() {    return this + 1;  },  times: function(iterator) {    $R(0, this, true).each(iterator);    return this;  },  toPaddedString: function(length, radix) {    var string = this.toString(radix || 10);    return '0'.times(length - string.length) + string;  },  toJSON: function() {    return isFinite(this) ? this.toString() : 'null';  }});$w('abs round ceil floor').each(function(method){  Number.prototype[method] = Math[method].methodize();});function $H(object) {  return new Hash(object);};var Hash = Class.create(Enumerable, (function() {  if (function() {    var i = 0, Test = function(value) { this.key = value };    Test.prototype.key = 'foo';    for (var property in new Test('bar')) i++;    return i > 1;  }()) {    function each(iterator) {      var cache = [];      for (var key in this._object) {        var value = this._object[key];        if (cache.include(key)) continue;        cache.push(key);        var pair = [key, value];        pair.key = key;        pair.value = value;        iterator(pair);      }    }  } else {    function each(iterator) {      for (var key in this._object) {        var value = this._object[key], pair = [key, value];        pair.key = key;        pair.value = value;        iterator(pair);      }    }  }  function toQueryPair(key, value) {    if (Object.isUndefined(value)) return key;    return key + '=' + encodeURIComponent(String.interpret(value));  }  return {    initialize: function(object) {      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);    },    _each: each,    set: function(key, value) {      return this._object[key] = value;    },    get: function(key) {      return this._object[key];    },    unset: function(key) {      var value = this._object[key];      delete this._object[key];      return value;    },    toObject: function() {      return Object.clone(this._object);    },    keys: function() {      return this.pluck('key');    },    values: function() {      return this.pluck('value');    },    index: function(value) {      var match = this.detect(function(pair) {        return pair.value === value;      });      return match && match.key;    },    merge: function(object) {      return this.clone().update(object);    },    update: function(object) {      return new Hash(object).inject(this, function(result, pair) {        result.set(pair.key, pair.value);        return result;      });    },    toQueryString: function() {      return this.map(function(pair) {        var key = encodeURIComponent(pair.key), values = pair.value;        if (values && typeof values == 'object') {          if (Object.isArray(values))            return values.map(toQueryPair.curry(key)).join('&');        }        return toQueryPair(key, values);      }).join('&');    },    inspect: function() {      return '#<Hash:{' + this.map(function(pair) {        return pair.map(Object.inspect).join(': ');      }).join(', ') + '}>';    },    toJSON: function() {      return Object.toJSON(this.toObject());    },    clone: function() {      return new Hash(this);    }  }})());Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;Hash.from = $H;var ObjectRange = Class.create(Enumerable, {  initialize: function(start, end, exclusive) {    this.start = start;    this.end = end;    this.exclusive = exclusive;  },  _each: function(iterator) {    var value = this.start;    while (this.include(value)) {      iterator(value);      value = value.succ();    }  },  include: function(value) {    if (value < this.start)      return false;    if (this.exclusive)      return value < this.end;    return value <= this.end;  }});var $R = function(start, end, exclusive) {  return new ObjectRange(start, end, exclusive);};var 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();  }});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 && 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;    }  },  getHeader: function(name) {    try {      return this.transport.getResponseHeader(name);    } catch (e) { return null }  },  evalResponse: function() {    try {      return eval((this.transport.responseText || '').unfilterJSON());    } catch (e) {      this.dispatchException(e);    }  },  dispatchException: function(exception) {    (this.options.onException || Prototype.emptyFunction)(this, exception);    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  = xml === undefined ? 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);    } catch (e) {      this.request.dispatchException(e);    }  },  _getResponseJSON: function() {    var options = this.request.options;    if (!options.evalJSON || (options.evalJSON != 'force' &&      !(this.getHeader('Content-type') || '').include('application/json')))        return null;    try {      return this.transport.responseText.evalJSON(options.sanitizeJSON);    } catch (e) {      this.request.dispatchException(e);    }  }});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 = options || { };    var onComplete = options.onComplete;    options.onComplete = (function(response, param) {      this.updateContent(response.responseText);      if (Object.isFunction(onComplete)) onComplete(response, param);    }).bind(this);    $super(url, options);  },  updateContent: function(responseText) {    var receiver = this.container[this.success() ? 'success' : 'failure'],        options = this.options;    if (!options.evalScripts) responseText = responseText.stripScripts();    if (receiver = $(receiver)) {      if (options.insertion) {        if (Object.isString(options.insertion)) {          var insertion = { }; insertion[options.insertion] = responseText;          receiver.insert(insertion);        }        else options.insertion(receiver, responseText);      }      else receiver.update(responseText);    }    if (this.success()) {      if (this.onComplete) this.onComplete.bind(this).defer();    }  }});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 || { });}).call(window);Element.cache = { };Element.Methods = {  visible: function(element) {    return $(element).style.display != 'none';  },  toggle: function(element) {    element = $(element);    Element[Element.visible(element) ? 'hide' : 'show'](element);    return element;  },  hide: function(element) {    $(element).style.display = 'none';    return element;  },  show: function(element) {    $(element).style.display = '';    return element;  },  remove: function(element) {    element = $(element);    element.parentNode.removeChild(element);    return element;  },  update: function(element, content) {    element = $(element);    if (content && content.toElement) content = content.toElement();    if (Object.isElement(content)) return element.update().insert(content);    content = Object.toHTML(content);    element.innerHTML = content.stripScripts();    content.evalScripts.bind(content).defer();    return element;  },  replace: function(element, content) {    element = $(element);    if (content && content.toElement) content = content.toElement();    else if (!Object.isElement(content)) {      content = Object.toHTML(content);      var range = element.ownerDocument.createRange();      range.selectNode(element);      content.evalScripts.bind(content).defer();      content = range.createContextualFragment(content.stripScripts());    }    element.parentNode.replaceChild(content, element);    return element;  },  insert: function(element, insertions) {    element = $(element);    if (Object.isString(insertions) || Object.isNumber(insertions) ||        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))          insertions = {bottom:insertions};    var content, t, range;    for (position in insertions) {      content  = insertions[position];      position = position.toLowerCase();      t = Element._insertionTranslations[position];      if (content && content.toElement) content = content.toElement();      if (Object.isElement(content)) {        t.insert(element, content);        continue;      }      content = Object.toHTML(content);      range = element.ownerDocument.createRange();      t.initializeRange(element, range);      t.insert(element, range.createContextualFragment(content.stripScripts()));      content.evalScripts.bind(content).defer();    }    return element;  },  wrap: function(element, wrapper, attributes) {    element = $(element);    if (Object.isElement(wrapper))      $(wrapper).writeAttribute(attributes || { });    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);    else wrapper = new Element('div', wrapper);    if (element.parentNode)      element.parentNode.replaceChild(wrapper, element);    wrapper.appendChild(element);    return wrapper;  },  inspect: function(element) {    element = $(element);    var result = '<' + element.tagName.toLowerCase();    $H({'id': 'id', 'className': 'class'}).each(function(pair) {      var property = pair.first(), attribute = pair.last();      var value = (element[property] || '').toString();      if (value) result += ' ' + attribute + '=' + value.inspect(true);    });    return result + '>';  },  recursivelyCollect: function(element, property) {    element = $(element);    var elements = [];    while (element = element[property])      if (element.nodeType == 1)        elements.push(Element.extend(element));    return elements;  },  ancestors: function(element) {    return $(element).recursivelyCollect('parentNode');  },  descendants: function(element) {    return $A($(element).getElementsByTagName('*')).each(Element.extend);  },  firstDescendant: function(element) {    element = $(element).firstChild;    while (element && element.nodeType != 1) element = element.nextSibling;    return $(element);  },  immediateDescendants: function(element) {    if (!(element = $(element).firstChild)) return [];    while (element && element.nodeType != 1) element = element.nextSibling;    if (element) return [element].concat($(element).nextSiblings());    return [];  },  previousSiblings: function(element) {    return $(element).recursivelyCollect('previousSibling');  },  nextSiblings: function(element) {    return $(element).recursivelyCollect('nextSibling');  },  siblings: function(element) {    element = $(element);    return element.previousSiblings().reverse().concat(element.nextSiblings());  },  match: function(element, selector) {    if (Object.isString(selector))      selector = new Selector(selector);    return selector.match($(element));  },  up: function(element, expression, index) {    element = $(element);    if (arguments.length == 1) return $(element.parentNode);    var ancestors = element.ancestors();    return expression ? Selector.findElement(ancestors, expression, index) :      ancestors[index || 0];  },  down: function(element, expression, index) {    element = $(element);    if (arguments.length == 1) return element.firstDescendant();    var descendants = element.descendants();    return expression ? Selector.findElement(descendants, expression, index) :      descendants[index || 0];  },  previous: function(element, expression, index) {    element = $(element);    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));    var previousSiblings = element.previousSiblings();    return expression ? Selector.findElement(previousSiblings, expression, index) :      previousSiblings[index || 0];  },  next: function(element, expression, index) {    element = $(element);    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));    var nextSiblings = element.nextSiblings();    return expression ? Selector.findElement(nextSiblings, expression, index) :      nextSiblings[index || 0];  },  select: function() {    var args = $A(arguments), element = $(args.shift());    return Selector.findChildElements(element, args);  },  adjacent: function() {    var args = $A(arguments), element = $(args.shift());    return Selector.findChildElements(element.parentNode, args).without(element);  },  identify: function(element) {    element = $(element);    var id = element.readAttribute('id'), self = arguments.callee;    if (id) return id;    do { id = 'anonymous_element_' + self.counter++ } while ($(id));    element.writeAttribute('id', id);    return id;  },  readAttribute: function(element, name) {    element = $(element);    if (Prototype.Browser.IE) {      var t = Element._attributeTranslations.read;      if (t.values[name]) return t.values[name](element, name);      if (t.names[name]) name = t.names[name];      if (name.include(':')) {        return (!element.attributes || !element.attributes[name]) ? null :         element.attributes[name].value;      }    }    return element.getAttribute(name);  },  writeAttribute: function(element, name, value) {    element = $(element);    var attributes = { }, t = Element._attributeTranslations.write;    if (typeof name == 'object') attributes = name;    else attributes[name] = value === undefined ? true : value;    for (var attr in attributes) {      var name = t.names[attr] || attr, value = attributes[attr];      if (t.values[attr]) name = t.values[attr](element, value);      if (value === false || value === null)        element.removeAttribute(name);      else if (value === true)        element.setAttribute(name, name);      else element.setAttribute(name, value);    }    return element;  },  getHeight: function(element) {    return $(element).getDimensions().height;  },  getWidth: function(element) {    return $(element).getDimensions().width;  },  classNames: function(element) {    return new Element.ClassNames(element);  },  hasClassName: function(element, className) {    if (!(element = $(element))) return;    var elementClassName = element.className;    return (elementClassName.length > 0 && (elementClassName == className ||      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));  },  addClassName: function(element, className) {    if (!(element = $(element))) return;    if (!element.hasClassName(className))      element.className += (element.className ? ' ' : '') + className;    return element;  },  removeClassName: function(element, className) {    if (!(element = $(element))) return;    element.className = element.className.replace(      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();    return element;  },  toggleClassName: function(element, className) {    if (!(element = $(element))) return;    return element[element.hasClassName(className) ?      'removeClassName' : 'addClassName'](className);  },  // removes whitespace-only text node children  cleanWhitespace: function(element) {    element = $(element);    var node = element.firstChild;    while (node) {      var nextNode = node.nextSibling;      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))        element.removeChild(node);      node = nextNode;    }    return element;  },  empty: function(element) {    return $(element).innerHTML.blank();  },  descendantOf: function(element, ancestor) {    element = $(element), ancestor = $(ancestor);    if (element.compareDocumentPosition)      return (element.compareDocumentPosition(ancestor) & 8) === 8;    if (element.sourceIndex && !Prototype.Browser.Opera) {      var e = element.sourceIndex, a = ancestor.sourceIndex,       nextAncestor = ancestor.nextSibling;      if (!nextAncestor) {        do { ancestor = ancestor.parentNode; }        while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);      }      if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);    }    while (element = element.parentNode)      if (element == ancestor) return true;    return false;  },  scrollTo: function(element) {    element = $(element);    var pos = element.cumulativeOffset();    window.scrollTo(pos[0], pos[1]);    return element;  },  getStyle: function(element, style) {    element = $(element);    style = style == 'float' ? 'cssFloat' : style.camelize();    var value = element.style[style];    if (!value) {      var css = document.defaultView.getComputedStyle(element, null);      value = css ? css[style] : null;    }    if (style == 'opacity') return value ? parseFloat(value) : 1.0;    return value == 'auto' ? null : value;  },  getOpacity: function(element) {    return $(element).getStyle('opacity');  },  setStyle: function(element, styles) {    element = $(element);    var elementStyle = element.style, match;    if (Object.isString(styles)) {      element.style.cssText += ';' + styles;      return styles.include('opacity') ?        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;    }    for (var property in styles)      if (property == 'opacity') element.setOpacity(styles[property]);      else        elementStyle[(property == 'float' || property == 'cssFloat') ?          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :            property] = styles[property];    return element;  },  setOpacity: function(element, value) {    element = $(element);    element.style.opacity = (value == 1 || value === '') ? '' :      (value < 0.00001) ? 0 : value;    return element;  },  getDimensions: function(element) {    element = $(element);    var display = $(element).getStyle('display');    if (display != 'none' && display != null) // Safari bug      return {width: element.offsetWidth, height: element.offsetHeight};    // All *Width and *Height properties give 0 on elements with display none,    // so enable the element temporarily    var els = element.style;    var originalVisibility = els.visibility;    var originalPosition = els.position;    var originalDisplay = els.display;    els.visibility = 'hidden';    els.position = 'absolute';    els.display = 'block';    var originalWidth = element.clientWidth;    var originalHeight = element.clientHeight;    els.display = originalDisplay;    els.position = originalPosition;    els.visibility = originalVisibility;    return {width: originalWidth, height: originalHeight};  },  makePositioned: function(element) {    element = $(element);    var pos = Element.getStyle(element, 'position');    if (pos == 'static' || !pos) {      element._madePositioned = true;      element.style.position = 'relative';      // Opera returns the offset relative to the positioning context, when an      // element is position relative but top and left have not been defined      if (window.opera) {        element.style.top = 0;        element.style.left = 0;      }    }    return element;  },  undoPositioned: function(element) {    element = $(element);    if (element._madePositioned) {      element._madePositioned = undefined;      element.style.position =        element.style.top =        element.style.left =        element.style.bottom =        element.style.right = '';    }    return element;  },  makeClipping: function(element) {    element = $(element);    if (element._overflow) return element;    element._overflow = Element.getStyle(element, 'overflow') || 'auto';    if (element._overflow !== 'hidden')      element.style.overflow = 'hidden';    return element;  },  undoClipping: function(element) {    element = $(element);    if (!element._overflow) return element;    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;    element._overflow = null;    return element;  },  cumulativeOffset: function(element) {    var valueT = 0, valueL = 0;    do {      valueT += element.offsetTop  || 0;      valueL += element.offsetLeft || 0;      element = element.offsetParent;    } while (element);    return Element._returnOffset(valueL, valueT);  },  positionedOffset: function(element) {    var valueT = 0, valueL = 0;    do {      valueT += element.offsetTop  || 0;      valueL += element.offsetLeft || 0;      element = element.offsetParent;      if (element) {        if (element.tagName == 'BODY') break;        var p = Element.getStyle(element, 'position');        if (p == 'relative' || p == 'absolute') break;      }    } while (element);    return Element._returnOffset(valueL, valueT);  },  absolutize: function(element) {    element = $(element);    if (element.getStyle('position') == 'absolute') return;    // Position.prepare(); // To be done manually by Scripty when it needs it.    var offsets = element.positionedOffset();    var top     = offsets[1];    var left    = offsets[0];    var width   = element.clientWidth;    var height  = element.clientHeight;    element._originalLeft   = left - parseFloat(element.style.left  || 0);    element._originalTop    = top  - parseFloat(element.style.top || 0);    element._originalWidth  = element.style.width;    element._originalHeight = element.style.height;    element.style.position = 'absolute';    element.style.top    = top + 'px';    element.style.left   = left + 'px';    element.style.width  = width + 'px';    element.style.height = height + 'px';    return element;  },  relativize: function(element) {    element = $(element);    if (element.getStyle('position') == 'relative') return;    // Position.prepare(); // To be done manually by Scripty when it needs it.    element.style.position = 'relative';    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);    element.style.top    = top + 'px';    element.style.left   = left + 'px';    element.style.height = element._originalHeight;    element.style.width  = element._originalWidth;    return element;  },  cumulativeScrollOffset: function(element) {    var valueT = 0, valueL = 0;    do {      valueT += element.scrollTop  || 0;      valueL += element.scrollLeft || 0;      element = element.parentNode;    } while (element);    return Element._returnOffset(valueL, valueT);  },  getOffsetParent: function(element) {    if (element.offsetParent) return $(element.offsetParent);    if (element == document.body) return $(element);    while ((element = element.parentNode) && element != document.body)      if (Element.getStyle(element, 'position') != 'static')        return $(element);    return $(document.body);  },  viewportOffset: function(forElement) {    var valueT = 0, valueL = 0;    var element = forElement;    do {      valueT += element.offsetTop  || 0;      valueL += element.offsetLeft || 0;      // Safari fix      if (element.offsetParent == document.body &&        Element.getStyle(element, 'position') == 'absolute') break;    } while (element = element.offsetParent);    element = forElement;    do {      if (!Prototype.Browser.Opera || element.tagName == 'BODY') {        valueT -= element.scrollTop  || 0;        valueL -= element.scrollLeft || 0;      }    } while (element = element.parentNode);    return Element._returnOffset(valueL, valueT);  },  clonePosition: function(element, source) {    var options = Object.extend({      setLeft:    true,      setTop:     true,      setWidth:   true,      setHeight:  true,      offsetTop:  0,      offsetLeft: 0    }, arguments[2] || { });    // find page position of source    source = $(source);    var p = source.viewportOffset();    // find coordinate system to use    element = $(element);    var delta = [0, 0];    var parent = null;    // delta [0,0] will do fine with position: fixed elements,    // position:absolute needs offsetParent deltas    if (Element.getStyle(element, 'position') == 'absolute') {      parent = element.getOffsetParent();      delta = parent.viewportOffset();    }    // correct by body offsets (fixes Safari)    if (parent == document.body) {      delta[0] -= document.body.offsetLeft;      delta[1] -= document.body.offsetTop;    }    // set position    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';    if (options.setHeight) element.style.height = source.offsetHeight + 'px';    return element;  }};Element.Methods.identify.counter = 1;Object.extend(Element.Methods, {  getElementsBySelector: Element.Methods.select,  childElements: Element.Methods.immediateDescendants});Element._attributeTranslations = {  write: {    names: {      className: 'class',      htmlFor:   'for'    },    values: { }  }};if (!document.createRange || Prototype.Browser.Opera) {  Element.Methods.insert = function(element, insertions) {    element = $(element);    if (Object.isString(insertions) || Object.isNumber(insertions) ||        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))          insertions = { bottom: insertions };    var t = Element._insertionTranslations, content, position, pos, tagName;    for (position in insertions) {      content  = insertions[position];      position = position.toLowerCase();      pos      = t[position];      if (content && content.toElement) content = content.toElement();      if (Object.isElement(content)) {        pos.insert(element, content);        continue;      }      content = Object.toHTML(content);      tagName = ((position == 'before' || position == 'after')        ? element.parentNode : element).tagName.toUpperCase();      if (t.tags[tagName]) {        var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());        if (position == 'top' || position == 'after') fragments.reverse();        fragments.each(pos.insert.curry(element));      }      else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());      content.evalScripts.bind(content).defer();    }    return element;  };}if (Prototype.Browser.Opera) {  Element.Methods._getStyle = Element.Methods.getStyle;  Element.Methods.getStyle = function(element, style) {    switch(style) {      case 'left':      case 'top':      case 'right':      case 'bottom':        if (Element._getStyle(element, 'position') == 'static') return null;      default: return Element._getStyle(element, style);    }  };  Element.Methods._readAttribute = Element.Methods.readAttribute;  Element.Methods.readAttribute = function(element, attribute) {    if (attribute == 'title') return element.title;    return Element._readAttribute(element, attribute);  };}else if (Prototype.Browser.IE) {  $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {    Element.Methods[method] = Element.Methods[method].wrap(      function(proceed, element) {        element = $(element);        var position = element.getStyle('position');        if (position != 'static') return proceed(element);        element.setStyle({ position: 'relative' });        var value = proceed(element);        element.setStyle({ position: position });        return value;      }    );  });  Element.Methods.getStyle = function(element, style) {    element = $(element);    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();    var value = element.style[style];    if (!value && element.currentStyle) value = element.currentStyle[style];    if (style == 'opacity') {      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))        if (value[1]) return parseFloat(value[1]) / 100;      return 1.0;    }    if (value == 'auto') {      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))        return element['offset' + style.capitalize()] + 'px';      return null;    }    return value;  };  Element.Methods.setOpacity = function(element, value) {    function stripAlpha(filter){      return filter.replace(/alpha\([^\)]*\)/gi,'');    }    element = $(element);    var currentStyle = element.currentStyle;    if ((currentStyle && !currentStyle.hasLayout) ||      (!currentStyle && element.style.zoom == 'normal'))        element.style.zoom = 1;    var filter = element.getStyle('filter'), style = element.style;    if (value == 1 || value === '') {      (filter = stripAlpha(filter)) ?        style.filter = filter : style.removeAttribute('filter');      return element;    } else if (value < 0.00001) value = 0;    style.filter = stripAlpha(filter) +      'alpha(opacity=' + (value * 100) + ')';    return element;  };  Element._attributeTranslations = {    read: {      names: {        'class': 'className',        'for':   'htmlFor'      },      values: {        _getAttr: function(element, attribute) {          return element.getAttribute(attribute, 2);        },        _getAttrNode: function(element, attribute) {          var node = element.getAttributeNode(attribute);          return node ? node.value : "";        },        _getEv: function(element, attribute) {          var attribute = element.getAttribute(attribute);          return attribute ? attribute.toString().slice(23, -2) : null;        },        _flag: function(element, attribute) {          return $(element).hasAttribute(attribute) ? attribute : null;        },        style: function(element) {          return element.style.cssText.toLowerCase();        },        title: function(element) {          return element.title;        }      }    }  };  Element._attributeTranslations.write = {    names: Object.clone(Element._attributeTranslations.read.names),    values: {      checked: function(element, value) {        element.checked = !!value;      },      style: function(element, value) {        element.style.cssText = value ? value : '';      }    }  };  Element._attributeTranslations.has = {};  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +      'encType maxLength readOnly longDesc').each(function(attr) {    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;    Element._attributeTranslations.has[attr.toLowerCase()] = attr;  });  (function(v) {    Object.extend(v, {      href:        v._getAttr,      src:         v._getAttr,      type:        v._getAttr,      action:      v._getAttrNode,      disabled:    v._flag,      checked:     v._flag,      readonly:    v._flag,      multiple:    v._flag,      onload:      v._getEv,      onunload:    v._getEv,      onclick:     v._getEv,      ondblclick:  v._getEv,      onmousedown: v._getEv,      onmouseup:   v._getEv,      onmouseover: v._getEv,      onmousemove: v._getEv,      onmouseout:  v._getEv,      onfocus:     v._getEv,      onblur:      v._getEv,      onkeypress:  v._getEv,      onkeydown:   v._getEv,      onkeyup:     v._getEv,      onsubmit:    v._getEv,      onreset:     v._getEv,      onselect:    v._getEv,      onchange:    v._getEv    });  })(Element._attributeTranslations.read.values);}else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {  Element.Methods.setOpacity = function(element, value) {    element = $(element);    element.style.opacity = (value == 1) ? 0.999999 :      (value === '') ? '' : (value < 0.00001) ? 0 : value;    return element;  };}else if (Prototype.Browser.WebKit) {  Element.Methods.setOpacity = function(element, value) {    element = $(element);    element.style.opacity = (value == 1 || value === '') ? '' :      (value < 0.00001) ? 0 : value;    if (value == 1)      if(element.tagName == 'IMG' && element.width) {        element.width++; element.width--;      } else try {        var n = document.createTextNode(' ');        element.appendChild(n);        element.removeChild(n);      } catch (e) { }    return element;  };  // Safari returns margins on body which is incorrect if the child is absolutely  // positioned.  For performance reasons, redefine Position.cumulativeOffset for  // KHTML/WebKit only.  Element.Methods.cumulativeOffset = function(element) {    var valueT = 0, valueL = 0;    do {      valueT += element.offsetTop  || 0;      valueL += element.offsetLeft || 0;      if (element.offsetParent == document.body)        if (Element.getStyle(element, 'position') == 'absolute') break;      element = element.offsetParent;    } while (element);    return Element._returnOffset(valueL, valueT);  };}if (Prototype.Browser.IE || Prototype.Browser.Opera) {  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements  Element.Methods.update = function(element, content) {    element = $(element);    if (content && content.toElement) content = content.toElement();    if (Object.isElement(content)) return element.update().insert(content);    content = Object.toHTML(content);    var tagName = element.tagName.toUpperCase();    if (tagName in Element._insertionTranslations.tags) {      $A(element.childNodes).each(function(node) { element.removeChild(node) });      Element._getContentFromAnonymousElement(tagName, content.stripScripts())        .each(function(node) { element.appendChild(node) });    }    else element.innerHTML = content.stripScripts();    content.evalScripts.bind(content).defer();    return element;  };}if (document.createElement('div').outerHTML) {  Element.Methods.replace = function(element, content) {    element = $(element);    if (content && content.toElement) content = content.toElement();    if (Object.isElement(content)) {      element.parentNode.replaceChild(content, element);      return element;    }    content = Object.toHTML(content);    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();    if (Element._insertionTranslations.tags[tagName]) {      var nextSibling = element.next();      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());      parent.removeChild(element);      if (nextSibling)        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });      else        fragments.each(function(node) { parent.appendChild(node) });    }    else element.outerHTML = content.stripScripts();    content.evalScripts.bind(content).defer();    return element;  };}Element._returnOffset = function(l, t) {  var result = [l, t];  result.left = l;  result.top = t;  return result;};Element._getContentFromAnonymousElement = function(tagName, html) {  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];  div.innerHTML = t[0] + html + t[1];  t[2].times(function() { div = div.firstChild });  return $A(div.childNodes);};Element._insertionTranslations = {  before: {    adjacency: 'beforeBegin',    insert: function(element, node) {      element.parentNode.insertBefore(node, element);    },    initializeRange: function(element, range) {      range.setStartBefore(element);    }  },  top: {    adjacency: 'afterBegin',    insert: function(element, node) {      element.insertBefore(node, element.firstChild);    },    initializeRange: function(element, range) {      range.selectNodeContents(element);      range.collapse(true);    }  },  bottom: {    adjacency: 'beforeEnd',    insert: function(element, node) {      element.appendChild(node);    }  },  after: {    adjacency: 'afterEnd',    insert: function(element, node) {      element.parentNode.insertBefore(node, element.nextSibling);    },    initializeRange: function(element, range) {      range.setStartAfter(element);    }  },  tags: {    TABLE:  ['<table>',                '</table>',                   1],    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],    SELECT: ['<select>',               '</select>',                  1]  }};(function() {  this.bottom.initializeRange = this.top.initializeRange;  Object.extend(this.tags, {    THEAD: this.tags.TBODY,    TFOOT: this.tags.TBODY,    TH:    this.tags.TD  });}).call(Element._insertionTranslations);Element.Methods.Simulated = {  hasAttribute: function(element, attribute) {    attribute = Element._attributeTranslations.has[attribute] || attribute;    var node = $(element).getAttributeNode(attribute);    return node && node.specified;  }};Element.Methods.ByTag = { };Object.extend(Element, Element.Methods);if (!Prototype.BrowserFeatures.ElementExtensions &&    document.createElement('div').__proto__) {  window.HTMLElement = { };  window.HTMLElement.prototype = document.createElement('div').__proto__;  Prototype.BrowserFeatures.ElementExtensions = true;}Element.extend = (function() {  if (Prototype.BrowserFeatures.SpecificElementExtensions)    return Prototype.K;  var Methods = { }, ByTag = Element.Methods.ByTag;  var extend = Object.extend(function(element) {    if (!element || element._extendedByPrototype ||        element.nodeType != 1 || element == window) return element;    var methods = Object.clone(Methods),      tagName = element.tagName, property, value;    // extend methods for specific tags    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);    for (property in methods) {      value = methods[property];      if (Object.isFunction(value) && !(property in element))        element[property] = value.methodize();    }    element._extendedByPrototype = Prototype.emptyFunction;    return element;  }, {    refresh: function() {      // extend methods for all tags (Safari doesn't need this)      if (!Prototype.BrowserFeatures.ElementExtensions) {        Object.extend(Methods, Element.Methods);        Object.extend(Methods, Element.Methods.Simulated);      }    }  });  extend.refresh();  return extend;})();Element.hasAttribute = function(element, attribute) {  if (element.hasAttribute) return element.hasAttribute(attribute);  return Element.Methods.Simulated.hasAttribute(element, attribute);};Element.addMethods = function(methods) {  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;  if (!methods) {    Object.extend(Form, Form.Methods);    Object.extend(Form.Element, Form.Element.Methods);    Object.extend(Element.Methods.ByTag, {      "FORM":     Object.clone(Form.Methods),      "INPUT":    Object.clone(Form.Element.Methods),      "SELECT":   Object.clone(Form.Element.Methods),      "TEXTAREA": Object.clone(Form.Element.Methods)    });  }  if (arguments.length == 2) {    var tagName = methods;    methods = arguments[1];  }  if (!tagName) Object.extend(Element.Methods, methods || { });  else {    if (Object.isArray(tagName)) tagName.each(extend);    else extend(tagName);  }  function extend(tagName) {    tagName = tagName.toUpperCase();    if (!Element.Methods.ByTag[tagName])      Element.Methods.ByTag[tagName] = { };    Object.extend(Element.Methods.ByTag[tagName], methods);  }  function copy(methods, destination, onlyIfAbsent) {    onlyIfAbsent = onlyIfAbsent || false;    for (var property in methods) {      var value = methods[property];      if (!Object.isFunction(value)) continue;      if (!onlyIfAbsent || !(property in destination))        destination[property] = value.methodize();    }  }  function findDOMClass(tagName) {    var klass;    var trans = {      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":      "FrameSet", "IFRAME": "IFrame"    };    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';    if (window[klass]) return window[klass];    klass = 'HTML' + tagName + 'Element';    if (window[klass]) return window[klass];    klass = 'HTML' + tagName.capitalize() + 'Element';    if (window[klass]) return window[klass];    window[klass] = { };    window[klass].prototype = document.createElement(tagName).__proto__;    return window[klass];  }  if (F.ElementExtensions) {    copy(Element.Methods, HTMLElement.prototype);    copy(Element.Methods.Simulated, HTMLElement.prototype, true);  }  if (F.SpecificElementExtensions) {    for (var tag in Element.Methods.ByTag) {      var klass = findDOMClass(tag);      if (Object.isUndefined(klass)) continue;      copy(T[tag], klass.prototype);    }  }  Object.extend(Element, Element.Methods);  delete Element.ByTag;  if (Element.extend.refresh) Element.extend.refresh();  Element.cache = { };};document.viewport = {  getDimensions: function() {    var dimensions = { };    $w('width height').each(function(d) {      var D = d.capitalize();      dimensions[d] = self['inner' + D] ||       (document.documentElement['client' + D] || document.body['client' + D]);    });    return dimensions;  },  getWidth: function() {    return this.getDimensions().width;  },  getHeight: function() {    return this.getDimensions().height;  },  getScrollOffsets: function() {    return Element._returnOffset(      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);  }};/* Portions of the Selector class are derived from Jack SlocumÃ¢â?¬â?¢s DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license.  Please see http://www.yui-ext.com/ for more information. */var Selector = Class.create({  initialize: function(expression) {    this.expression = expression.strip();    this.compileMatcher();  },  compileMatcher: function() {    // Selectors with namespaced attributes can't use the XPath version    if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))      return this.compileXPathMatcher();    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,        c = Selector.criteria, le, p, m;    if (Selector._cache[e]) {      this.matcher = Selector._cache[e];      return;    }    this.matcher = ["this.matcher = function(root) {",                    "var r = root, h = Selector.handlers, c = false, n;"];    while (e && le != e && (/\S/).test(e)) {      le = e;      for (var i in ps) {        p = ps[i];        if (m = e.match(p)) {          this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :    	      new Template(c[i]).evaluate(m));          e = e.replace(m[0], '');          break;        }      }    }    this.matcher.push("return h.unique(n);\n}");    eval(this.matcher.join('\n'));    Selector._cache[this.expression] = this.matcher;  },  compileXPathMatcher: function() {    var e = this.expression, ps = Selector.patterns,        x = Selector.xpath, le, m;    if (Selector._cache[e]) {      this.xpath = Selector._cache[e]; return;    }    this.matcher = ['.//*'];    while (e && le != e && (/\S/).test(e)) {      le = e;      for (var i in ps) {        if (m = e.match(ps[i])) {          this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :            new Template(x[i]).evaluate(m));          e = e.replace(m[0], '');          break;        }      }    }    this.xpath = this.matcher.join('');    Selector._cache[this.expression] = this.xpath;  },  findElements: function(root) {    root = root || document;    if (this.xpath) return document._getElementsByXPath(this.xpath, root);    return this.matcher(root);  },  match: function(element) {    this.tokens = [];    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;    var le, p, m;    while (e && le !== e && (/\S/).test(e)) {      le = e;      for (var i in ps) {        p = ps[i];        if (m = e.match(p)) {          // use the Selector.assertions methods unless the selector          // is too complex.          if (as[i]) {            this.tokens.push([i, Object.clone(m)]);            e = e.replace(m[0], '');          } else {            // reluctantly do a document-wide search            // and look for a match in the array            return this.findElements(document).include(element);          }        }      }    }    var match = true, name, matches;    for (var i = 0, token; token = this.tokens[i]; i++) {      name = token[0], matches = token[1];      if (!Selector.assertions[name](element, matches)) {        match = false; break;      }    }    return match;  },  toString: function() {    return this.expression;  },  inspect: function() {    return "#<Selector:" + this.expression.inspect() + ">";  }});Object.extend(Selector, {  _cache: { },  xpath: {    descendant:   "//*",    child:        "/*",    adjacent:     "/following-sibling::*[1]",    laterSibling: '/following-sibling::*',    tagName:      function(m) {      if (m[1] == '*') return '';      return "[local-name()='" + m[1].toLowerCase() +             "' or local-name()='" + m[1].toUpperCase() + "']";    },    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",    id:           "[@id='#{1}']",    attrPresence: "[@#{1}]",    attr: function(m) {      m[3] = m[5] || m[6];      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);    },    pseudo: function(m) {      var h = Selector.xpath.pseudos[m[1]];      if (!h) return '';      if (Object.isFunction(h)) return h(m);      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);    },    operators: {      '=':  "[@#{1}='#{3}']",      '!=': "[@#{1}!='#{3}']",      '^=': "[starts-with(@#{1}, '#{3}')]",      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",      '*=': "[contains(@#{1}, '#{3}')]",      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"    },    pseudos: {      'first-child': '[not(preceding-sibling::*)]',      'last-child':  '[not(following-sibling::*)]',      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",      'checked':     "[@checked]",      'disabled':    "[@disabled]",      'enabled':     "[not(@disabled)]",      'not': function(m) {        var e = m[6], p = Selector.patterns,            x = Selector.xpath, le, m, v;        var exclusion = [];        while (e && le != e && (/\S/).test(e)) {          le = e;          for (var i in p) {            if (m = e.match(p[i])) {              v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);              exclusion.push("(" + v.substring(1, v.length - 1) + ")");              e = e.replace(m[0], '');              break;            }          }        }        return "[not(" + exclusion.join(" and ") + ")]";      },      'nth-child':      function(m) {        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);      },      'nth-last-child': function(m) {        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);      },      'nth-of-type':    function(m) {        return Selector.xpath.pseudos.nth("position() ", m);      },      'nth-last-of-type': function(m) {        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);      },      'first-of-type':  function(m) {        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);      },      'last-of-type':   function(m) {        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);      },      'only-of-type':   function(m) {        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);      },      nth: function(fragment, m) {        var mm, formula = m[6], predicate;        if (formula == 'even') formula = '2n+0';        if (formula == 'odd')  formula = '2n+1';        if (mm = formula.match(/^(\d+)$/)) // digit only          return '[' + fragment + "= " + mm[1] + ']';        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b          if (mm[1] == "-") mm[1] = -1;          var a = mm[1] ? Number(mm[1]) : 1;          var b = mm[2] ? Number(mm[2]) : 0;          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +          "((#{fragment} - #{b}) div #{a} >= 0)]";          return new Template(predicate).evaluate({            fragment: fragment, a: a, b: b });        }      }    }  },  criteria: {    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;',    className:    'n = h.className(n, r, "#{1}", c); c = false;',    id:           'n = h.id(n, r, "#{1}", c);        c = false;',    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',    attr: function(m) {      m[3] = (m[5] || m[6]);      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);    },    pseudo: function(m) {      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);    },    descendant:   'c = "descendant";',    child:        'c = "child";',    adjacent:     'c = "adjacent";',    laterSibling: 'c = "laterSibling";'  },  patterns: {    // combinators must be listed first    // (and descendant needs to be last combinator)    laterSibling: /^\s*~\s*/,    child:        /^\s*>\s*/,    adjacent:     /^\s*\+\s*/,    descendant:   /^\s/,    // selectors follow    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,    id:           /^#([\w\-\*]+)(\b|$)/,    className:    /^\.([\w\-\*]+)(\b|$)/,    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,    attrPresence: /^\[([\w]+)\]/,    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/  },  // for Selector.match and Element#match  assertions: {    tagName: function(element, matches) {      return matches[1].toUpperCase() == element.tagName.toUpperCase();    },    className: function(element, matches) {      return Element.hasClassName(element, matches[1]);    },    id: function(element, matches) {      return element.id === matches[1];    },    attrPresence: function(element, matches) {      return Element.hasAttribute(element, matches[1]);    },    attr: function(element, matches) {      var nodeValue = Element.readAttribute(element, matches[1]);      return Selector.operators[matches[2]](nodeValue, matches[3]);    }  },  handlers: {    // UTILITY FUNCTIONS    // joins two collections    concat: function(a, b) {      for (var i = 0, node; node = b[i]; i++)        a.push(node);      return a;    },    // marks an array of nodes for counting    mark: function(nodes) {      for (var i = 0, node; node = nodes[i]; i++)        node._counted = true;      return nodes;    },    unmark: function(nodes) {      for (var i = 0, node; node = nodes[i]; i++)        node._counted = undefined;      return nodes;    },    // mark each child node with its position (for nth calls)    // "ofType" flag indicates whether we're indexing for nth-of-type    // rather than nth-child    index: function(parentNode, reverse, ofType) {      parentNode._counted = true;      if (reverse) {        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {          var node = nodes[i];          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;        }      } else {        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;      }    },    // filters out duplicates and extends all nodes    unique: function(nodes) {      if (nodes.length == 0) return nodes;      var results = [], n;      for (var i = 0, l = nodes.length; i < l; i++)        if (!(n = nodes[i])._counted) {          n._counted = true;          results.push(Element.extend(n));        }      return Selector.handlers.unmark(results);    },    // COMBINATOR FUNCTIONS    descendant: function(nodes) {      var h = Selector.handlers;      for (var i = 0, results = [], node; node = nodes[i]; i++)        h.concat(results, node.getElementsByTagName('*'));      return results;    },    child: function(nodes) {      var h = Selector.handlers;      for (var i = 0, results = [], node; node = nodes[i]; i++) {        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)          if (child.nodeType == 1 && child.tagName != '!') results.push(child);      }      return results;    },    adjacent: function(nodes) {      for (var i = 0, results = [], node; node = nodes[i]; i++) {        var next = this.nextElementSibling(node);        if (next) results.push(next);      }      return results;    },    laterSibling: function(nodes) {      var h = Selector.handlers;      for (var i = 0, results = [], node; node = nodes[i]; i++)        h.concat(results, Element.nextSiblings(node));      return results;    },    nextElementSibling: function(node) {      while (node = node.nextSibling)	      if (node.nodeType == 1) return node;      return null;    },    previousElementSibling: function(node) {      while (node = node.previousSibling)        if (node.nodeType == 1) return node;      return null;    },    // TOKEN FUNCTIONS    tagName: function(nodes, root, tagName, combinator) {      tagName = tagName.toUpperCase();      var results = [], h = Selector.handlers;      if (nodes) {        if (combinator) {          // fastlane for ordinary descendant combinators          if (combinator == "descendant") {            for (var i = 0, node; node = nodes[i]; i++)              h.concat(results, node.getElementsByTagName(tagName));            return results;          } else nodes = this[combinator](nodes);          if (tagName == "*") return nodes;        }        for (var i = 0, node; node = nodes[i]; i++)          if (node.tagName.toUpperCase() == tagName) results.push(node);        return results;      } else return root.getElementsByTagName(tagName);    },    id: function(nodes, root, id, combinator) {      var targetNode = $(id), h = Selector.handlers;      if (!targetNode) return [];      if (!nodes && root == document) return [targetNode];      if (nodes) {        if (combinator) {          if (combinator == 'child') {            for (var i = 0, node; node = nodes[i]; i++)              if (targetNode.parentNode == node) return [targetNode];          } else if (combinator == 'descendant') {            for (var i = 0, node; node = nodes[i]; i++)              if (Element.descendantOf(targetNode, node)) return [targetNode];          } else if (combinator == 'adjacent') {            for (var i = 0, node; node = nodes[i]; i++)              if (Selector.handlers.previousElementSibling(targetNode) == node)                return [targetNode];          } else nodes = h[combinator](nodes);        }        for (var i = 0, node; node = nodes[i]; i++)          if (node == targetNode) return [targetNode];        return [];      }      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];    },    className: function(nodes, root, className, combinator) {      if (nodes && combinator) nodes = this[combinator](nodes);      return Selector.handlers.byClassName(nodes, root, className);    },    byClassName: function(nodes, root, className) {      if (!nodes) nodes = Selector.handlers.descendant([root]);      var needle = ' ' + className + ' ';      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {        nodeClassName = node.className;        if (nodeClassName.length == 0) continue;        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))          results.push(node);      }      return results;    },    attrPresence: function(nodes, root, attr) {      if (!nodes) nodes = root.getElementsByTagName("*");      var results = [];      for (var i = 0, node; node = nodes[i]; i++)        if (Element.hasAttribute(node, attr)) results.push(node);      return results;    },    attr: function(nodes, root, attr, value, operator) {      if (!nodes) nodes = root.getElementsByTagName("*");      var handler = Selector.operators[operator], results = [];      for (var i = 0, node; node = nodes[i]; i++) {        var nodeValue = Element.readAttribute(node, attr);        if (nodeValue === null) continue;        if (handler(nodeValue, value)) results.push(node);      }      return results;    },    pseudo: function(nodes, name, value, root, combinator) {      if (nodes && combinator) nodes = this[combinator](nodes);      if (!nodes) nodes = root.getElementsByTagName("*");      return Selector.pseudos[name](nodes, value, root);    }  },  pseudos: {    'first-child': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++) {        if (Selector.handlers.previousElementSibling(node)) continue;          results.push(node);      }      return results;    },    'last-child': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++) {        if (Selector.handlers.nextElementSibling(node)) continue;          results.push(node);      }      return results;    },    'only-child': function(nodes, value, root) {      var h = Selector.handlers;      for (var i = 0, results = [], node; node = nodes[i]; i++)        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))          results.push(node);      return results;    },    'nth-child':        function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, formula, root);    },    'nth-last-child':   function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, formula, root, true);    },    'nth-of-type':      function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, formula, root, false, true);    },    'nth-last-of-type': function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, formula, root, true, true);    },    'first-of-type':    function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, "1", root, false, true);    },    'last-of-type':     function(nodes, formula, root) {      return Selector.pseudos.nth(nodes, "1", root, true, true);    },    'only-of-type':     function(nodes, formula, root) {      var p = Selector.pseudos;      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);    },    // handles the an+b logic    getIndices: function(a, b, total) {      if (a == 0) return b > 0 ? [b] : [];      return $R(1, total).inject([], function(memo, i) {        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);        return memo;      });    },    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type    nth: function(nodes, formula, root, reverse, ofType) {      if (nodes.length == 0) return [];      if (formula == 'even') formula = '2n+0';      if (formula == 'odd')  formula = '2n+1';      var h = Selector.handlers, results = [], indexed = [], m;      h.mark(nodes);      for (var i = 0, node; node = nodes[i]; i++) {        if (!node.parentNode._counted) {          h.index(node.parentNode, reverse, ofType);          indexed.push(node.parentNode);        }      }      if (formula.match(/^\d+$/)) { // just a number        formula = Number(formula);        for (var i = 0, node; node = nodes[i]; i++)          if (node.nodeIndex == formula) results.push(node);      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b        if (m[1] == "-") m[1] = -1;        var a = m[1] ? Number(m[1]) : 1;        var b = m[2] ? Number(m[2]) : 0;        var indices = Selector.pseudos.getIndices(a, b, nodes.length);        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {          for (var j = 0; j < l; j++)            if (node.nodeIndex == indices[j]) results.push(node);        }      }      h.unmark(nodes);      h.unmark(indexed);      return results;    },    'empty': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++) {        // IE treats comments as element nodes        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;        results.push(node);      }      return results;    },    'not': function(nodes, selector, root) {      var h = Selector.handlers, selectorType, m;      var exclusions = new Selector(selector).findElements(root);      h.mark(exclusions);      for (var i = 0, results = [], node; node = nodes[i]; i++)        if (!node._counted) results.push(node);      h.unmark(exclusions);      return results;    },    'enabled': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++)        if (!node.disabled) results.push(node);      return results;    },    'disabled': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++)        if (node.disabled) results.push(node);      return results;    },    'checked': function(nodes, value, root) {      for (var i = 0, results = [], node; node = nodes[i]; i++)        if (node.checked) results.push(node);      return results;    }  },  operators: {    '=':  function(nv, v) { return nv == v; },    '!=': function(nv, v) { return nv != v; },    '^=': function(nv, v) { return nv.startsWith(v); },    '$=': function(nv, v) { return nv.endsWith(v); },    '*=': function(nv, v) { return nv.include(v); },    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }  },  matchElements: function(elements, expression) {    var matches = new Selector(expression).findElements(), h = Selector.handlers;    h.mark(matches);    for (var i = 0, results = [], element; element = elements[i]; i++)      if (element._counted) results.push(element);    h.unmark(matches);    return results;  },  findElement: function(elements, expression, index) {    if (Object.isNumber(expression)) {      index = expression; expression = false;    }    return Selector.matchElements(elements, expression || '*')[index || 0];  },  findChildElements: function(element, expressions) {    var exprs = expressions.join(','), expressions = [];    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {      expressions.push(m[1].strip());    });    var results = [], h = Selector.handlers;    for (var i = 0, l = expressions.length, selector; i < l; i++) {      selector = new Selector(expressions[i].strip());      h.concat(results, selector.findElements(element));    }    return (l > 1) ? h.unique(results) : results;  }});function $$() {  return Selector.findChildElements(document, $A(arguments));}var Form = {  reset: function(form) {    $(form).reset();    return form;  },  serializeElements: function(elements, options) {    if (typeof options != 'object') options = { hash: !!options };    else if (options.hash === undefined) options.hash = true;    var key, value, submitted = false, submit = options.submit;    var data = elements.inject({ }, function(result, element) {      if (!element.disabled && element.name) {        key = element.name; value = $(element).getValue();        if (value != null && (element.type != 'submit' || (!submitted &&            submit !== false && (!submit || key == submit) && (submitted = true)))) {          if (key in result) {            // a key is already present; construct an array of values            if (!Object.isArray(result[key])) result[key] = [result[key]];            result[key].push(value);          }          else result[key] = value;        }      }      return result;    });    return options.hash ? data : Object.toQueryString(data);  }};Form.Methods = {  serialize: function(form, options) {    return Form.serializeElements(Form.getElements(form), options);  },  getElements: function(form) {    return $A($(form).getElementsByTagName('*')).inject([],      function(elements, child) {        if (Form.Element.Serializers[child.tagName.toLowerCase()])          elements.push(Element.extend(child));        return elements;      }    );  },  getInputs: function(form, typeName, name) {    form = $(form);    var inputs = form.getElementsByTagName('input');    if (!typeName && !name) return $A(inputs).map(Element.extend);    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {      var input = inputs[i];      if ((typeName && input.type != typeName) || (name && input.name != name))        continue;      matchingInputs.push(Element.extend(input));    }    return matchingInputs;  },  disable: function(form) {    form = $(form);    Form.getElements(form).invoke('disable');    return form;  },  enable: function(form) {    form = $(form);    Form.getElements(form).invoke('enable');    return form;  },  findFirstElement: function(form) {    var elements = $(form).getElements().findAll(function(element) {      return 'hidden' != element.type && !element.disabled;    });    var firstByIndex = elements.findAll(function(element) {      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;    }).sortBy(function(element) { return element.tabIndex }).first();    return firstByIndex ? firstByIndex : elements.find(function(element) {      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());    });  },  focusFirstElement: function(form) {    form = $(form);    form.findFirstElement().activate();    return form;  },  request: function(form, options) {    form = $(form), options = Object.clone(options || { });    var params = options.parameters, action = form.readAttribute('action') || '';    if (action.blank()) action = window.location.href;    options.parameters = form.serialize(true);    if (params) {      if (Object.isString(params)) params = params.toQueryParams();      Object.extend(options.parameters, params);    }    if (form.hasAttribute('method') && !options.method)      options.method = form.method;    return new 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.blur();    element.disabled = true;    return element;  },  enable: function(element) {    element = $(element);    element.disabled = false;    return element;  }};/*--------------------------------------------------------------------------*/var Field = Form.Element;var $F = Form.Element.Methods.getValue;/*--------------------------------------------------------------------------*/Form.Element.Serializers = {  input: function(element, value) {    switch (element.type.toLowerCase()) {      case 'checkbox':      case 'radio':        return Form.Element.Serializers.inputSelector(element, value);      default:        return Form.Element.Serializers.textarea(element, value);    }  },  inputSelector: function(element, value) {    if (value === undefined) return element.checked ? element.value : null;    else element.checked = !!value;  },  textarea: function(element, value) {    if (value === undefined) return element.value;    else element.value = value;  },  select: function(element, index) {    if (index === undefined)      return this[element.type == 'select-one' ?        'selectOne' : 'selectMany'](element);    else {      var opt, value, single = !Object.isArray(index);      for (var i = 0, length = element.length; i < length; i++) {        opt = element.options[i];        value = this.optionValue(opt);        if (single) {          if (value == index) {            opt.selected = true;            return;          }        }        else opt.selected = index.include(value);      }    }  },  selectOne: function(element) {    var index = element.selectedIndex;    return index >= 0 ? this.optionValue(element.options[index]) : null;  },  selectMany: function(element) {    var values, length = element.length;    if (!length) return null;    for (var i = 0, values = []; i < length; i++) {      var opt = element.options[i];      if (opt.selected) values.push(this.optionValue(opt));    }    return values;  },  optionValue: function(opt) {    // extend element because hasAttribute may not be native    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;  }};/*--------------------------------------------------------------------------*/Abstract.TimedObserver = Class.create(PeriodicalExecuter, {  initialize: function($super, element, frequency, callback) {    $super(callback, frequency);    this.element   = $(element);    this.lastValue = this.getValue();  },  execute: function() {    var value = this.getValue();    if (Object.isString(this.lastValue) && Object.isString(value) ?        this.lastValue != value : String(this.lastValue) != String(value)) {      this.callback(this.element, value);      this.lastValue = value;    }  }});Form.Element.Observer = Class.create(Abstract.TimedObserver, {  getValue: function() {    return Form.Element.getValue(this.element);  }});Form.Observer = Class.create(Abstract.TimedObserver, {  getValue: function() {    return Form.serialize(this.element);  }});/*--------------------------------------------------------------------------*/Abstract.EventObserver = Class.create({  initialize: function(element, callback) {    this.element  = $(element);    this.callback = callback;    this.lastValue = this.getValue();    if (this.element.tagName.toLowerCase() == 'form')      this.registerFormCallbacks();    else      this.registerCallback(this.element);  },  onElementEvent: function() {    var value = this.getValue();    if (this.lastValue != value) {      this.callback(this.element, value);      this.lastValue = value;    }  },  registerFormCallbacks: function() {    Form.getElements(this.element).each(this.registerCallback, this);  },  registerCallback: function(element) {    if (element.type) {      switch (element.type.toLowerCase()) {        case 'checkbox':        case 'radio':          Event.observe(element, 'click', this.onElementEvent.bind(this));          break;        default:          Event.observe(element, 'change', this.onElementEvent.bind(this));          break;      }    }  }});Form.Element.EventObserver = Class.create(Abstract.EventObserver, {  getValue: function() {    return Form.Element.getValue(this.element);  }});Form.EventObserver = Class.create(Abstract.EventObserver, {  getValue: function() {    return Form.serialize(this.element);  }});if (!window.Event) var Event = { };Object.extend(Event, {  KEY_BACKSPACE: 8,  KEY_TAB:       9,  KEY_RETURN:   13,  KEY_ESC:      27,  KEY_LEFT:     37,  KEY_UP:       38,  KEY_RIGHT:    39,  KEY_DOWN:     40,  KEY_DELETE:   46,  KEY_HOME:     36,  KEY_END:      35,  KEY_PAGEUP:   33,  KEY_PAGEDOWN: 34,  KEY_INSERT:   45,  cache: { },  relatedTarget: function(event) {    var element;    switch(event.type) {      case 'mouseover': element = event.fromElement; break;      case 'mouseout':  element = event.toElement;   break;      default: return null;    }    return Element.extend(element);  }});Event.Methods = (function() {  var isButton;  if (Prototype.Browser.IE) {    var buttonMap = { 0: 1, 1: 4, 2: 2 };    isButton = function(event, code) {      return event.button == buttonMap[code];    };  } else if (Prototype.Browser.WebKit) {    isButton = function(event, code) {      switch (code) {        case 0: return event.which == 1 && !event.metaKey;        case 1: return event.which == 1 && event.metaKey;        default: return false;      }    };  } else {    isButton = function(event, code) {      return event.which ? (event.which === code + 1) : (event.button === code);    };  }  return {    isLeftClick:   function(event) { return isButton(event, 0) },    isMiddleClick: function(event) { return isButton(event, 1) },    isRightClick:  function(event) { return isButton(event, 2) },    element: function(event) {      var node = Event.extend(event).target;      return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);    },    findElement: function(event, expression) {      var element = Event.element(event);      return element.match(expression) ? element : element.up(expression);    },    pointer: function(event) {      return {        x: event.pageX || (event.clientX +          (document.documentElement.scrollLeft || document.body.scrollLeft)),        y: event.pageY || (event.clientY +          (document.documentElement.scrollTop || document.body.scrollTop))      };    },    pointerX: function(event) { return Event.pointer(event).x },    pointerY: function(event) { return Event.pointer(event).y },    stop: function(event) {      Event.extend(event);      event.preventDefault();      event.stopPropagation();      event.stopped = true;    }  };})();Event.extend = (function() {  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {    m[name] = Event.Methods[name].methodize();    return m;  });  if (Prototype.Browser.IE) {    Object.extend(methods, {      stopPropagation: function() { this.cancelBubble = true },      preventDefault:  function() { this.returnValue = false },      inspect: function() { return "[object Event]" }    });    return function(event) {      if (!event) return false;      if (event._extendedByPrototype) return event;      event._extendedByPrototype = Prototype.emptyFunction;      var pointer = Event.pointer(event);      Object.extend(event, {        target: event.srcElement,        relatedTarget: Event.relatedTarget(event),        pageX:  pointer.x,        pageY:  pointer.y      });      return Object.extend(event, methods);    };  } else {    Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;    Object.extend(Event.prototype, methods);    return Prototype.K;  }})();Object.extend(Event, (function() {  var cache = Event.cache;  function getEventID(element) {    if (element._eventID) return element._eventID;    arguments.callee.id = arguments.callee.id || 1;    return element._eventID = ++arguments.callee.id;  }  function getDOMEventName(eventName) {    if (eventName && eventName.include(':')) return "dataavailable";    return eventName;  }  function getCacheForID(id) {    return cache[id] = cache[id] || { };  }  function getWrappersForEventName(id, eventName) {    var c = getCacheForID(id);    return c[eventName] = c[eventName] || [];  }  function createWrapper(element, eventName, handler) {    var id = getEventID(element);    var c = getWrappersForEventName(id, eventName);    if (c.pluck("handler").include(handler)) return false;    var wrapper = function(event) {      if (!Event || !Event.extend ||        (event.eventName && event.eventName != eventName))          return false;      Event.extend(event);      handler.call(element, event)    };    wrapper.handler = handler;    c.push(wrapper);    return wrapper;  }  function findWrapper(id, eventName, handler) {    var c = getWrappersForEventName(id, eventName);    return c.find(function(wrapper) { return wrapper.handler == handler });  }  function destroyWrapper(id, eventName, handler) {    var c = getCacheForID(id);    if (!c[eventName]) return false;    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));  }  function destroyCache() {    for (var id in cache)      for (var eventName in cache[id])        cache[id][eventName] = null;  }  if (window.attachEvent) {    window.attachEvent("onunload", destroyCache);  }  return {    observe: function(element, eventName, handler) {      element = $(element);      var name = getDOMEventName(eventName);      var wrapper = createWrapper(element, eventName, handler);      if (!wrapper) return element;      if (element.addEventListener) {        element.addEventListener(name, wrapper, false);      } else {        element.attachEvent("on" + name, wrapper);      }      return element;    },    stopObserving: function(element, eventName, handler) {      element = $(element);      var id = getEventID(element), name = getDOMEventName(eventName);      if (!handler && eventName) {        getWrappersForEventName(id, eventName).each(function(wrapper) {          element.stopObserving(eventName, wrapper.handler);        });        return element;      } else if (!eventName) {        Object.keys(getCacheForID(id)).each(function(eventName) {          element.stopObserving(eventName);        });        return element;      }      var wrapper = findWrapper(id, eventName, handler);      if (!wrapper) return element;      if (element.removeEventListener) {        element.removeEventListener(name, wrapper, false);      } else {        element.detachEvent("on" + name, wrapper);      }      destroyWrapper(id, eventName, handler);      return element;    },    fire: function(element, eventName, memo) {      element = $(element);      if (element == document && document.createEvent && !element.dispatchEvent)        element = document.documentElement;      if (document.createEvent) {        var event = document.createEvent("HTMLEvents");        event.initEvent("dataavailable", true, true);      } else {        var event = document.createEventObject();        event.eventType = "ondataavailable";      }      event.eventName = eventName;      event.memo = memo || { };      if (document.createEvent) {        element.dispatchEvent(event);      } else {        element.fireEvent(event.eventType, event);      }      return event;    }  };})());Object.extend(Event, Event.Methods);Element.addMethods({  fire:          Event.fire,  observe:       Event.observe,  stopObserving: Event.stopObserving});Object.extend(document, {  fire:          Element.Methods.fire.methodize(),  observe:       Element.Methods.observe.methodize(),  stopObserving: Element.Methods.stopObserving.methodize()});(function() {  /* Support for the DOMContentLoaded event is based on work by Dan Webb,     Matthias Miller, Dean Edwards and John Resig. */  var timer, fired = false;  function fireContentLoadedEvent() {    if (fired) return;    if (timer) window.clearInterval(timer);    document.fire("dom:loaded");    fired = true;  }  if (document.addEventListener) {    if (Prototype.Browser.WebKit) {      timer = window.setInterval(function() {        if (/loaded|complete/.test(document.readyState))          fireContentLoadedEvent();      }, 0);      Event.observe(window, "load", fireContentLoadedEvent);    } else {      document.addEventListener("DOMContentLoaded",        fireContentLoadedEvent, false);    }  } else {    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");    $("__onDOMContentLoaded").onreadystatechange = function() {      if (this.readyState == "complete") {        this.onreadystatechange = null;        fireContentLoadedEvent();      }    };  }})();/*------------------------------- DEPRECATED -------------------------------*/Hash.toQueryString = Object.toQueryString;var Toggle = { display: Element.toggle };Element.Methods.childOf = Element.Methods.descendantOf;var Insertion = {  Before: function(element, content) {    return Element.insert(element, {before:content});  },  Top: function(element, content) {    return Element.insert(element, {top:content});  },  Bottom: function(element, content) {    return Element.insert(element, {bottom:content});  },  After: function(element, content) {    return Element.insert(element, {after:content});  }};var $continue = new Error('"throw $continue" is deprecated, use "return" instead');// This should be moved to script.aculo.us; notice the deprecated methods// further below, that map to the newer Element methods.var Position = {  // set to true if needed, warning: firefox performance problems  // NOT neeeded for page scrolling, only if draggable contained in  // scrollable elements  includeScrollOffsets: false,  // must be called before calling withinIncludingScrolloffset, every time the  // page is scrolled  prepare: function() {    this.deltaX =  window.pageXOffset                || document.documentElement.scrollLeft                || document.body.scrollLeft                || 0;    this.deltaY =  window.pageYOffset                || document.documentElement.scrollTop                || document.body.scrollTop                || 0;  },  // caches x/y coordinate pair to use with overlap  within: function(element, x, y) {    if (this.includeScrollOffsets)      return this.withinIncludingScrolloffsets(element, x, y);    this.xcomp = x;    this.ycomp = y;    this.offset = Element.cumulativeOffset(element);    return (y >= this.offset[1] &&            y <  this.offset[1] + element.offsetHeight &&            x >= this.offset[0] &&            x <  this.offset[0] + element.offsetWidth);  },  withinIncludingScrolloffsets: function(element, x, y) {    var offsetcache = Element.cumulativeScrollOffset(element);    this.xcomp = x + offsetcache[0] - this.deltaX;    this.ycomp = y + offsetcache[1] - this.deltaY;    this.offset = Element.cumulativeOffset(element);    return (this.ycomp >= this.offset[1] &&            this.ycomp <  this.offset[1] + element.offsetHeight &&            this.xcomp >= this.offset[0] &&            this.xcomp <  this.offset[0] + element.offsetWidth);  },  // within must be called directly before  overlap: function(mode, element) {    if (!mode) return 0;    if (mode == 'vertical')      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /        element.offsetHeight;    if (mode == 'horizontal')      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /        element.offsetWidth;  },  // Deprecation layer -- use newer Element methods now (1.5.2).  cumulativeOffset: Element.Methods.cumulativeOffset,  positionedOffset: Element.Methods.positionedOffset,  absolutize: function(element) {    Position.prepare();    return Element.absolutize(element);  },  relativize: function(element) {    Position.prepare();    return Element.relativize(element);  },  realOffset: Element.Methods.cumulativeScrollOffset,  offsetParent: Element.Methods.getOffsetParent,  page: Element.Methods.viewportOffset,  clone: function(source, target, options) {    options = options || { };    return Element.clonePosition(target, source, options);  }};/*--------------------------------------------------------------------------*/if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){  function iter(name) {    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";  }  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?  function(element, className) {    className = className.toString().strip();    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];  } : function(element, className) {    className = className.toString().strip();    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);    if (!classNames && !className) return elements;    var nodes = $(element).getElementsByTagName('*');    className = ' ' + className + ' ';    for (var i = 0, child, cn; child = nodes[i]; i++) {      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||          (classNames && classNames.all(function(name) {            return !name.toString().blank() && cn.include(' ' + name + ' ');          }))))        elements.push(Element.extend(child));    }    return elements;  };  return function(className, parentElement) {    return $(parentElement || document.body).getElementsByClassName(className);  };}(Element.Methods);/*--------------------------------------------------------------------------*/Element.ClassNames = Class.create();Element.ClassNames.prototype = {  initialize: function(element) {    this.element = $(element);  },  _each: function(iterator) {    this.element.className.split(/\s+/).select(function(name) {      return name.length > 0;    })._each(iterator);  },  set: function(className) {    this.element.className = className;  },  add: function(classNameToAdd) {    if (this.include(classNameToAdd)) return;    this.set($A(this).concat(classNameToAdd).join(' '));  },  remove: function(classNameToRemove) {    if (!this.include(classNameToRemove)) return;    this.set($A(this).without(classNameToRemove).join(' '));  },  toString: function() {    return $A(this).join(' ');  }};Object.extend(Element.ClassNames.prototype, Enumerable);/*--------------------------------------------------------------------------*/Element.addMethods();

String.prototype.parseColor = function() { var color = '#'; if (this.slice(0,4) == 'rgb(') { var cols = this.slice(4,this.length-1).split(','); var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);} else { if (this.slice(0,1) == '#') { if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); if (this.length==7) color = this.toLowerCase();}}return (color.length==7 ? color : (arguments[0] || this));}; Element.collectTextNodes = function(element) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue :(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));}).flatten().join('');}; Element.collectTextNodesIgnoreClass = function(element, className) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue :((node.hasChildNodes() && !Element.hasClassName(node,className)) ?Element.collectTextNodesIgnoreClass(node, className) : ''));}).flatten().join('');}; Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({fontSize: (percent/100) + 'em'}); if (Prototype.Browser.WebKit) window.scrollBy(0,0); return element;}; Element.getInlineOpacity = function(element){ return $(element).style.opacity || '';}; Element.forceRerendering = function(element) { try { element = $(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n);} catch(e) { }}; var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate'}, Transitions: { linear: Prototype.K, sinoidal: function(pos) { return (-Math.cos(pos*Math.PI)/2) + 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 ( ((pos % (1/pulses)) * pulses).round() == 0 ?((pos * pulses * 2) - (pos * pulses * 2).floor()) :1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) );}, spring: function(pos) { return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));}, none: function(pos) { return 0;}, full: function(pos) { return 1;}}, DefaultOptions: { duration: 1.0, fps: 100, sync: false, from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel'}, tagifyText: function(element) { var tagifyStyle = 'position:relative'; if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { if (child.nodeType==3) { child.nodeValue.toArray().each( function(character) { element.insertBefore( new Element('span', {style: tagifyStyle}).update( character == ' ' ? String.fromCharCode(160) : character), child);}); Element.remove(child);}});}, multiple: function(element, effect) { var elements; if (((typeof element == 'object') || Object.isFunction(element)) &&(element.length))elements = element; elseelements = $(element).childNodes; var options = Object.extend({ speed: 0.1, delay: 0.0}, arguments[2] || { }); var masterDelay = options.delay; $A(elements).each( function(element, index) { new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));});}, PAIRS: { 'slide': ['SlideDown','SlideUp'], 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade']}, toggle: function(element, effect) { element = $(element); effect = (effect || 'appear').toLowerCase(); var options = Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }}, arguments[2] || { }); Effect[element.visible() ?Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);}}; Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; Effect.ScopedQueue = Class.create(Enumerable, { initialize: function() { this.effects = []; this.interval = null;}, _each: function(iterator) { this.effects._each(iterator);}, add: function(effect) { var timestamp = new Date().getTime(); var position = Object.isString(effect.options.queue) ?effect.options.queue : effect.options.queue.position; switch(position) { case 'front':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':timestamp = this.effects.pluck('finishOn').max() || timestamp; break;}effect.startOn += timestamp; effect.finishOn += timestamp; if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))this.effects.push(effect); if (!this.interval)this.interval = setInterval(this.loop.bind(this), 15);}, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e==effect }); if (this.effects.length == 0) { clearInterval(this.interval); this.interval = null;}}, loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i<len;i++)this.effects[i] && this.effects[i].loop(timePos);}}); Effect.Queues = { instances: $H(), get: function(queueName) { if (!Object.isString(queueName)) return queueName; return this.instances.get(queueName) || this.instances.set(queueName, new Effect.ScopedQueue());}}; Effect.Queue = Effect.Queues.get('global'); Effect.Base = Class.create({ position: null, start: function(options) { function codeForEvent(options,eventName){ return ( (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + (options[eventName] ? 'this.options.'+eventName+'(this);' : '') );}if (options && options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); this.currentFrame = 0; this.state = 'idle'; this.startOn = this.options.delay*1000; this.finishOn = this.startOn+(this.options.duration*1000); this.fromToDelta = this.options.to-this.options.from; this.totalTime = this.finishOn-this.startOn; this.totalFrames = this.options.fps*this.options.duration; eval('this.render = function(pos){ '+ 'if (this.state=="idle"){this.state="running";'+ codeForEvent(this.options,'beforeSetup')+ (this.setup ? 'this.setup();':'')+ codeForEvent(this.options,'afterSetup')+ '};if (this.state=="running"){'+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ 'this.position=pos;'+ codeForEvent(this.options,'beforeUpdate')+ (this.update ? 'this.update(pos);':'')+ codeForEvent(this.options,'afterUpdate')+ '}}'); this.event('beforeStart'); if (!this.options.sync)Effect.Queues.get(Object.isString(this.options.queue) ?'global' : this.options.queue.scope).add(this);}, loop: function(timePos) { if (timePos >= this.startOn) { if (timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if (this.finish) this.finish(); this.event('afterFinish'); return;}var pos = (timePos - this.startOn) / this.totalTime, frame = (pos * this.totalFrames).round(); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame;}}}, cancel: function() { if (!this.options.sync)Effect.Queues.get(Object.isString(this.options.queue) ?'global' : this.options.queue.scope).remove(this); this.state = 'finished';}, event: function(eventName) { if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if (this.options[eventName]) this.options[eventName](this);}, inspect: function() { var data = $H(); for(property in this)if (!Object.isFunction(this[property])) data.set(property, this[property]); return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';}}); Effect.Parallel = Class.create(Effect.Base, { initialize: function(effects) { this.effects = effects || []; this.start(arguments[1]);}, update: function(position) { this.effects.invoke('render', position);}, finish: function(position) { this.effects.each( function(effect) { effect.render(1.0); effect.cancel(); effect.event('beforeFinish'); if (effect.finish) effect.finish(position); effect.event('afterFinish');});}}); Effect.Tween = Class.create(Effect.Base, { initialize: function(object, from, to) { object = Object.isString(object) ? $(object) : object; var args = $A(arguments), method = args.last(), options = args.length == 5 ? args[3] : null; this.method = Object.isFunction(method) ? method.bind(object) :Object.isFunction(object[method]) ? object[method].bind(object) :function(value) { object[method] = value }; this.start(Object.extend({ from: from, to: to }, options || { }));}, update: function(position) { this.method(position);}}); Effect.Event = Class.create(Effect.Base, { initialize: function() { this.start(Object.extend({ duration: 0 }, arguments[0] || { }));}, update: Prototype.emptyFunction}); Effect.Opacity = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, to: 1.0}, arguments[1] || { }); this.start(options);}, update: function(position) { this.element.setOpacity(position);}}); Effect.Move = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, mode: 'relative'}, arguments[1] || { }); this.start(options);}, setup: function() { this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if (this.options.mode == 'absolute') { this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop;}}, update: function(position) { this.element.setStyle({ left: (this.options.x * position + this.originalLeft).round() + 'px', top: (this.options.y * position + this.originalTop).round() + 'px'});}}); Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));}; Effect.Scale = Class.create(Effect.Base, { initialize: function(element, percent) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', scaleFrom: 100.0, scaleTo: percent}, arguments[2] || { }); this.start(options);}, setup: function() { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = this.element.getStyle('position'); this.originalStyle = { }; ['top','left','width','height','fontSize'].each( function(k) { this.originalStyle[k] = this.element.style[k];}.bind(this)); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; ['em','px','%','pt'].each( function(fontSizeType) { if (fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType;}}.bind(this)); this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; this.dims = null; if (this.options.scaleMode=='box')this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if (/^content/.test(this.options.scaleMode))this.dims = [this.element.scrollHeight, this.element.scrollWidth]; if (!this.dims)this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth];}, update: function(position) { var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); if (this.options.scaleContent && this.fontSize)this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);}, finish: function(position) { if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);}, setDimensions: function(height, width) { var d = { }; if (this.options.scaleX) d.width = width.round() + 'px'; if (this.options.scaleY) d.height = height.round() + 'px'; if (this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; if (this.elementPositioning == 'absolute') { if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';} else { if (this.options.scaleY) d.top = -topd + 'px'; if (this.options.scaleX) d.left = -leftd + 'px';}}this.element.setStyle(d);}}); Effect.Highlight = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); this.start(options);}, setup: function() { if (this.element.getStyle('display')=='none') { this.cancel(); return;}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'); this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));}, update: function(position) { this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart());}.bind(this)) });}, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor}));}}); Effect.ScrollTo = function(element) { var options = arguments[1] || { }, scrollOffsets = document.viewport.getScrollOffsets(), elementOffsets = $(element).cumulativeOffset(), max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); if (options.offset) elementOffsets[1] += options.offset; return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1] > max ? max : elementOffsets[1], options, function(p){ scrollTo(scrollOffsets.left, p.round()) } );}; 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, afterFinishInternal: function(effect) { effect.element.forceRerendering();}, beforeSetup: function(effect) { effect.element.setOpacity(effect.options.from).show();}}, arguments[1] || { }); return new Effect.Opacity(element,options);}; Effect.Puff = function(element) { element = $(element); var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height}; return new Effect.Parallel( [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { Position.absolutize(effect.effects[0].element)}, afterFinishInternal: function(effect) { effect.effects[0].element.hide().setStyle(oldStyle);}}, arguments[1] || { }) );}; Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { effect.element.hide().undoClipping();}}, arguments[1] || { }) );}; Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makeClipping().setStyle({height: '0px'}).show();}, afterFinishInternal: function(effect) { effect.element.undoClipping();}}, arguments[1] || { }));}; Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, afterFinishInternal: function(effect) { new Effect.Scale(effect.element, 1, { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makePositioned().makeClipping();}, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});}})}}, arguments[1] || { }));}; Effect.DropOut = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left'), opacity: element.getInlineOpacity() }; return new Effect.Parallel( [ new Effect.Move(element, {x: 0, y: 100, sync: true }), new Effect.Opacity(element, { sync: true, to: 0.0 }) ], Object.extend( { duration: 0.5, beforeSetup: function(effect) { effect.effects[0].element.makePositioned();}, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);}}, arguments[1] || { }));}; Effect.Shake = function(element) { element = $(element); var options = Object.extend({ distance: 20, duration: 0.5}, arguments[1] || {}); var distance = parseFloat(options.distance); var split = parseFloat(options.duration) / 10.0; var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle);}}) }}) }}) }}) }}) }});}; Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().setStyle({height: '0px'}).show();}, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom:(effect.dims[0] - effect.element.clientHeight) + 'px' });}, afterFinishInternal: function(effect) { effect.element.undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});}}, arguments[1] || { }) );}; Effect.SlideUp = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().show();}, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom:(effect.dims[0] - effect.element.clientHeight) + 'px' });}, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});}}, arguments[1] || { }) );}; 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(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ style: { }}, arguments[1] || { }); if (!Object.isString(options.style)) this.style = $H(options.style); else { if (options.style.include(':'))this.style = options.style.parseStyle(); else { this.element.addClassName(options.style); this.style = $H(this.element.getStyles()); this.element.removeClassName(options.style); var css = this.element.getStyles(); this.style = this.style.reject(function(style) { return style.value == css[style.key];}); options.afterFinishInternal = function(effect) { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { effect.element.style[transform.style] = '';});}}}this.start(options);}, setup: function(){ function parseColor(color){ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; color = color.parseColor(); return $R(0,2).map(function(i){ return parseInt( color.slice(i*2+1,i*2+3), 16 )});}this.transforms = this.style.map(function(pair){ var property = pair[0], value = pair[1], unit = null; if (value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color';} else if (property == 'opacity') { value = parseFloat(value); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))this.element.setStyle({zoom: 1});} else if (Element.CSS_LENGTH.test(value)) { var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); unit = (components.length == 3) ? components[2] : null;}var originalValue = this.element.getStyle(property); return { style: property.camelize(), originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit};}.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || ( transform.unit != 'color' &&(isNaN(transform.originalValue) || isNaN(transform.targetValue))))});}, update: function(position) { var style = { }, transform, i = this.transforms.length; while(i--)style[(transform = this.transforms[i]).style] = transform.unit=='color' ? '#'+ (Math.round(transform.originalValue[0]+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + (Math.round(transform.originalValue[1]+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + (Math.round(transform.originalValue[2]+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :(transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? '' : transform.unit); this.element.setStyle(style, true);}}); Effect.Transform = Class.create({ initialize: function(tracks){ this.tracks = []; this.options = arguments[1] || { }; this.addTracks(tracks);}, addTracks: function(tracks){ tracks.each(function(track){ track = $H(track); var data = track.values().first(); this.tracks.push($H({ ids: track.keys().first(), effect: Effect.Morph, options: { style: data }}));}.bind(this)); return this;}, play: function(){ return new Effect.Parallel( this.tracks.map(function(track){ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); var elements = [$(ids) || $$(ids)].flatten(); return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });}).flatten(), this.options );}}); Element.CSS_PROPERTIES = $w( 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex'); Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.__parseStyleElement = document.createElement('div'); String.prototype.parseStyle = function(){ var style, styleRules = $H(); if (Prototype.Browser.WebKit)style = new Element('div',{style:this}).style; else { String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; style = String.__parseStyleElement.childNodes[0].style;}Element.CSS_PROPERTIES.each(function(property){ if (style[property]) styleRules.set(property, style[property]);}); if (Prototype.Browser.IE && this.include('opacity'))styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); return styleRules;}; if (document.defaultView && document.defaultView.getComputedStyle) { Element.getStyles = function(element) { var css = document.defaultView.getComputedStyle($(element), null); return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { styles[property] = css[property]; return styles;});};} else { Element.getStyles = function(element) { element = $(element); var css = element.currentStyle, styles; styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) { hash.set(property, css[property]); return hash;}); if (!styles.opacity) styles.set('opacity', element.getOpacity()); return styles;};}; Effect.Methods = { morph: function(element, style) { element = $(element); new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); return element;}, visualEffect: function(element, effect, options) { element = $(element)var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); new Effect[klass](element, options); return element;}, highlight: function(element, options) { element = $(element); new Effect.Highlight(element, options); return element;}}; $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 'pulsate shake puff squish switchOff dropOut').each( function(effect) { Effect.Methods[effect] = function(element, options){ element = $(element); Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); return element;}} ); $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( function(f) { Effect.Methods[f] = Element[f];} ); Element.addMethods(Effect.Methods); 

// 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 : 20,
				width : 20
			},
			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 : 10,
			EOLASFix : 'swf,wmv,fla,flv',
			overlay : {
				opacity : 0.7,
				image : '/images/black.png',
				presetImage : '/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" >close</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="/images/ajax-loading.gif" alt="loading" />'+
								'<span>Loading or <a href="javascript: myLightWindow.deactivate();">Cancel</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 : 'get',
			hideFlash : false,
			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);	
	},
	//
	//  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+'px'
			});			
		} else {
			overlay.setStyle({
				opacity: this.options.overlay.opacity,
				backgroundImage: 'url('+this.options.overlay.image+')',
				backgroundRepeat: 'repeat',
				height: this.pageDimensions.height+'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;
			
		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();
	},
	//
	//  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();
	}
}

/*-----------------------------------------------------------------------------------------------*/

Event.observe(window, 'load', lightwindowInit, false);

//
//	Set up all of our links
//
var myLightWindow = null;
function lightwindowInit() {
	myLightWindow = new lightwindow();
}

// script.aculo.us slider.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007

// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs 
//
// 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/

if (!Control) var Control = { };

// options:
//  axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider = Class.create({
  initialize: function(handle, track, options) {
    var slider = this;
    
    if (Object.isArray(handle)) {
      this.handles = handle.collect( function(e) { return $(e) });
    } else {
      this.handles = [$(handle)];
    }
    
    this.track   = $(track);
    this.options = options || { };

    this.axis      = this.options.axis || 'horizontal';
    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.range     = this.options.range || $R(0,1);
    
    this.value     = 0; // assure backwards compat
    this.values    = this.handles.map( function() { return 0 });
    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
    this.options.startSpan = $(this.options.startSpan || null);
    this.options.endSpan   = $(this.options.endSpan || null);

    this.restricted = this.options.restricted || false;

    this.maximum   = this.options.maximum || this.range.end;
    this.minimum   = this.options.minimum || this.range.start;

    // Will be used to align the handle onto the track, if necessary
    this.alignX = parseInt(this.options.alignX || '0');
    this.alignY = parseInt(this.options.alignY || '0');
    
    this.trackLength = this.maximumOffset() - this.minimumOffset();

    this.handleLength = this.isVertical() ? 
      (this.handles[0].offsetHeight != 0 ? 
        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 
      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 
        this.handles[0].style.width.replace(/px$/,""));

    this.active   = false;
    this.dragging = false;
    this.disabled = false;

    if (this.options.disabled) this.setDisabled();

    // Allowed values array
    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
    if (this.allowedValues) {
      this.minimum = this.allowedValues.min();
      this.maximum = this.allowedValues.max();
    }

    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
    this.eventMouseMove = this.update.bindAsEventListener(this);

    // Initialize handles in reverse (make sure first handle is active)
    this.handles.each( function(h,i) {
      i = slider.handles.length-1-i;
      slider.setValue(parseFloat(
        (Object.isArray(slider.options.sliderValue) ? 
          slider.options.sliderValue[i] : slider.options.sliderValue) || 
         slider.range.start), i);
      h.makePositioned().observe("mousedown", slider.eventMouseDown);
    });
    
    this.track.observe("mousedown", this.eventMouseDown);
    document.observe("mouseup", this.eventMouseUp);
    document.observe("mousemove", this.eventMouseMove);
    
    this.initialized = true;
  },
  dispose: function() {
    var slider = this;    
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },  
  getNearestValue: function(value){
    if (this.allowedValues){
      if (value >= this.allowedValues.max()) return(this.allowedValues.max());
      if (value <= this.allowedValues.min()) return(this.allowedValues.min());
      
      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if (currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        } 
      });
      return newValue;
    }
    if (value > this.range.end) return this.range.end;
    if (value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if (!this.active) {
      this.activeHandleIdx = handleIdx || 0;
      this.activeHandle    = this.handles[this.activeHandleIdx];
      this.updateStyles();
    }
    handleIdx = handleIdx || this.activeHandleIdx || 0;
    if (this.initialized && this.restricted) {
      if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
        sliderValue = this.values[handleIdx-1];
      if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1];
    }
    sliderValue = this.getNearestValue(sliderValue);
    this.values[handleIdx] = sliderValue;
    this.value = this.values[0]; // assure backwards compat
    
    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
      this.translateToPx(sliderValue);
    
    this.drawSpans();
    if (!this.dragging || !this.event) this.updateFinished();
  },
  setValueBy: function(delta, handleIdx) {
    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
      handleIdx || this.activeHandleIdx || 0);
  },
  translateToPx: function(value) {
    return Math.round(
      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
      (value - this.range.start)) + "px";
  },
  translateToValue: function(offset) {
    return ((offset/(this.trackLength-this.handleLength) * 
      (this.range.end-this.range.start)) + this.range.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K); 
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffset: function(){
    return(this.isVertical() ? this.alignY : this.alignX);
  },
  maximumOffset: function(){
    return(this.isVertical() ? 
      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
        this.track.style.height.replace(/px$/,"")) - this.alignY : 
      (this.track.offsetWidth != 0 ? this.track.offsetWidth : 
        this.track.style.width.replace(/px$/,"")) - this.alignX);
  },  
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if (this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if (this.options.startSpan)
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if (this.options.endSpan)
      this.setSpan(this.options.endSpan, 
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if (this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if (Event.isLeftClick(event)) {
      if (!this.disabled){
        this.active = true;
        
        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if (track==this.track) {
          var offsets  = Position.cumulativeOffset(this.track); 
          this.event = event;
          this.setValue(this.translateToValue( 
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
            handle = handle.parentNode;
            
          if (this.handles.indexOf(handle)!=-1) {
            this.activeHandle    = handle;
            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
            this.updateStyles();
            
            var offsets  = Position.cumulativeOffset(this.activeHandle);
            this.offsetX = (pointer[0] - offsets[0]);
            this.offsetY = (pointer[1] - offsets[1]);
          }
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if (this.active) {
      if (!this.dragging) this.dragging = true;
      this.draw(event);
      if (Prototype.Browser.WebKit) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = Position.cumulativeOffset(this.track);
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
    if (this.initialized && this.options.onSlide)
      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  },
  endDrag: function(event) {
    if (this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
  },  
  finishDrag: function(event, success) {
    this.active = false;
    this.dragging = false;
    this.updateFinished();
  },
  updateFinished: function() {
    if (this.initialized && this.options.onChange) 
      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
    this.event = null;
  }
});


var enableCache = true; var jsCache = new Array(); var dynamicContent_ajaxObjects = new Array(); function ajax_showContent(divId,ajaxIndex,url){ document.getElementById(divId).innerHTML = dynamicContent_ajaxObjects[ajaxIndex].response; if(enableCache){ jsCache[url] = dynamicContent_ajaxObjects[ajaxIndex].response;}dynamicContent_ajaxObjects[ajaxIndex] = false;}function ajax_loadContent(divId,url){ if(enableCache && jsCache[url]){ document.getElementById(divId).innerHTML = jsCache[url]; return;}var ajaxIndex = dynamicContent_ajaxObjects.length; document.getElementById(divId).innerHTML = '<img src="../images/loading.gif"> Loading content - please wait'; dynamicContent_ajaxObjects[ajaxIndex] = new sack(); if(url.indexOf('?')>=0){ dynamicContent_ajaxObjects[ajaxIndex].method='GET'; var string = url.substring(url.indexOf('?')); url = url.replace(string,''); string = string.replace('?',''); var items = string.split(/&/g); for(var no=0;no<items.length;no++){ var tokens = items[no].split('='); if(tokens.length==2){ dynamicContent_ajaxObjects[ajaxIndex].setVar(tokens[0],tokens[1]);}}url = url.replace(string,'');}dynamicContent_ajaxObjects[ajaxIndex].requestFile = url; dynamicContent_ajaxObjects[ajaxIndex].onCompletion = function(){ ajax_showContent(divId,ajaxIndex,url);}; dynamicContent_ajaxObjects[ajaxIndex].runAJAX();}

function sack(file){ this.AjaxFailedAlert = "Your browser does not support the enhanced functionality of this website, and therefore you will have an experience that differs from the intended one.\n"; this.requestFile = file; this.method = "POST"; this.URLString = ""; this.encodeURIString = true; this.execute = false; this.onLoading = function() { }; this.onLoaded = function() { }; this.onInteractive = function() { }; this.onCompletion = function() { }; this.createAJAX = function() { try { this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) { try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (err) { this.xmlhttp = null;}}if(!this.xmlhttp && typeof XMLHttpRequest != "undefined")this.xmlhttp = new XMLHttpRequest(); if (!this.xmlhttp){ this.failed = true;}}; this.setVar = function(name, value){ if (this.URLString.length < 3){ this.URLString = name + "=" + value;} else { this.URLString += "&" + name + "=" + value;}}this.encVar = function(name, value){ var varString = encodeURIComponent(name) + "=" + encodeURIComponent(value); return varString;}this.encodeURLString = function(string){ varArray = string.split('&'); for (i = 0; i < varArray.length; i++){ urlVars = varArray[i].split('='); if (urlVars[0].indexOf('amp;') != -1){ urlVars[0] = urlVars[0].substring(4);}varArray[i] = this.encVar(urlVars[0],urlVars[1]);}return varArray.join('&');}this.runResponse = function(){ eval(this.response);}this.runAJAX = function(urlstring){ this.responseStatus = new Array(2); if(this.failed && this.AjaxFailedAlert){ alert(this.AjaxFailedAlert);} else { if (urlstring){ if (this.URLString.length){ this.URLString = this.URLString + "&" + urlstring;} else { this.URLString = urlstring;}}if (this.encodeURIString){ var timeval = new Date().getTime(); this.URLString = this.encodeURLString(this.URLString); this.setVar("rndval", timeval);}if (this.element) { this.elementObj = document.getElementById(this.element);}if (this.xmlhttp) { var self = this; if (this.method == "GET") { var totalurlstring = this.requestFile + "?" + this.URLString; this.xmlhttp.open(this.method, totalurlstring, true);} else { this.xmlhttp.open(this.method, this.requestFile, true);}if (this.method == "POST"){ try { this.xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded')} catch (e) {}}this.xmlhttp.send(this.URLString); this.xmlhttp.onreadystatechange = function() { switch (self.xmlhttp.readyState){ case 1:self.onLoading(); break; case 2:self.onLoaded(); break; case 3:self.onInteractive(); break; case 4:self.response = self.xmlhttp.responseText; self.responseXML = self.xmlhttp.responseXML; self.responseStatus[0] = self.xmlhttp.status; self.responseStatus[1] = self.xmlhttp.statusText; self.onCompletion(); if(self.execute){ self.runResponse();}if (self.elementObj) { var elemNodeName = self.elementObj.nodeName; elemNodeName.toLowerCase(); if (elemNodeName == "input" || elemNodeName == "select" || elemNodeName == "option" || elemNodeName == "textarea"){ self.elementObj.value = self.response;} else { self.elementObj.innerHTML = self.response;}}self.URLString = ""; break;}};}}}; this.createAJAX();}

var x_offset_tooltip = 5; var y_offset_tooltip = 0; var ajax_tooltipObj = false; var ajax_tooltipObj_iframe = false; var ajax_tooltip_MSIE = false; if(navigator.userAgent.indexOf('MSIE')>=0)ajax_tooltip_MSIE=true; function ajax_showTooltip(externalFile,inputObj){ if(!ajax_tooltipObj){ ajax_tooltipObj = document.createElement('DIV'); ajax_tooltipObj.style.position = 'absolute'; ajax_tooltipObj.id = 'ajax_tooltipObj'; document.body.appendChild(ajax_tooltipObj); var leftDiv = document.createElement('DIV'); leftDiv.className='ajax_tooltip_arrow'; leftDiv.id = 'ajax_tooltip_arrow'; ajax_tooltipObj.appendChild(leftDiv); var contentDiv = document.createElement('DIV'); contentDiv.className = 'ajax_tooltip_content'; ajax_tooltipObj.appendChild(contentDiv); contentDiv.id = 'ajax_tooltip_content'; if(ajax_tooltip_MSIE){ ajax_tooltipObj_iframe = document.createElement('<IFRAME frameborder="0">'); ajax_tooltipObj_iframe.style.position = 'absolute'; ajax_tooltipObj_iframe.border='0'; ajax_tooltipObj_iframe.frameborder=0; ajax_tooltipObj_iframe.style.backgroundColor='#FFF'; ajax_tooltipObj_iframe.src = 'about:blank'; contentDiv.appendChild(ajax_tooltipObj_iframe); ajax_tooltipObj_iframe.style.left = '0px'; ajax_tooltipObj_iframe.style.top = '0px';}}ajax_tooltipObj.style.display='block'; ajax_loadContent('ajax_tooltip_content',externalFile); if(ajax_tooltip_MSIE){ ajax_tooltipObj_iframe.style.width = ajax_tooltipObj.clientWidth + 'px'; ajax_tooltipObj_iframe.style.height = ajax_tooltipObj.clientHeight + 'px';}ajax_positionTooltip(inputObj);}function ajax_positionTooltip(inputObj){ var leftPos = (ajaxTooltip_getLeftPos(inputObj) + inputObj.offsetWidth); var topPos = ajaxTooltip_getTopPos(inputObj); var tooltipWidth = document.getElementById('ajax_tooltip_content').offsetWidth + document.getElementById('ajax_tooltip_arrow').offsetWidth; ajax_tooltipObj.style.left = leftPos + 'px'; ajax_tooltipObj.style.top = topPos + 'px';}function ajax_hideTooltip(){ ajax_tooltipObj.style.display='none';}function ajaxTooltip_getTopPos(inputObj){ var returnValue = inputObj.offsetTop; while((inputObj = inputObj.offsetParent) != null){ if(inputObj.tagName!='HTML')returnValue += inputObj.offsetTop;}return returnValue;}function ajaxTooltip_getLeftPos(inputObj){ var returnValue = inputObj.offsetLeft; while((inputObj = inputObj.offsetParent) != null){ if(inputObj.tagName!='HTML')returnValue += inputObj.offsetLeft;}return returnValue;}function pop_close(){ var pop_up=document.getElementById("lightbox1"); var over=document.getElementById("overlay1"); pop_up.style.visibility = "hidden"; over.style.visibility = "hidden";}function startLoading(div) { document.getElementById("lightwindow_loading").style.visibility = "visible";}function finishLoading(div) { setTimeout("Effect.toggle('lightwindow_loading');", 1000);}function scrollload(){ var slider3 = new Control.Slider('handle3', 'track3', { axis: 'vertical', onSlide: function(v) { scrollVertical(v, $('scrollable2'), slider3);}, onChange: function(v) { scrollVertical(v, $('scrollable2'), slider3);}}); function scrollVertical(value, element, slider) { element.scrollTop = Math.round(value/slider.maximum*(element.scrollHeight-element.offsetHeight));}function scrollHorizontal(value, element, slider) { element.scrollLeft = Math.round(value/slider.maximum*(element.scrollWidth-element.offsetWidth));}if ($('scrollable2').scrollHeight <= $('scrollable2').offsetHeight) { slider3.setDisabled(); $('wrap3').hide();}}function open_pop(page,id){ var pop_up=document.getElementById("lightbox1"); var over=document.getElementById("overlay1"); pop_up.innerHTML=''; over.style.height=3*(document.documentElement.clientHeight)+'px'; pop_up.style.visibility = "visible"; over.style.visibility = "visible"; pop_up.innerHTML="<img src='http://www.bellsbeershop.com/images/ajax-loader.gif'>"new Ajax.Updater('lightbox1', page, {method: 'post', postBody:'content='+ id +'',evalScripts:true});}

/* * GMapEZ -- Turn specially-marked HTML into Google Maps * Copyright (C) July 2005 - May 2006 by Chris Houser <chouser@bluweb.com> * * This code is licensed under the GNU General Public License (GPL) * * If you use this code on a web page, please include on that page a * link to http://bluweb.com/chouser/gmapez/ -- this is a request, not * a requirement.  Thanks. */(function(){  var startdate = new Date();  // configuration -- if you're using your own copy of gmapez.js, you  // may want to modify these:  var overlaysPerStep = 25;  var imgBase = 'http://n01se.net/gmapez/';  function loadfunc() {    if( ! GBrowserIsCompatible() ) {      if( document.getElementsByTagName ) {        // Find all divs marked as GMapEZ        var divs = document.getElementsByTagName( 'div' );        for( var i = 0; i < divs.length; ++i ) {          var div = divs[ i ];          if( div.className.indexOf( 'GMapEZ' ) > -1 ) {            div.innerHTML =  [              "<div>This map cannot be displayed.  The site's key may be ",              "incorrect, or your browser may not compatible (see if ",              "your browser is listed ",              '<a href="http://maps.google.com/support/bin/answer.py?answer=16532">here</a>).</div>',              '<div class="firefoxref"><iframe src="http://pagead2.googlesyndication.com/cpa/ads?client=ca-pub-1237864095616304&amp;cpa_choice=CAAQyaj8zwEaCIwcWMzeycafKMu293M&amp;oe=UTF-8&amp;dt=1148266564041&amp;lmt=1148266562&amp;format=180x60_as_rimg&amp;output=html&amp;region=_google_cpa_region_&amp;cc=100&amp;u_h=1024&amp;u_w=1280&amp;u_ah=1050&amp;u_aw=1400&amp;u_cd=24&amp;u_tz=-240&amp;u_his=1&amp;u_java=true&amp;u_nplug=11&amp;u_nmime=133" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" frameborder="0" height="60" scrolling="no" width="180"></iframe></div>'              ].join('\n');            div.style.visibility = 'visible';            div.style.padding = '0.3em';            div.style.background = '#eee';            div.style.overflow = 'auto';          }        }      }      else {        alert( [          'Your browser is not capable of displaying',          'Google Maps on this page. Try using Firefox:',          'http://getfirefox.com/' ].join('\n') );      }      return;    }    addOnUnload( GUnload );    function GSmallMapTypeControl() {      GMapTypeControl.call( this, true );    }    GSmallMapTypeControl.prototype = new GMapTypeControl();    GSmallMapTypeControl.prototype.constructor = GSmallMapTypeControl;    window.GSmallMapTypeControl = GSmallMapTypeControl;    var CtrlTable = {      'GLargeMapControl': true,      'GSmallMapControl': true,      'GSmallZoomControl': true,      'GSmallMapTypeControl': true,      'GMapTypeControl': true,      'GScaleControl': true    };    var MapTypeTable = {      'G_MAP_TYPE' : true,      'G_SATELLITE_TYPE' : true,      'G_HYBRID_TYPE' : true,      'G_KATRINA_TYPE' : true    };    var idmarkers = {};    function markerForUrl( url ) {      var matcha = /#(.*)/.exec( url );      if( matcha )        return idmarkers[ matcha[ 1 ] ];      else        return null;    }    function wordMap( str ) {      var wmap = {};      var list = str.split(' ');      for( var j = 0; j < list.length; ++j ) {        wmap[ list[ j ] ] = true;      }      return wmap;    }    var markerOpener = {      markers: [],      addMarker: function( marker ) {        this.markers.push( marker );      },      chainOpen: function( i ) {        /*         * This is a work-around for a Google Maps bug.  If I try to open         * all the info windows at once, only the last one succeeds.         *         * Otherwise, it is equivalent to:         *   for( i = 0; i < this.markers.length; ++i )         *     this.markers[ i ].doOpen();         */        i = i || 0;        if( i < this.markers.length ) {          var onOpen = GEvent.bind(              this.markers[ i ],              "infowindowopen",              this,              function(){                GEvent.removeListener( onOpen );                this.chainOpen( i + 1 );              });          this.markers[ i ].doOpen();        }        else {          //alert('GMapEZ loadtime: ' + ( new Date() - startdate ) );        }      }    };    var laterFuncs = [];    var lastFunc = null;    function doNow() {      if( laterFuncs.length > 0 ) {        laterFuncs.shift().call();        setTimeout( doNow, 1 );      }      else {        if( lastFunc ) {          lastFunc.call();        }      }    }    function doLater( obj, func ) {      laterFuncs.push( function() { func.call( obj ); } );    }    var MiniIcon = new GIcon();    MiniIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";    MiniIcon.iconSize = new GSize(12, 20);    MiniIcon.shadowSize = new GSize(22, 20);    MiniIcon.iconAnchor = new GPoint(6, 20);    MiniIcon.infoWindowAnchor = new GPoint(5, 1);    function EZInfoMarker( ezmap, point, icon, title ) {      this.ezmap = ezmap;      this.point = point;      this.icon = icon;      this.title = title;      this.blowup = false;      this.tabs = [];      this.infoZoomOffset = undefined;      this.infoZoomLevel = undefined;      this.infoMapType = null;    }    EZInfoMarker.prototype = new GMarker( new GLatLng( 0, 0 ) );    EZInfoMarker.prototype.constructor = EZInfoMarker;    EZInfoMarker.prototype.initialize = function( map ) {      GMarker.call(          this,          this.point,          {            icon: this.icon,            clickable: ( this.tabs.length > 0 || this.blowup ),            title: this.title          });      GMarker.prototype.initialize.call( this, map );    };    EZInfoMarker.prototype.doOpen = function() {      var zoom = null;      if( this.tabs.length > 0 ) {        this.openInfoWindowTabs( this.tabs, {          maxWidth: this.ezmap.div.offsetWidth - 100 } );      }      else if( this.blowup ) {        if( this.infoZoomOffset != undefined )          zoom = this.ezmap.map.getZoom() + this.infoZoomOffset;        else if( this.infoZoomLevel != undefined )          zoom = this.infoZoomLevel;        if( zoom >= this.ezmap.map.getCurrentMapType().numZoomLevels )          zoom = this.ezmap.map.getCurrentMapType().numZoomLevels - 1;        else if( zoom < 0 )          zoom = 0;        this.showMapBlowup( { zoomLevel: zoom, mapType: this.infoMapType } );      }      else {        this.ezmap.map.closeInfoWindow();      }    };    function EZPolyline( color, weight, opacity ) {      this.points = [];      this.initialize = function( map ) {        GPolyline.call( this, this.points, color, weight, opacity );        GPolyline.prototype.initialize.call( this, map );      };    };    EZPolyline.prototype = new GPolyline();    EZPolyline.prototype.constructor = EZPolyline;    function EZMap( div, classes ) {      this.div = div;      this.classes = classes;      this.divData = null;      this.map = undefined;      this.mapType = undefined;      this.autoBounds = undefined;      this.center = undefined;      this.span = undefined;      this.explicitExtent = false;      this.overlayList = [];      this.loading = null;      this.bar = null;      this.maxstep = 0;      this.step = 0;      this.oi = 0;      this.initFrame();    }    EZMap.prototype.logWarning = function( str ) {      if( ! this.warningNode ) {        this.warningVis = false;        this.warningNode = document.createElement('ul');        this.warningNode.className = 'warnings';        this.div.appendChild( this.warningNode );        var warnBtn = document.createElement('button');        warnBtn.className = 'warnings';        warnBtn.innerHTML = 'Warnings...';        this.div.appendChild( warnBtn );        var ezmap = this;        warnBtn.onclick = function() { ezmap.toggleWarnings(); };      }      var li = document.createElement('li');      li.innerHTML = str;      this.warningNode.appendChild( li );    };    EZMap.prototype.toggleWarnings = function() {      this.warningVis = ! this.warningVis;      this.warningNode.style.display = this.warningVis ? 'block' : 'none';    };    EZMap.prototype.processMarkers = function( parentNode, polyline ) {      for( var node = parentNode.firstChild; node; node = node.nextSibling){        var lastOverlay = this.overlayList[ this.overlayList.length - 1 ];        switch( node.nodeName ) {        case 'A':          var textContent = node.innerHTML.replace( /<[^>]*>/g, '' );          var openThisMarker = /\bOPEN\b/.exec( textContent );          textContent = textContent.replace( /\bOPEN\b/, '' );          textContent = textContent.replace( /^\s*/, '' );          textContent = textContent.replace( /\s*$/, '' );          if( textContent == 'EXTENT' )            this.explicitExtent = true;          var matchll = /\Wll=([-.\d]*),([-.\d]*)/.exec( node.href );          if( matchll ) {            var lat = parseFloat( matchll[1] );            var lng = parseFloat( matchll[2] );            var point = new GLatLng( lat, lng );            if( polyline ) {              polyline.points.push( point );            }            if( textContent == 'EXTENT'                || ( ! this.explicitExtent && this.overlayList.length < 1 ) )            {              this.center = point;              var matchspn = /\Wspn=([-.\d]*),([-.\d]*)/.exec( node.href );              if( matchspn ) {                this.span = new GLatLng(                    parseFloat( matchspn[1] ),                    parseFloat( matchspn[2] ) );              }              var matchtype = /\Wt=(.)/.exec( node.href );              if( matchtype ) {                switch( matchtype[1] ) {                  case 'k': this.mapType = G_SATELLITE_TYPE; break;                  case 'h': this.mapType = G_HYBRID_TYPE; break;                }              }            }            if( textContent != 'EXTENT' ) {              if( ! this.autoBounds ) {                this.autoBounds = new GLatLngBounds( point, point );              }              else {                this.autoBounds.extend( point );              }              var iconmodel = G_DEFAULT_ICON;              var iconbase = 'marker';              var sym = null;              var color = 'ORANGE';              var matchcolor =                  /\b(ORANGE|PURPLE|YELLOW|GREEN|BLUE|RED|AQUA|WHITE|GRAY)\b/                  .exec( textContent );              if( matchcolor )                color = matchcolor[0];              var matchsym =                  /\b([0-9A-Za-z]|BLANK|HASH|DOLLAR|DOT|START|END)\b/                  .exec( textContent );              if( matchsym )                sym = matchsym[ 0 ];              var matchmini = /\bMINI\b/.exec( textContent );              if( matchmini ) {                iconmodel = MiniIcon;                iconbase = 'mini';                sym = 'BLANK';              }              if( sym || ! polyline ) {                var icon = new GIcon( iconmodel );                icon.image = [                  imgBase, 'iconEZ2/', iconbase, '-', color, '-',                  ( sym || 'DOT' ), '.png' ].join('');                var marker = new EZInfoMarker(                    this, point, icon, node.getAttribute('title') );                this.overlayList.push( marker );                idmarkers[ node.id || node.name ] = marker;                if( openThisMarker )                  markerOpener.addMarker( marker );              }            }          }          else {            this.logWarning( "No ll param for marker [" + node.innerHTML +              ":" + (node.id || node.name) + "]" );          }          break;        case 'DIV':          if( ! lastOverlay ) {            this.logWarning( "div block given before any markers" );            continue;          }          else {            var infoClasses = wordMap( node.className );            if( 'GMapEZ' in infoClasses ) {              // infoWindow blowup              lastOverlay.blowup = true;              var matchzoom = /ZOOMLEVEL([-+=]?)(\d+)/.exec( node.innerHTML );              if( matchzoom ) {                var num = parseInt( matchzoom[ 2 ] );                if( matchzoom[ 1 ] == '-' )                  lastOverlay.infoZoomOffset = num;                else if( matchzoom[ 1 ] == '+' )                  lastOverlay.infoZoomOffset = - num;                else                  lastOverlay.infoZoomLevel = num;              }              for( typeName in MapTypeTable ) {                if( typeName in infoClasses ) {                  lastOverlay.infoMapType = window[ typeName ];                  break;                }              }            }            else {              lastOverlay.tabs.push(                  new GInfoWindowTab( node.getAttribute('title'), node ));            }          }          break;        case 'LI':          this.processMarkers( node, polyline );          break;        case 'OL':          var params = { color: null, weight: null, opacity: null };          for( var word in wordMap( node.className ) ) {            var matchparam = /^(color|weight|opacity):(.*)$/.exec( word );            if( matchparam )              params[ matchparam[1] ] = matchparam[2];          }          if( params.color && ! /^#[0-9a-zA-Z]{6}$/.exec( params.color ) )            this.logWarning( 'Polyline color should be a 6-digit' +                ' hex color like "#123abc", not "' + params.color + '"' );          if( params.weight != null ) {            var w = parseInt( params.weight );            if( w < 1 || isNaN( w ) )              this.logWarning( 'Polyline weight should be an' +                  ' interger above 0, not "' + params.weight + '"' );            params.weight = w;          }          if( params.opacity ) {            var o = parseFloat( params.opacity );            if( o < 0 || o > 1 || isNaN( o ) )              this.logWarning( 'Polyline opacity should be ' +                  ' between 0 and 1, not "' + params.opacity + '"' );            params.opacity = o;          }          var newline = new EZPolyline(              params.color,              params.weight,              params.opacity );          this.overlayList.push( newline );          this.processMarkers( node, newline );          break;        case '#text':        case '#comment':          // ignore text and comments          break;        default:          this.logWarning( "Unknown or misplaced node " + node.nodeName );          break;        }      }    };    EZMap.prototype.onClick = function( overlay, point ) {      if( overlay && overlay.doOpen ) {        overlay.doOpen();      }      else if( point ) {        this.map.closeInfoWindow();      }    };    EZMap.prototype.nextStep = function( func ) {      if( this.maxstep > 0 ) {        this.bar.style.width = Math.round( this.step / this.maxstep * 100 ) + '%';      }      this.step += 1;      doLater( this, func );    };    EZMap.prototype.initFrame = function() {      this.divData = div.cloneNode( true );      this.div.innerHTML = '';      this.div.style.visibility = 'visible';      this.loading = document.createElement('div');      this.loading.className = 'loadprogress';      this.loading.style.marginTop = ( this.div.offsetHeight / 3 ) + 'px';      this.loading.innerHTML = '<div class="box"><div class="logo"></div><div class="trough"><div class="bar"></div></div></div>';      this.bar = this.loading.getElementsByTagName('div')[3];      this.div.appendChild( this.loading );      this.nextStep( this.initParse );    };    EZMap.prototype.initParse = function() {      this.processMarkers( this.divData );      this.divData = null;      this.map = new GMap2( this.div );      this.map.getContainer().appendChild( this.loading );      GEvent.bind( this.map, 'click', this, this.onClick );      // map type      if( this.overlayList.length > 1 && ! this.explicitExtent ) {        this.mapType = null;      }      for( typeName in MapTypeTable ) {        if( typeName in this.classes ) {          this.mapType = window[ typeName ];          break;        }      }      this.mapType = this.mapType || G_MAP_TYPE;      // center and zoom      var viewsize = new GSize( this.div.offsetWidth, this.div.offsetHeight );      var zoomLevel;      if( this.overlayList.length == 1 || this.explicitExtent ) {        if( this.span ) {          zoomLevel = this.mapType.getSpanZoomLevel(              this.center, this.span, viewsize );        }      }      else if( this.overlayList.length > 1 ) {        var sw = this.autoBounds.getSouthWest();        var ne = this.autoBounds.getNorthEast();        this.center = new GLatLng(          ( sw.lat() + ne.lat() ) / 2,          ( sw.lng() + ne.lng() ) / 2 );        zoomLevel = this.mapType.getBoundsZoomLevel( this.autoBounds, viewsize);      }      else {        this.center = new GLatLng( 41.075210, -85.130310 );        zoomLevel = 10;      }      // apply center, zoom, and map type      this.map.setCenter( this.center, zoomLevel, this.mapType );      this.maxstep = Math.floor( this.overlayList.length / overlaysPerStep ) + 2;      this.initOverlays();    };    EZMap.prototype.initOverlays = function() {      var steplimit = Math.min(this.overlayList.length, this.oi+overlaysPerStep);      for( ; this.oi < steplimit; ++this.oi ) {        this.map.addOverlay( this.overlayList[ this.oi ] );        this.overlayList[ this.oi ] = null;      }      if( this.oi < this.overlayList.length )        this.nextStep( this.initOverlays );      else        this.nextStep( this.initControls );    };    EZMap.prototype.initControls = function() {      for( var ctrl in CtrlTable ) {        if( ctrl in this.classes ) {          this.map.addControl( new window[ ctrl ]() );        }      }      this.nextStep( this.initLoading );    };    EZMap.prototype.initLoading = function() {      this.loading.parentNode.removeChild( this.loading );      this.loading = null;    };    // Find all divs marked as GMapEZ    var divs = document.getElementsByTagName( 'div' );    for( var i = 0; i < divs.length; ++i ) {      var div = divs[ i ];      var classes = wordMap( div.className );      if( 'GMapEZ' in classes ) {        new EZMap( div, classes );      }    }    lastFunc = function() {      // Find all anchor tags linking to GMapEZ markers      var anchors = document.getElementsByTagName( 'a' );      for( var mi = 0; mi < anchors.length; ++mi ) {        var marker = markerForUrl( anchors[ mi ].href );        if( marker )          GEvent.bindDom( anchors[ mi ], "click", marker, marker.doOpen );      }      // Examine current page location for a reference to a GMapEZ marker      var marker = markerForUrl( document.location );      if( marker )        markerOpener.addMarker( marker );      // Open all the markers we need to      markerOpener.chainOpen();    };    doNow();  }  function chainWindowFunc( funcname, newfunc ) {    var oldfunc = window[ funcname ];    if( oldfunc ) {      window[ funcname ] = function() { oldfunc(); newfunc(); };    }    else {      window[ funcname ] = newfunc;    }  }  window.addOnLoad   = function( func ) { chainWindowFunc( "onload",   func ); };  window.addOnUnload = function( func ) { chainWindowFunc( "onunload", func ); };  window.ez_preload = function() {    if( window.G_INCOMPAT ) {      // If the key failed to validate, cause all keys to appear valid      // and try again.      window.G_INCOMPAT = false;      window.GValidateKey = function(){ return true; }      GLoad();    }    addOnLoad( loadfunc );  }  var key = '';  var gmapversion = '2';  (function(){    var metas = document.getElementsByTagName( 'meta' );    var match;    for( var i = 0; i < metas.length; ++i ) {      match = /gmapkey:?(.*)/.exec( metas[ i ].name );      if( match ) {        if( ! match[ 1 ] ) {          key = metas[ i ].content;        }        else if( (new RegExp( match[ 1 ] )).exec( window.location.href ) ) {          key = metas[ i ].content;          break;        }      }      else if( metas[ i ].name == 'gmapversion' ) {        gmapversion = metas[ i ].content;      }    }  })();  document.write( [    '<script src="http://maps.google.com/maps?file=api&v='    + gmapversion + '&key=' + key    + '" type="text/javascript"></script>',    '<script type="text/javascript">',    '  ez_preload();',    '</script>',    '<style type="text/css">',    'div.GMapEZ {',    '  visibility: hidden;',    '  border: 1px #888 solid;',    '}',    'div.GMapEZ ul.warnings {',    '  position: absolute;',    '  top: 0;',    '  left: 0;',    '  margin: 0;',    '  padding-right: 0.5em;',    '  padding-left: 1.5em;',    '  display: none;',    '  border: 1px #888 solid;',    '  background: #fff;',    '  z-index: 100000000;',    '  text-align: left;',    '  font-family: Arial;',    '  font-size: 9pt;',    '  overflow: auto;',    '}',    'div.GMapEZ button.warnings {',    '  display: block;',    '  position: absolute;',    '  z-index: 100000000;',    '  bottom: 20px;',    '  right: 0;',    '  color: #f00;',    '}',    'div.GMapEZ .firefoxref {',    '  text-align: center;',    '  margin: 1em;',    '}',    'div.GMapEZ .loadprogress {',    '  position: relative;',    '  z-index: 100000000;',    '  text-align: center;',    '}',    'div.GMapEZ .loadprogress .box {',    '  font-family: Arial, sans-serif;',    '  background: #fff;',    '  border: 1px #bbb inset;',    '  width: 136px;',    '  height: 45px;',    '  margin: auto;',    '}',    'div.GMapEZ .loadprogress .logo {',    '  margin: 8px;',    '  margin-bottom: 0;',    '  width: 120px;',    '  height: 28px;',    "  filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" +        imgBase + "logo3.png',sizingMethod='scale');",    '}',    'div.GMapEZ .loadprogress .box > .logo {',    '  position: relative;',    '  background: url(' + imgBase + 'logo3.png) no-repeat;',    '}',    'div.GMapEZ .loadprogress .trough {',    '  margin: 8px;',    '  margin-top: -5px;',    '  background: #ccc;',    '  font-size: 1px;',    '  height: 8px;',    '  text-align: left;',    '}',    'div.GMapEZ .loadprogress .bar {',    '  height: 8px;',    '  width: 0px;',    '  background: #55a url(' + imgBase + 'progressbar.png);',    '}',    'v\\:* {',    '  behavior:url(#default#VML);',    '}',    '</style>'  ].join('\n'));})();

if(typeof Prototype=="undefined"){throw"Unable to load Shadowbox, Prototype framework not found."}if(typeof Effect=="undefined"){throw"Unable to load Shadowbox, Scriptaculous effects framework not found."}var Shadowbox={};Shadowbox.lib={getStyle:function(B,A){return Element.getStyle(B,A)},setStyle:function(C,B,D){if(typeof B!="object"){var A={};A[B]=D;B=A}Element.setStyle(C,B)},get:function(A){return $(A)},remove:function(A){Element.remove(A)},getTarget:function(A){return Event.element(A)},preventDefault:function(A){Event.stop(A)},addEvent:function(C,A,B){Event.observe(C,A,B)},removeEvent:function(C,A,B){Event.stopObserving(C,A,B)},animate:function(A,D,C,F){var E={};for(var B in D){for(var B in D){E[B]=String(D[B].to);if(B!="opacity"){E[B]+="px"}}}return new Effect.Morph(A,{afterFinish:F,duration:C,style:E})}}

if(typeof Shadowbox=="undefined"){throw"Unable to load Shadowbox, no base library adapter found."}(function(){var version="1.0";var options={assetURL:"",loadingImage:"/images/loading.gif",animate:true,animSequence:"wh",flvPlayer:"flvplayer.swf",overlayColor:"#000",overlayOpacity:0.85,overlayBgImage:"../images/overlay-85.png",listenOverlay:true,autoplayMovies:true,showMovieControls:true,resizeDuration:0.35,fadeDuration:0.35,displayNav:true,continuous:false,displayCounter:true,counterType:"default",viewportPadding:20,handleLgImages:"resize",initialHeight:160,initialWidth:320,enableKeys:true,keysClose:["c","q",27],keysNext:["n",39],keysPrev:["p",37],onOpen:null,onFinish:null,onChange:null,onClose:null,handleUnsupported:"link",skipSetup:false,text:{cancel:"Cancel",loading:"loading",close:'<span class="shortcut">C</span>lose',next:'<span class="shortcut">N</span>ext',prev:'<span class="shortcut">P</span>revious',errors:{single:'You must install the <a href="{0}">{1}</a> browser plugin to view this content.',shared:'You must install both the <a href="{0}">{1}</a> and <a href="{2}">{3}</a> browser plugins to view this content.',either:'You must install either the <a href="{0}">{1}</a> or the <a href="{2}">{3}</a> browser plugin to view this content.'}},errors:{fla:{name:"Flash",url:"http://www.adobe.com/products/flashplayer/"},qt:{name:"QuickTime",url:"http://www.apple.com/quicktime/download/"},wmp:{name:"Windows Media Player",url:"http://www.microsoft.com/windows/windowsmedia/"},f4m:{name:"Flip4Mac",url:"http://www.flip4mac.com/wmv_download.htm"}},skin:{main:'<div id="shadowbox_overlay"></div><div id="shadowbox_container"><div id="shadowbox"><div id="shadowbox_title"><div id="shadowbox_title_inner"></div></div><div id="shadowbox_body"><div id="shadowbox_body_inner"></div><div id="shadowbox_loading"></div></div><div id="shadowbox_toolbar"><div id="shadowbox_toolbar_inner"></div></div></div></div>',loading:'<img src="{0}" alt="{1}" /><span><a href="javascript:Shadowbox.close();">{2}</a></span>',counter:'<div id="shadowbox_counter">{0}</div>',close:'<div id="shadowbox_nav_close"><a href="javascript:Shadowbox.close();">{0}</a></div>',next:'<div id="shadowbox_nav_next"><a href="javascript:Shadowbox.next();">{0}</a></div>',prev:'<div id="shadowbox_nav_previous"><a href="javascript:Shadowbox.previous();">{0}</a></div>'},ext:{img:["png","jpg","jpeg","gif","bmp"],qt:["dv","mov","moov","movie","mp4"],wmp:["asf","wm","wmv"],qtwmp:["avi","mpg","mpeg"],iframe:["asp","aspx","cgi","cfm","htm","html","pl","php","php3","php4","php5","phtml","rb","rhtml","shtml","txt","vbs"]}};var default_options=null;var SL=Shadowbox.lib;var RE={resize:/(img|swf|flv)/,overlay:/(img|iframe|html|inline)/,swf:/\.swf\s*$/i,flv:/\.flv\s*$/i,domain:/:\/\/(.*?)[:\/]/,inline:/#(.+)$/,rel:/^(light|shadow)box/i,gallery:/^(light|shadow)box\[(.*?)\]/i,unsupported:/^unsupported-(\w+)/,param:/\s*([a-z_]*?)\s*=\s*(.+)\s*/,empty:/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i};var cache=[];var current_gallery;var current;var optimal_height=options.initialHeight;var optimal_width=options.initialWidth;var current_height=0;var current_width=0;var preloader;var initialized=false;var activated=false;var drag;var draggable;var overlay_img_needed;var ua=navigator.userAgent.toLowerCase();var isStrict=document.compatMode=="CSS1Compat",isOpera=ua.indexOf("opera")>-1,isIE=ua.indexOf("msie")>-1,isIE7=ua.indexOf("msie 7")>-1,isBorderBox=isIE&&!isStrict,isSafari=(/webkit|khtml/).test(ua),isSafari3=isSafari&&!!(document.evaluate),isGecko=!isSafari&&ua.indexOf("gecko")>-1,isWindows=(ua.indexOf("windows")!=-1||ua.indexOf("win32")!=-1),isMac=(ua.indexOf("macintosh")!=-1||ua.indexOf("mac os x")!=-1),isLinux=(ua.indexOf("linux")!=-1);var absolute_pos=isIE&&!isIE7;var plugins=null;if(navigator.plugins&&navigator.plugins.length){var detectPlugin=function(plugin_name){var detected=false;for(var i=0,len=navigator.plugins.length;i<len;++i){if(navigator.plugins[i].name.indexOf(plugin_name)>-1){detected=true;break}}return detected};var f4m=detectPlugin("Flip4Mac");var plugins={fla:detectPlugin("Shockwave Flash"),qt:detectPlugin("QuickTime"),wmp:!f4m&&detectPlugin("Windows Media"),f4m:f4m}}else{var detectPlugin=function(plugin_name){var detected=false;try{var axo=new ActiveXObject(plugin_name);if(axo){detected=true}}catch(e){}return detected};var plugins={fla:detectPlugin("ShockwaveFlash.ShockwaveFlash"),qt:detectPlugin("QuickTime.QuickTime"),wmp:detectPlugin("wmplayer.ocx"),f4m:false}}var apply=function(o,e){for(var p in e){o[p]=e[p]}return o};var isLink=function(el){return typeof el.tagName=="string"&&(el.tagName.toUpperCase()=="A"||el.tagName.toUpperCase()=="AREA")};SL.getViewportHeight=function(){var height=window.innerHeight;var mode=document.compatMode;if((mode||isIE)&&!isOpera){height=isStrict?document.documentElement.clientHeight:document.body.clientHeight}return height};SL.getViewportWidth=function(){var width=window.innerWidth;var mode=document.compatMode;if(mode||isIE){width=isStrict?document.documentElement.clientWidth:document.body.clientWidth}return width};SL.getDocumentHeight=function(){var scrollHeight=isStrict?document.documentElement.scrollHeight:document.body.scrollHeight;return Math.max(scrollHeight,SL.getViewportHeight())};SL.getDocumentWidth=function(){var scrollWidth=isStrict?document.documentElement.scrollWidth:document.body.scrollWidth;return Math.max(scrollWidth,SL.getViewportWidth())};var clearOpacity=function(el){if(isIE){if(typeof el.style.filter=="string"&&(/alpha/i).test(el.style.filter)){el.style.filter=""}}else{el.style.opacity="";el.style["-moz-opacity"]="";el.style["-khtml-opacity"]=""}};var fadeIn=function(el,endingOpacity,duration,callback){if(options.animate){SL.setStyle(el,"opacity",0);el.style.visibility="visible";SL.animate(el,{opacity:{to:endingOpacity}},duration,function(){if(endingOpacity==1){clearOpacity(el)}if(typeof callback=="function"){callback()}})}else{if(endingOpacity==1){clearOpacity(el)}else{SL.setStyle(el,"opacity",endingOpacity)}el.style.visibility="visible";if(typeof callback=="function"){callback()}}};var fadeOut=function(el,duration,callback){var cb=function(){el.style.visibility="hidden";clearOpacity(el);if(typeof callback=="function"){callback()}};if(options.animate){SL.animate(el,{opacity:{to:0}},duration,cb)}else{cb()}};var appendHTML=function(el,html){el=SL.get(el);if(el.insertAdjacentHTML){el.insertAdjacentHTML("BeforeEnd",html);return el.lastChild}if(el.lastChild){var range=el.ownerDocument.createRange();range.setStartAfter(el.lastChild);var frag=range.createContextualFragment(html);el.appendChild(frag);return el.lastChild}else{el.innerHTML=html;return el.lastChild}};var overwriteHTML=function(el,html){el=SL.get(el);el.innerHTML=html;return el.firstChild};var getComputedHeight=function(el){var h=Math.max(el.offsetHeight,el.clientHeight);if(!h){h=parseInt(SL.getStyle(el,"height"),10)||0;if(!isBorderBox){h+=parseInt(SL.getStyle(el,"padding-top"),10)+parseInt(SL.getStyle(el,"padding-bottom"),10)+parseInt(SL.getStyle(el,"border-top-width"),10)+parseInt(SL.getStyle(el,"border-bottom-width"),10)}}return h};var getComputedWidth=function(el){var w=Math.max(el.offsetWidth,el.clientWidth);if(!w){w=parseInt(SL.getStyle(el,"width"),10)||0;if(!isBorderBox){w+=parseInt(SL.getStyle(el,"padding-left"),10)+parseInt(SL.getStyle(el,"padding-right"),10)+parseInt(SL.getStyle(el,"border-left-width"),10)+parseInt(SL.getStyle(el,"border-right-width"),10)}}return w};var getPlayerType=function(url){if(RE.img.test(url)){return"img"}var match=url.match(RE.domain);var this_domain=match?document.domain==match[1]:false;if(url.indexOf("#")>-1&&this_domain){return"inline"}var q_index=url.indexOf("?");if(q_index>-1){url=url.substring(0,q_index)}if(RE.swf.test(url)){return plugins.fla?"swf":"unsupported-swf"}if(RE.flv.test(url)){return plugins.fla?"flv":"unsupported-flv"}if(RE.qt.test(url)){return plugins.qt?"qt":"unsupported-qt"}if(RE.wmp.test(url)){if(plugins.wmp){return"wmp"}else{if(plugins.f4m){return"qt"}else{return isMac?(plugins.qt?"unsupported-f4m":"unsupported-qtf4m"):"unsupported-wmp"}}}else{if(RE.qtwmp.test(url)){if(plugins.qt){return"qt"}else{if(plugins.wmp){return"wmp"}else{return isMac?"unsupported-qt":"unsupported-qtwmp"}}}else{if(!this_domain||RE.iframe.test(url)){return"iframe"}}}return"unsupported"};var handleClick=function(ev){var link;if(isLink(this)){link=this}else{link=SL.getTarget(ev);while(!isLink(link)&&link.parentNode){link=link.parentNode}}Shadowbox.open(link);if(current_gallery.length){SL.preventDefault(ev)}};var setupGallery=function(obj){var copy=apply({},obj);if(!obj.gallery){current_gallery=[copy];current=0}else{current_gallery=[];var index,ci;for(var i=0,len=cache.length;i<len;++i){ci=cache[i];if(ci.gallery){if(ci.content==obj.content&&ci.gallery==obj.gallery&&ci.title==obj.title){index=current_gallery.length}if(ci.gallery==obj.gallery){current_gallery.push(apply({},ci))}}}if(index==null){current_gallery.unshift(copy);index=0}current=index}var match,r;for(var i=0,len=current_gallery.length;i<len;++i){r=false;if(current_gallery[i].type=="unsupported"){r=true}else{if(match=RE.unsupported.exec(current_gallery[i].type)){if(options.handleUnsupported=="link"){current_gallery[i].type="html";var m;switch(match[1]){case"qtwmp":m=String.format(options.text.errors.either,options.errors.qt.url,options.errors.qt.name,options.errors.wmp.url,options.errors.wmp.name);break;case"qtf4m":m=String.format(options.text.errors.shared,options.errors.qt.url,options.errors.qt.name,options.errors.f4m.url,options.errors.f4m.name);break;default:if(match[1]=="swf"||match[1]=="flv"){match[1]="fla"}m=String.format(options.text.errors.single,options.errors[match[1]].url,options.errors[match[1]].name)}current_gallery[i]=apply(current_gallery[i],{height:160,width:320,content:'<div class="shadowbox_message">'+m+"</div>"})}else{r=true}}else{if(current_gallery[i].type=="inline"){var match=RE.inline.exec(current_gallery[i].content);if(match){var el;if(el=SL.get(match[1])){current_gallery[i].content=el.innerHTML}else{throw"No element found with id "+match[1]}}else{throw"No element id found for inline content"}}}}if(r){current_gallery.splice(i,1);if(i<current){--current}--i}}};var buildBars=function(){var link=current_gallery[current];if(!link){return }var title_i=SL.get("shadowbox_title_inner");title_i.innerHTML=(link.title)?link.title:"";var tool_i=SL.get("shadowbox_toolbar_inner");tool_i.innerHTML="";if(options.displayNav){tool_i.innerHTML=String.format(options.skin.close,options.text.close);if(current_gallery.length>1){if(options.continuous){appendHTML(tool_i,String.format(options.skin.next,options.text.next));appendHTML(tool_i,String.format(options.skin.prev,options.text.prev))}else{if((current_gallery.length-1)>current){appendHTML(tool_i,String.format(options.skin.next,options.text.next))}if(current>0){appendHTML(tool_i,String.format(options.skin.prev,options.text.prev))}}}}if(current_gallery.length>1&&options.displayCounter){var counter="";if(options.counterType=="skip"){for(var i=0,len=current_gallery.length;i<len;++i){counter+='<a href="javascript:Shadowbox.change('+i+');"';if(i==current){counter+=' class="shadowbox_counter_current"'}counter+=">"+(i+1)+"</a>"}}else{counter=(current+1)+" of "+current_gallery.length}appendHTML(tool_i,String.format(options.skin.counter,counter))}};var hideBars=function(callback){var title_m=getComputedHeight(SL.get("shadowbox_title"));var tool_m=0-getComputedHeight(SL.get("shadowbox_toolbar"));var title_i=SL.get("shadowbox_title_inner");var tool_i=SL.get("shadowbox_toolbar_inner");if(options.animate&&callback){SL.animate(title_i,{marginTop:{to:title_m}},0.2);SL.animate(tool_i,{marginTop:{to:tool_m}},0.2,callback)}else{SL.setStyle(title_i,"marginTop",title_m+"px");SL.setStyle(tool_i,"marginTop",tool_m+"px")}};var showBars=function(callback){var title_i=SL.get("shadowbox_title_inner");if(options.animate){if(title_i.innerHTML!=""){SL.animate(title_i,{marginTop:{to:0}},0.35)}SL.animate(SL.get("shadowbox_toolbar_inner"),{marginTop:{to:0}},0.35,callback)}else{if(title_i.innerHTML!=""){SL.setStyle(title_i,"margin-top","0px")}SL.setStyle(SL.get("shadowbox_toolbar_inner"),"margin-top","0px");callback()}};var resetDrag=function(){drag={x:0,y:0,start_x:null,start_y:null}};var toggleDrag=function(on){if(on){resetDrag();var styles=["position:absolute","cursor:"+(isGecko?"-moz-grab":"move")];styles.push(isIE?"background-color:#fff;filter:alpha(opacity=0)":"background-color:transparent");appendHTML("shadowbox_body_inner",'<div id="shadowbox_drag_layer" style="'+styles.join(";")+'"></div>');SL.addEvent(SL.get("shadowbox_drag_layer"),"mousedown",listenDrag)}else{var d=SL.get("shadowbox_drag_layer");if(d){SL.removeEvent(d,"mousedown",listenDrag);SL.remove(d)}}};var listenDrag=function(ev){drag.start_x=ev.clientX;drag.start_y=ev.clientY;draggable=SL.get("shadowbox_content");SL.addEvent(document,"mousemove",positionDrag);SL.addEvent(document,"mouseup",unlistenDrag);if(isGecko){SL.setStyle(SL.get("shadowbox_drag_layer"),"cursor","-moz-grabbing")}};var unlistenDrag=function(){SL.removeEvent(document,"mousemove",positionDrag);SL.removeEvent(document,"mouseup",unlistenDrag);if(isGecko){SL.setStyle(SL.get("shadowbox_drag_layer"),"cursor","-moz-grab")}};var positionDrag=function(ev){var move_y=ev.clientY-drag.start_y;drag.start_y=drag.start_y+move_y;drag.y=Math.max(Math.min(0,drag.y+move_y),current_height-optimal_height);SL.setStyle(draggable,"top",drag.y+"px");var move_x=ev.clientX-drag.start_x;drag.start_x=drag.start_x+move_x;drag.x=Math.max(Math.min(0,drag.x+move_x),current_width-optimal_width);SL.setStyle(draggable,"left",drag.x+"px")};var loadContent=function(){var obj=current_gallery[current];if(!obj){return }buildBars();switch(obj.type){case"img":preloader=new Image();preloader.onload=function(){var h=obj.height?parseInt(obj.height,10):preloader.height;var w=obj.width?parseInt(obj.width,10):preloader.width;resizeContent(h,w,function(dims){showBars(function(){setContent({tag:"img",height:dims.i_height,width:dims.i_width,src:obj.content,style:"position:absolute"});if(dims.enableDrag&&options.handleLgImages=="drag"){toggleDrag(true);SL.setStyle(SL.get("shadowbox_drag_layer"),{height:dims.i_height+"px",width:dims.i_width+"px"})}finishContent()})});preloader.onload=function(){}};preloader.src=obj.content;break;case"swf":case"flv":case"qt":case"wmp":var markup=Shadowbox.movieMarkup(obj);resizeContent(markup.height,markup.width,function(){showBars(function(){setContent(markup);finishContent()})});break;case"iframe":var h=obj.height?parseInt(obj.height,10):SL.getViewportHeight();var w=obj.width?parseInt(obj.width,10):SL.getViewportWidth();var content={tag:"iframe",name:"shadowbox_content",height:"100%",width:"100%",frameborder:"0",marginwidth:"0",marginheight:"0",scrolling:"auto"};resizeContent(h,w,function(dims){showBars(function(){setContent(content);var win=(isIE)?SL.get("shadowbox_content").contentWindow:window.frames["shadowbox_content"];win.location=obj.content;finishContent()})});break;case"html":case"inline":var h=obj.height?parseInt(obj.height,10):SL.getViewportHeight();var w=obj.width?parseInt(obj.width,10):SL.getViewportWidth();var content={tag:"div",cls:"html",html:obj.content};resizeContent(h,w,function(){showBars(function(){setContent(content);finishContent()})});break;default:throw"Shadowbox cannot open content of type "+obj.type}if(current_gallery.length>0){var next=current_gallery[current+1];if(!next){next=current_gallery[0]}if(next.type=="img"){var preload_next=new Image();preload_next.src=next.href}var prev=current_gallery[current-1];if(!prev){prev=current_gallery[current_gallery.length-1]}if(prev.type=="img"){var preload_prev=new Image();preload_prev.src=prev.href}}};var setContent=function(obj){var id="shadowbox_content";var content=SL.get(id);if(content){switch(content.tagName.toUpperCase()){case"OBJECT":var link=current_gallery[(obj?current-1:current)];if(link.type=="wmp"&&isIE){try{shadowbox_content.controls.stop();shadowbox_content.URL="non-existent.wmv";window.shadowbox_content=function(){}}catch(e){}}else{if(link.type=="qt"&&isSafari){try{document.shadowbox_content.Stop()}catch(e){}content.innerHTML=""}}setTimeout(function(){SL.remove(content)},10);break;case"IFRAME":SL.remove(content);if(isGecko){delete window.frames[id]}break;default:SL.remove(content)}}if(obj){if(!obj.id){obj.id=id}return appendHTML("shadowbox_body_inner",Shadowbox.createHTML(obj))}return null};var finishContent=function(){var obj=current_gallery[current];if(!obj){return }hideLoading(function(){listenKeyboard(true);if(options.onFinish&&typeof options.onFinish=="function"){options.onFinish(obj)}})};var resizeContent=function(height,width,callback){optimal_height=height;optimal_width=width;var resizable=RE.resize.test(current_gallery[current].type);var dims=getDimensions(optimal_height,optimal_width,resizable);if(callback){var cb=function(){callback(dims)};switch(options.animSequence){case"hw":adjustHeight(dims.height,dims.top,true,function(){adjustWidth(dims.width,true,cb)});break;case"wh":adjustWidth(dims.width,true,function(){adjustHeight(dims.height,dims.top,true,cb)});break;default:adjustWidth(dims.width,true);adjustHeight(dims.height,dims.top,true,cb)}}else{adjustWidth(dims.width,false);adjustHeight(dims.height,dims.top,false);if(options.handleLgImages=="resize"&&resizable){var content=SL.get("shadowbox_content");if(content){content.height=dims.i_height;content.width=dims.i_width}}}};var getDimensions=function(o_height,o_width,resizable){if(typeof resizable=="undefined"){resizable=false}var height=o_height=parseInt(o_height);var width=o_width=parseInt(o_width);var shadowbox_b=SL.get("shadowbox_body");var view_height=SL.getViewportHeight();var extra_height=parseInt(SL.getStyle(shadowbox_b,"border-top-width"),10)+parseInt(SL.getStyle(shadowbox_b,"border-bottom-width"),10)+parseInt(SL.getStyle(shadowbox_b,"margin-top"),10)+parseInt(SL.getStyle(shadowbox_b,"margin-bottom"),10)+getComputedHeight(SL.get("shadowbox_title"))+getComputedHeight(SL.get("shadowbox_toolbar"))+(2*options.viewportPadding);if((height+extra_height)>=view_height){height=view_height-extra_height}var view_width=SL.getViewportWidth();var extra_body_width=parseInt(SL.getStyle(shadowbox_b,"border-left-width"),10)+parseInt(SL.getStyle(shadowbox_b,"border-right-width"),10)+parseInt(SL.getStyle(shadowbox_b,"margin-left"),10)+parseInt(SL.getStyle(shadowbox_b,"margin-right"),10);var extra_width=extra_body_width+(2*options.viewportPadding);if((width+extra_width)>=view_width){width=view_width-extra_width}var enableDrag=false;var i_height=o_height;var i_width=o_width;var handle=options.handleLgImages;if(resizable&&(handle=="resize"||handle=="drag")){var change_h=(o_height-height)/o_height;var change_w=(o_width-width)/o_width;if(handle=="resize"){if(change_h>change_w){width=Math.round((o_width/o_height)*height)}else{if(change_w>change_h){height=Math.round((o_height/o_width)*width)}}i_width=width;i_height=height}else{var link=current_gallery[current];if(link){enableDrag=link.type=="img"&&(change_h>0||change_w>0)}}}return{height:height,width:width+extra_body_width,i_height:i_height,i_width:i_width,top:((view_height-(height+extra_height))/2)+options.viewportPadding,enableDrag:enableDrag}};var centerVertically=function(){var shadowbox=SL.get("shadowbox");var scroll=document.documentElement.scrollTop;var s_top=scroll+Math.round((SL.getViewportHeight()-(shadowbox.offsetHeight||0))/2);SL.setStyle(shadowbox,"top",s_top+"px")};var adjustHeight=function(height,top,animate,callback){height=parseInt(height);current_height=height;var sbi=SL.get("shadowbox_body_inner");if(animate&&options.animate){SL.animate(sbi,{height:{to:height}},options.resizeDuration,callback)}else{SL.setStyle(sbi,"height",height+"px");if(typeof callback=="function"){callback()}}if(absolute_pos){centerVertically();SL.addEvent(window,"scroll",centerVertically);top+=document.documentElement.scrollTop}var shadowbox=SL.get("shadowbox");if(animate&&options.animate){SL.animate(shadowbox,{top:{to:top}},options.resizeDuration)}else{SL.setStyle(shadowbox,"top",top+"px")}};var adjustWidth=function(width,animate,callback){width=parseInt(width);current_width=width;var shadowbox=SL.get("shadowbox");if(animate&&options.animate){SL.animate(shadowbox,{width:{to:width}},options.resizeDuration,callback)}else{SL.setStyle(shadowbox,"width",width+"px");if(typeof callback=="function"){callback()}}};var listenKeyboard=function(on){if(!options.enableKeys){return }if(on){document.onkeydown=handleKey}else{document.onkeydown=""}};var assertKey=function(valid,key,code){return(valid.indexOf(key)!=-1||valid.indexOf(code)!=-1)};var handleKey=function(e){var code=e?e.which:event.keyCode;var key=String.fromCharCode(code).toLowerCase();if(assertKey(options.keysClose,key,code)){Shadowbox.close()}else{if(assertKey(options.keysPrev,key,code)){Shadowbox.previous()}else{if(assertKey(options.keysNext,key,code)){Shadowbox.next()}}}};var toggleTroubleElements=function(on){var vis=(on?"visible":"hidden");var selects=document.getElementsByTagName("select");for(i=0,len=selects.length;i<len;++i){selects[i].style.visibility=vis}var objects=document.getElementsByTagName("object");for(i=0,len=objects.length;i<len;++i){objects[i].style.visibility=vis}var embeds=document.getElementsByTagName("embed");for(i=0,len=embeds.length;i<len;++i){embeds[i].style.visibility=vis}};var showLoading=function(){var loading=SL.get("shadowbox_loading");overwriteHTML(loading,String.format(options.skin.loading,options.assetURL+options.loadingImage,options.text.loading,options.text.cancel));loading.style.visibility="visible"};var hideLoading=function(callback){var t=current_gallery[current].type;var anim=(t=="img"||t=="html");var loading=SL.get("shadowbox_loading");if(anim){fadeOut(loading,0.35,callback)}else{loading.style.visibility="hidden";callback()}};var resizeOverlay=function(){var overlay=SL.get("shadowbox_overlay");SL.setStyle(overlay,{height:"100%",width:"100%"});SL.setStyle(overlay,"height",SL.getDocumentHeight()+"px");if(!isSafari3){SL.setStyle(overlay,"width",SL.getDocumentWidth()+"px")}};var checkOverlayImgNeeded=function(){if(!(isGecko&&isMac)){return false}for(var i=0,len=current_gallery.length;i<len;++i){if(!RE.overlay.exec(current_gallery[i].type)){return true}}return false};var toggleOverlay=function(callback){var overlay=SL.get("shadowbox_overlay");if(overlay_img_needed==null){overlay_img_needed=checkOverlayImgNeeded()}if(callback){resizeOverlay();if(overlay_img_needed){SL.setStyle(overlay,{visibility:"visible",backgroundColor:"transparent",backgroundImage:"url("+options.assetURL+options.overlayBgImage+")",backgroundRepeat:"repeat",opacity:1});callback()}else{SL.setStyle(overlay,{visibility:"visible",backgroundColor:options.overlayColor,backgroundImage:"none"});fadeIn(overlay,options.overlayOpacity,options.fadeDuration,callback)}}else{if(overlay_img_needed){SL.setStyle(overlay,"visibility","hidden")}else{fadeOut(overlay,options.fadeDuration)}overlay_img_needed=null}};Shadowbox.init=function(opts){if(initialized){return }options=apply(options,opts||{});appendHTML(document.body,options.skin.main);RE.img=new RegExp(".("+options.ext.img.join("|")+")s*$","i");RE.qt=new RegExp(".("+options.ext.qt.join("|")+")s*$","i");RE.wmp=new RegExp(".("+options.ext.wmp.join("|")+")s*$","i");RE.qtwmp=new RegExp(".("+options.ext.qtwmp.join("|")+")s*$","i");RE.iframe=new RegExp(".("+options.ext.iframe.join("|")+")s*$","i");var id=null;var resize=function(){clearInterval(id);id=null;resizeOverlay();resizeContent(optimal_height,optimal_width)};SL.addEvent(window,"resize",function(){if(activated){if(id){clearInterval(id);id=null}if(!id){id=setInterval(resize,50)}}});if(options.listenOverlay){SL.addEvent(SL.get("shadowbox_overlay"),"click",Shadowbox.close)}if(absolute_pos){SL.setStyle(SL.get("shadowbox_container"),"position","absolute");SL.setStyle("shadowbox_body","zoom",1);SL.addEvent(SL.get("shadowbox_container"),"click",function(e){var target=SL.getTarget(e);if(target.id&&target.id=="shadowbox_container"){Shadowbox.close()}})}if(!options.skipSetup){Shadowbox.setup()}initialized=true};Shadowbox.setup=function(links,opts){if(!links){var links=[];var a=document.getElementsByTagName("a"),rel;for(var i=0,len=a.length;i<len;++i){rel=a[i].getAttribute("rel");if(rel&&RE.rel.test(rel)){links[links.length]=a[i]}}}else{if(!links.length){links=[links]}}var link;for(var i=0,len=links.length;i<len;++i){link=links[i];if(typeof link.shadowboxCacheKey=="undefined"){link.shadowboxCacheKey=cache.length;SL.addEvent(link,"click",handleClick)}cache[link.shadowboxCacheKey]=this.buildCacheObj(link,opts)}};Shadowbox.buildCacheObj=function(link,opts){var href=link.href;var o={el:link,title:link.getAttribute("title"),type:getPlayerType(href),options:apply({},opts||{}),content:href};var opt,l_opts=["title","type","height","width","gallery"];for(var i=0,len=l_opts.length;i<len;++i){opt=l_opts[i];if(typeof o.options[opt]!="undefined"){o[opt]=o.options[opt];delete o.options[opt]}}var rel=link.getAttribute("rel");if(rel){var match=rel.match(RE.gallery);if(match){o.gallery=escape(match[2])}var params=rel.split(";");for(var i=0,len=params.length;i<len;++i){match=params[i].match(RE.param);if(match){if(match[1]=="options"){eval("o.options = apply(o.options, "+match[2]+")")}else{o[match[1]]=match[2]}}}}return o};Shadowbox.applyOptions=function(opts){if(opts){default_options=apply({},options);options=apply(options,opts)}};Shadowbox.revertOptions=function(){if(default_options){options=default_options;default_options=null}};Shadowbox.open=function(obj,opts){if(activated){return }activated=true;if(isLink(obj)){if(typeof obj.shadowboxCacheKey=="undefined"||typeof cache[obj.shadowboxCacheKey]=="undefined"){obj=this.buildCacheObj(obj,opts)}else{obj=cache[obj.shadowboxCacheKey]}}this.revertOptions();if(obj.options||opts){this.applyOptions(apply(apply({},obj.options||{}),opts||{}))}setupGallery(obj);if(current_gallery.length){if(options.onOpen&&typeof options.onOpen=="function"){options.onOpen(obj)}SL.setStyle(SL.get("shadowbox"),"display","block");toggleTroubleElements(false);var dims=getDimensions(options.initialHeight,options.initialWidth);adjustHeight(dims.height,dims.top);adjustWidth(dims.width);hideBars(false);toggleOverlay(function(){SL.setStyle(SL.get("shadowbox"),"visibility","visible");showLoading();loadContent()})}};Shadowbox.change=function(num){if(!current_gallery){return }if(!current_gallery[num]){if(!options.continuous){return }else{num=(num<0)?(current_gallery.length-1):0}}current=num;toggleDrag(false);setContent(null);listenKeyboard(false);if(options.onChange&&typeof options.onChange=="function"){options.onChange(current_gallery[current])}showLoading();hideBars(loadContent)};Shadowbox.next=function(){return this.change(current+1)};Shadowbox.previous=function(){return this.change(current-1)};Shadowbox.close=function(){if(!activated){return }listenKeyboard(false);SL.setStyle(SL.get("shadowbox"),{display:"none",visibility:"hidden"});if(absolute_pos){SL.removeEvent(window,"scroll",centerVertically)}toggleDrag(false);setContent(null);if(preloader){preloader.onload=function(){};preloader=null}toggleOverlay(false);toggleTroubleElements(true);if(options.onClose&&typeof options.onClose=="function"){options.onClose(current_gallery[current])}activated=false};Shadowbox.clearCache=function(){for(var i=0,len=cache.length;i<len;++i){if(cache[i].el){SL.removeEvent(cache[i].el,"click",handleClick);delete cache[i].shadowboxCacheKey}}cache=[]};Shadowbox.movieMarkup=function(obj){var h=obj.height?parseInt(obj.height,10):300;var w=obj.width?parseInt(obj.width,10):300;var autoplay=options.autoplayMovies;var controls=options.showMovieControls;if(obj.options){if(obj.options.autoplayMovies!=null){autoplay=obj.options.autoplayMovies}if(obj.options.showMovieControls!=null){controls=obj.options.showMovieControls}}var markup={tag:"object",name:"shadowbox_content"};switch(obj.type){case"swf":var dims=getDimensions(h,w,true);h=dims.height;w=dims.width;markup.type="application/x-shockwave-flash";markup.data=obj.content;markup.children=[{tag:"param",name:"movie",value:obj.content}];break;case"flv":autoplay=autoplay?"true":"false";var showicons="false";var a=h/w;if(controls){showicons="true";h+=20}var dims=getDimensions(h,h/a,true);h=dims.height;w=(h-(controls?20:0))/a;var flashvars=["file="+obj.content,"height="+h,"width="+w,"autostart="+autoplay,"displayheight="+(h-(controls?20:0)),"showicons="+showicons,"backcolor=0x000000&amp;frontcolor=0xCCCCCC&amp;lightcolor=0x557722"];markup.type="application/x-shockwave-flash";markup.data=options.assetURL+options.flvPlayer;markup.children=[{tag:"param",name:"movie",value:options.assetURL+options.flvPlayer},{tag:"param",name:"flashvars",value:flashvars.join("&amp;")},{tag:"param",name:"allowfullscreen",value:"true"}];break;case"qt":autoplay=autoplay?"true":"false";if(controls){controls="true";h+=16}else{controls="false"}markup.children=[{tag:"param",name:"src",value:obj.content},{tag:"param",name:"scale",value:"aspect"},{tag:"param",name:"controller",value:controls},{tag:"param",name:"autoplay",value:autoplay}];if(isIE){markup.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";markup.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"}else{markup.type="video/quicktime";markup.data=obj.content}break;case"wmp":autoplay=autoplay?1:0;markup.children=[{tag:"param",name:"autostart",value:autoplay}];if(isIE){if(controls){controls="full";h+=70}else{controls="none"}markup.classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6";markup.children[markup.children.length]={tag:"param",name:"url",value:obj.content};markup.children[markup.children.length]={tag:"param",name:"uimode",value:controls}}else{if(controls){controls=1;h+=45}else{controls=0}markup.type="video/x-ms-wmv";markup.data=obj.content;markup.children[markup.children.length]={tag:"param",name:"showcontrols",value:controls}}break}markup.height=h;markup.width=w;return markup};Shadowbox.createHTML=function(obj){var html="<"+obj.tag;for(var attr in obj){if(attr=="tag"||attr=="html"||attr=="children"){continue}if(attr=="cls"){html+=' class="'+obj["cls"]+'"'}else{html+=" "+attr+'="'+obj[attr]+'"'}}if(RE.empty.test(obj.tag)){html+="/>\n"}else{html+=">\n";var cn=obj.children;if(cn){for(var i=0,len=cn.length;i<len;++i){html+=this.createHTML(cn[i])}}if(obj.html){html+=obj.html}html+="</"+obj.tag+">\n"}return html};Shadowbox.getPlugins=function(){return plugins};Shadowbox.getOptions=function(){return options};Shadowbox.getCurrent=function(){return current_gallery[current]};Shadowbox.getVersion=function(){return version}})();Array.prototype.indexOf=Array.prototype.indexOf||function(C){for(var B=0,A=this.length;B<A;++B){if(this[B]==C){return B}}return -1};String.format=String.format||function(B){var A=Array.prototype.slice.call(arguments,1);return B.replace(/\{(\d+)\}/g,function(C,D){return A[D]})}