
/*  Prototype JavaScript framework, version 1.5.0_rc0
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.5.0_rc0',
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

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

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

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

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

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}

Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

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

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

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

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

    return returnValue;
  }
}

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

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

    this.registerCallback();
  },

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

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
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 += (replacement(match) || '').toString();
        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 this;
  },

  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : 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 div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  },

  toQueryParams: function() {
    var pairs = this.match(/^\??(.*)$/)[1].split('&');
    return pairs.inject({}, function(params, pairString) {
      var pair = pairString.split('=');
      params[pair[0]] = pair[1];
      return params;
    });
  },

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

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

    var camelizedString = this.indexOf('-') == 0
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
      : oStringList[0];

    for (var i = 1, len = oStringList.length; i < len; i++) {
      var s = oStringList[i];
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
    }

    return camelizedString;
  },

  inspect: function() {
    return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
  }
});

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

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

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
      if (before == '\\') return match[2];
      return before + (object[match[3]] || '').toString();
    });
  }
}

var $break    = new Object();
var $continue = new Object();

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

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

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

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

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

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

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

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

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

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

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

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

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

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

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

  sortBy: function(iterator) {
    return this.collect(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.collect(Prototype.K);
  },

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

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

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

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

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; i < this.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 != undefined || value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

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

  indexOf: function(object) {
    for (var i = 0; i < this.length; i++)
      if (this[i] == object) return i;
    return -1;
  },

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

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});
var Hash = {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (typeof value == 'function') continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

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

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

  merge: function(hash) {
    return $H(hash).inject($H(this), function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  toQueryString: function() {
    return this.map(function(pair) {
      return pair.map(encodeURIComponent).join('=');
    }).join('&');
  },

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

function $H(object) {
  var hash = Object.extend({}, object || {});
  Object.extend(hash, Enumerable);
  Object.extend(hash, Hash);
  return hash;
}
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

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

  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(responderToAdd) {
    if (!this.include(responderToAdd))
      this.responders.push(responderToAdd);
  },

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

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (responder[callback] && typeof responder[callback] == 'function') {
        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 = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      parameters:   ''
    }
    Object.extend(this.options, options || {});
  },

  responseIsSuccess: function() {
    return this.transport.status == undefined
        || this.transport.status == 0
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  responseIsFailure: function() {
    return !this.responseIsSuccess();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    var parameters = this.options.parameters || '';
    if (parameters.length > 0) parameters += '&_=';

    try {
      this.url = url;
      if (this.options.method == 'get' && parameters.length > 0)
        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

      Ajax.Responders.dispatch('onCreate', this, this.transport);

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

      if (this.options.asynchronous) {
        this.transport.onreadystatechange = this.onStateChange.bind(this);
        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
      }

      this.setRequestHeaders();

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

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

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

    if (this.options.method == 'post') {
      requestHeaders.push('Content-type', this.options.contentType);

      /* Force "Connection: close" for Mozilla browsers to work around
       * a bug where XMLHttpReqeuest sends an incorrect Content-length
       * header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType)
        requestHeaders.push('Connection', 'close');
    }

    if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

    for (var i = 0; i < requestHeaders.length; i += 2)
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  },

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

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

  evalJSON: function() {
    try {
      return eval('(' + this.header('X-JSON') + ')');
    } catch (e) {}
  },

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

  respondToReadyState: function(readyState) {
    var event = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (event == 'Complete') {
      try {
        (this.options['on' + this.transport.status]
         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
      } catch (e) {
        this.dispatchException(e);
      }

      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
        this.evalResponse();
    }

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

    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
    if (event == 'Complete')
      this.transport.onreadystatechange = Prototype.emptyFunction;
  },

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

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.containers = {
      success: container.success ? $(container.success) : $(container),
      failure: container.failure ? $(container.failure) :
        (container.success ? null : $(container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, object) {
      this.updateContent();
      onComplete(transport, object);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.responseIsSuccess() ?
      this.containers.success : this.containers.failure;
    var response = this.transport.responseText;

    if (!this.options.evalScripts)
      response = response.stripScripts();

    if (receiver) {
      if (this.options.insertion) {
        new this.options.insertion(receiver, response);
      } else {
        Element.update(receiver, response);
      }
    }

    if (this.responseIsSuccess()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(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.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

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

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $() {
  var results = [], element;
  for (var i = 0; i < arguments.length; i++) {
    element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);
    results.push(Element.extend(element));
  }
  return results.length < 2 ? results[0] : results;
}

document.getElementsByClassName = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  return $A(children).inject([], function(elements, child) {
    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      elements.push(Element.extend(child));
    return elements;
  });
}

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

if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element) return;
  if (_nativeExtensions) return element;

  if (!element._extended && element.tagName && element != window) {
    var methods = Element.Methods, cache = Element.extend.cache;
    for (property in methods) {
      var value = methods[property];
      if (typeof value == 'function')
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
}

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
}

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

  toggle: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      Element[Element.visible(element) ? 'hide' : 'show'](element);
    }
  },

  hide: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = 'none';
    }
  },

  show: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = '';
    }
  },

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

  update: function(element, html) {
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
  },

  replace: function(element, html) {
    element = $(element);
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
  },

  getHeight: function(element) {
    element = $(element);
    return element.offsetHeight;
  },

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

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element.classNames(element).include(className);
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element.classNames(element).add(className);
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element.classNames(element).remove(className);
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    for (var i = 0; i < element.childNodes.length; i++) {
      var node = element.childNodes[i];
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        Element.remove(node);
    }
  },

  empty: function(element) {
    return $(element).innerHTML.match(/^\s*$/);
  },

  childOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var x = element.x ? element.x : element.offsetLeft,
        y = element.y ? element.y : element.offsetTop;
    window.scrollTo(x, y);
  },

  getStyle: function(element, style) {
    element = $(element);
    var value = element.style[style.camelize()];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(style) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style.camelize()];
      }
    }

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';

    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style)
      element.style[name.camelize()] = style[name];
  },

  getDimensions: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'display') != 'none')
      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;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = '';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = 'none';
    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;
      }
    }
  },

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

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

  undoClipping: function(element) {
    element = $(element);
    if (element._overflow) return;
    element.style.overflow = element._overflow;
    element._overflow = undefined;
  }
}

Object.extend(Element, Element.Methods);

var _nativeExtensions = false;

if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  var HTMLElement = {}
  HTMLElement.prototype = document.createElement('div').__proto__;
}

Element.addMethods = function(methods) {
  Object.extend(Element.Methods, methods || {});

  if(typeof HTMLElement != 'undefined') {
    var methods = Element.Methods, cache = Element.extend.cache;
    for (property in methods) {
      var value = methods[property];
      if (typeof value == 'function')
        HTMLElement.prototype[property] = cache.findOrStore(value);
    }
    _nativeExtensions = true;
  }
}

Element.addMethods();

var Toggle = new Object();
Toggle.display = Element.toggle;

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

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        var tagName = this.element.tagName.toLowerCase();
        if (tagName == 'tbody' || tagName == 'tr') {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse(false).each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

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

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(this.toArray().concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set(this.select(function(className) {
      return className != classNameToRemove;
    }).join(' '));
  },

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

Object.extend(Element.ClassNames.prototype, Enumerable);
var Selector = Class.create();
Selector.prototype = {
  initialize: function(expression) {
    this.params = {classNames: []};
    this.expression = expression.toString().strip();
    this.parseExpression();
    this.compileMatcher();
  },

  parseExpression: function() {
    function abort(message) { throw 'Parse error in selector: ' + message; }

    if (this.expression == '')  abort('empty expression');

    var params = this.params, expr = this.expression, match, modifier, clause, rest;
    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
      params.attributes = params.attributes || [];
      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
      expr = match[1];
    }

    if (expr == '*') return this.params.wildcard = true;

    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
      modifier = match[1], clause = match[2], rest = match[3];
      switch (modifier) {
        case '#':       params.id = clause; break;
        case '.':       params.classNames.push(clause); break;
        case '':
        case undefined: params.tagName = clause.toUpperCase(); break;
        default:        abort(expr.inspect());
      }
      expr = rest;
    }

    if (expr.length > 0) abort(expr.inspect());
  },

  buildMatchExpression: function() {
    var params = this.params, conditions = [], clause;

    if (params.wildcard)
      conditions.push('true');
    if (clause = params.id)
      conditions.push('element.id == ' + clause.inspect());
    if (clause = params.tagName)
      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
    if ((clause = params.classNames).length > 0)
      for (var i = 0; i < clause.length; i++)
        conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
    if (clause = params.attributes) {
      clause.each(function(attribute) {
        var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
        var splitValueBy = function(delimiter) {
          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
        }

        switch (attribute.operator) {
          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
          case '|=':      conditions.push(
                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
                          ); break;
          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
          case '':
          case undefined: conditions.push(value + ' != null'); break;
          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
        }
      });
    }

    return conditions.join(' && ');
  },

  compileMatcher: function() {
    this.match = new Function('element', 'if (!element.tagName) return false; \
      return ' + this.buildMatchExpression());
  },

  findElements: function(scope) {
    var element;

    if (element = $(this.params.id))
      if (this.match(element))
        if (!scope || Element.childOf(element, scope))
          return [element];

    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');

    var results = [];
    for (var i = 0; i < scope.length; i++)
      if (this.match(element = scope[i]))
        results.push(Element.extend(element));

    return results;
  },

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

function $$() {
  return $A(arguments).map(function(expression) {
    return expression.strip().split(/\s+/).inject([null], function(results, expr) {
      var selector = new Selector(expr);
      return results.map(selector.findElements.bind(selector)).flatten();
    });
  }).flatten();
}
var Field = {
  clear: function() {
    for (var i = 0; i < arguments.length; i++)
      $(arguments[i]).value = '';
  },

  focus: function(element) {
    $(element).focus();
  },

  present: function() {
    for (var i = 0; i < arguments.length; i++)
      if ($(arguments[i]).value == '') return false;
    return true;
  },

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

  activate: function(element) {
    element = $(element);
    element.focus();
    if (element.select)
      element.select();
  }
}

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

var Form = {
  serialize: function(form) {
    var elements = Form.getElements($(form));
    var queryComponents = new Array();

    for (var i = 0; i < elements.length; i++) {
      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }

    return queryComponents.join('&');
  },

  getElements: function(form) {
    form = $(form);
    var elements = new Array();

    for (var tagName in Form.Element.Serializers) {
      var tagElements = form.getElementsByTagName(tagName);
      for (var j = 0; j < tagElements.length; j++)
        elements.push(tagElements[j]);
    }
    return elements;
  },

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

    if (!typeName && !name)
      return inputs;

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

    return matchingInputs;
  },

  disable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.blur();
      element.disabled = 'true';
    }
  },

  enable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.disabled = '';
    }
  },

  findFirstElement: function(form) {
    return Form.getElements(form).find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    Field.activate(Form.findFirstElement(form));
  },

  reset: function(form) {
    $(form).reset();
  }
}

Form.Element = {
  serialize: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter) {
      var key = encodeURIComponent(parameter[0]);
      if (key.length == 0) return;

      if (parameter[1].constructor != Array)
        parameter[1] = [parameter[1]];

      return parameter[1].map(function(value) {
        return key + '=' + encodeURIComponent(value);
      }).join('&');
    }
  },

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

    if (parameter)
      return parameter[1];
  }
}

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'submit':
      case 'hidden':
      case 'password':
      case 'text':
        return Form.Element.Serializers.textarea(element);
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
    }
    return false;
  },

  inputSelector: function(element) {
    if (element.checked)
      return [element.name, element.value];
  },

  textarea: function(element) {
    return [element.name, element.value];
  },

  select: function(element) {
    return Form.Element.Serializers[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var value = '', opt, index = element.selectedIndex;
    if (index >= 0) {
      opt = element.options[index];
      value = opt.value || opt.text;
    }
    return [element.name, value];
  },

  selectMany: function(element) {
    var value = [];
    for (var i = 0; i < element.length; i++) {
      var opt = element.options[i];
      if (opt.selected)
        value.push(opt.value || opt.text);
    }
    return [element.name, value];
  }
}

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

var $F = Form.Element.getValue;

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

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

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

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

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

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

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

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  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() {
    var elements = Form.getElements(this.element);
    for (var i = 0; i < elements.length; i++)
      this.registerCallback(elements[i]);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        case 'password':
        case 'text':
        case 'textarea':
        case 'select-one':
        case 'select-multiple':
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

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

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

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,

  element: function(event) {
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    this._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      element.detachEvent('on' + name, observer);
    }
  }
});

/* prevent memory leaks in IE */
if (navigator.appVersion.match(/\bMSIE\b/))
  Event.observe(window, 'unload', Event.unloadCache, false);
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;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

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

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valueL, valueT];
  },

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

  // 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 = this.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 = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.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;
  },

  clone: function(source, target) {
    source = $(source);
    target = $(target);
    target.style.position = 'absolute';
    var offsets = this.cumulativeOffset(source);
    target.style.top    = offsets[1] + 'px';
    target.style.left   = offsets[0] + 'px';
    target.style.width  = source.offsetWidth + 'px';
    target.style.height = source.offsetHeight + 'px';
  },

  page: 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)
        if (Element.getStyle(element,'position')=='absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      valueT -= element.scrollTop  || 0;
      valueL -= element.scrollLeft || 0;
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

  clone: function(source, target) {
    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 = Position.page(source);

    // find coordinate system to use
    target = $(target);
    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(target,'position') == 'absolute') {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // 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)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    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';;
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    Position.prepare();

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

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.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 [valueL, valueT];
  }
}
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

var Scriptaculous = {
  Version: '1.6.1',
  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
  },
  load: function() {
    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       parseFloat(Prototype.Version.split(".")[0] + "." +
                  Prototype.Version.split(".")[1]) < 1.5)
       throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");

    $A(document.getElementsByTagName("script")).findAll( function(s) {
      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
    }).each( function(s) {
      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
      var includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
       function(include)
       {
       		//Scriptaculous.require(path+include+'.js')
       });
    });
  }
}

Scriptaculous.load();
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// See scriptaculous.js for full license.

var Builder = {
  NODEMAP: {
    AREA: 'map',
    CAPTION: 'table',
    COL: 'table',
    COLGROUP: 'table',
    LEGEND: 'fieldset',
    OPTGROUP: 'select',
    OPTION: 'select',
    PARAM: 'object',
    TBODY: 'table',
    TD: 'table',
    TFOOT: 'table',
    TH: 'table',
    THEAD: 'table',
    TR: 'table'
  },
  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  //       due to a Firefox bug
  node: function(elementName) {
    elementName = elementName.toUpperCase();
    
    // try innerHTML approach
    var parentTag = this.NODEMAP[elementName] || 'div';
    var parentElement = document.createElement(parentTag);
    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
    } catch(e) {}
    var element = parentElement.firstChild || null;
      
    // see if browser added wrapping tags
    if(element && (element.tagName != elementName))
      element = element.getElementsByTagName(elementName)[0];
    
    // fallback to createElement approach
    if(!element) element = document.createElement(elementName);
    
    // abort if nothing could be created
    if(!element) return;

    // attributes (or text)
    if(arguments[1])
      if(this._isStringOrNumber(arguments[1]) ||
        (arguments[1] instanceof Array)) {
          this._children(element, arguments[1]);
        } else {
          var attrs = this._attributes(arguments[1]);
          if(attrs.length) {
            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
              parentElement.innerHTML = "<" +elementName + " " +
                attrs + "></" + elementName + ">";
            } catch(e) {}
            element = parentElement.firstChild || null;
            // workaround firefox 1.0.X bug
            if(!element) {
              element = document.createElement(elementName);
              for(attr in arguments[1]) 
                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
            }
            if(element.tagName != elementName)
              element = parentElement.getElementsByTagName(elementName)[0];
            }
        } 

    // text, or array of children
    if(arguments[2])
      this._children(element, arguments[2]);

     return element;
  },
  _text: function(text) {
     return document.createTextNode(text);
  },
  _attributes: function(attributes) {
    var attrs = [];
    for(attribute in attributes)
      attrs.push((attribute=='className' ? 'class' : attribute) +
          '="' + attributes[attribute].toString().escapeHTML() + '"');
    return attrs.join(" ");
  },
  _children: function(element, children) {
    if(typeof children=='object') { // array can hold nodes and text
      children.flatten().each( function(e) {
        if(typeof e=='object')
          element.appendChild(e)
        else
          if(Builder._isStringOrNumber(e))
            element.appendChild(Builder._text(e));
      });
    } else
      if(Builder._isStringOrNumber(children)) 
         element.appendChild(Builder._text(children));
  },
  _isStringOrNumber: function(param) {
    return(typeof param=='string' || typeof param=='number');
  }
}
// Copyright (c) 2005 Marty Haught, Thomas Fuchs 
//
// See http://script.aculo.us for more info
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

if(!Control) var Control = {};
Control.Slider = Class.create();

// options:
//  axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider.prototype = {
  initialize: function(handle, track, options) {
    var slider = this;
    
    if(handle instanceof Array) {
      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 : this.handles[0].offsetWidth;

    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(
        (slider.options.sliderValue instanceof Array ? 
          slider.options.sliderValue[i] : slider.options.sliderValue) || 
         slider.range.start), i);
      Element.makePositioned(h); // fix IE
      Event.observe(h, "mousedown", slider.eventMouseDown);
    });
    
    Event.observe(this.track, "mousedown", this.eventMouseDown);
    Event.observe(document, "mouseup", this.eventMouseUp);
    Event.observe(document, "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.activeHandle    = this.handles[handleIdx];
      this.activeHandleIdx = handleIdx;
      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 - this.alignY : this.track.offsetWidth - 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)];
        if(handle==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;
        
          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);
      // fix AppleWebKit rendering
      if(navigator.appVersion.indexOf('AppleWebKit')>0) 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;
  }
}
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
// 
// See scriptaculous.js for full license.  

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

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

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

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

Element.setContentZoom = function(element, percent) {
  element = $(element);  
  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
}

Element.getOpacity = function(element){  
  var opacity;
  if (opacity = Element.getStyle(element, 'opacity'))  
    return parseFloat(opacity);  
  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
  return 1.0;  
}

Element.setOpacity = function(element, value){  
  element= $(element);  
  if (value == 1){
    Element.setStyle(element, { opacity: 
      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
      0.999999 : null });
    if(/MSIE/.test(navigator.userAgent))  
      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
  } else {  
    if(value < 0.00001) value = 0;  
    Element.setStyle(element, {opacity: value});
    if(/MSIE/.test(navigator.userAgent))  
     Element.setStyle(element, 
       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
                 'alpha(opacity='+value*100+')' });  
  }
}  
 
Element.getInlineOpacity = function(element){  
  return $(element).style.opacity || '';
}  

Element.childrenWithClassName = function(element, className, findFirst) {
  var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)");
  var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { 
    return (c.className && c.className.match(classNameRegExp));
  });
  if(!results) results = [];
  return results;
}

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

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

Array.prototype.call = function() {
  var args = arguments;
  this.each(function(f){ f.apply(this, args) });
}

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

var Effect = {
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
    element = $(element);
    $A(element.childNodes).each( function(child) {
      if(child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            Builder.node('span',{style: tagifyStyle},
              character == ' ' ? String.fromCharCode(160) : character), 
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if(((typeof element == 'object') || 
        (typeof element == 'function')) && 
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;
      
    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || {});
    var masterDelay = options.delay;

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

var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {}

Effect.Transitions.linear = function(pos) {
  return pos;
}
Effect.Transitions.sinoidal = function(pos) {
  return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
Effect.Transitions.reverse  = function(pos) {
  return 1-pos;
}
Effect.Transitions.flicker = function(pos) {
  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
}
Effect.Transitions.wobble = function(pos) {
  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
Effect.Transitions.pulse = function(pos) {
  return (Math.floor(pos*10) % 2 == 0 ? 
    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
}
Effect.Transitions.none = function(pos) {
  return 0;
}
Effect.Transitions.full = function(pos) {
  return 1;
}

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

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();
    
    var position = (typeof effect.options.queue == 'string') ? 
      effect.options.queue : effect.options.queue.position;
    
    switch(position) {
      case 'front':
        // move unstarted effects after this effect  
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }
    
    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);
    
    if(!this.interval) 
      this.interval = setInterval(this.loop.bind(this), 40);
  },
  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();
    this.effects.invoke('loop', timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if(typeof queueName != 'string') return queueName;
    
    if(!this.instances[queueName])
      this.instances[queueName] = new Effect.ScopedQueue();
      
    return this.instances[queueName];
  }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
  transition: Effect.Transitions.sinoidal,
  duration:   1.0,   // seconds
  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
  sync:       false, // true for combining
  from:       0.0,
  to:         1.0,
  delay:      0.0,
  queue:      'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
  position: null,
  start: function(options) {
    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.event('beforeStart');
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if(timePos >= this.startOn) {
      if(timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if(this.finish) this.finish(); 
        this.event('afterFinish');
        return;  
      }
      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
      var frame = Math.round(pos * this.options.fps * this.options.duration);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  render: function(pos) {
    if(this.state == 'idle') {
      this.state = 'running';
      this.event('beforeSetup');
      if(this.setup) this.setup();
      this.event('afterSetup');
    }
    if(this.state == 'running') {
      if(this.options.transition) pos = this.options.transition(pos);
      pos *= (this.options.to-this.options.from);
      pos += this.options.from;
      this.position = pos;
      this.event('beforeUpdate');
      if(this.update) this.update(pos);
      this.event('afterUpdate');
    }
  },
  cancel: function() {
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
}

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

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

Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Bug in Opera: Opera returns the "real" position of a static element or
    // relative element that does not have top/left explicitly set.
    // ==> Always set top and left for position relative elements in your stylesheets 
    // (to 0 if you do not need them) 
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if(this.options.mode == 'absolute') {
      // absolute movement, so we need to calc deltaX and deltaY
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: this.options.x  * position + this.originalLeft + 'px',
      top:  this.options.y  * position + this.originalTop  + 'px'
    });
  }
});

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

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element)
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');
    
    this.originalStyle = {};
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
    
    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%'].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 + 'px';
    if(this.options.scaleY) d.height = height + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

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

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    this.start(arguments[1] || {});
  },
  setup: function() {
    Position.prepare();
    var offsets = Position.cumulativeOffset(this.element);
    if(this.options.offset) offsets[1] += this.options.offset;
    var max = window.innerHeight ? 
      window.height - window.innerHeight :
      document.body.scrollHeight - 
        (document.documentElement.clientHeight ? 
          document.documentElement.clientHeight : document.body.clientHeight);
    this.scrollStart = Position.deltaY;
    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
  },
  update: function(position) {
    Position.prepare();
    window.scrollTo(Position.deltaX, 
      this.scrollStart + (position*this.delta));
  }
});

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

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

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

Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') };
  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) {
        effect.effects[0].element.setStyle({position: 'absolute'}); },
      afterFinishInternal: function(effect) {
         effect.effects[0].element.hide();
         effect.effects[0].element.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();
        effect.element.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();
        effect.element.setStyle({height: '0px'});
        effect.element.show(); 
      },  
      afterFinishInternal: function(effect) {
        effect.element.undoClipping();
      }
    }, arguments[1] || {})
  );
}

Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  return new Effect.Appear(element, { 
    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();
          effect.element.makeClipping();
        },
        afterFinishInternal: function(effect) {
          effect.element.hide();
          effect.element.undoClipping();
          effect.element.undoPositioned();
          effect.element.setStyle({opacity: oldOpacity});
        }
      })
    }
  });
}

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();
          effect.effects[0].element.undoPositioned();
          effect.effects[0].element.setStyle(oldStyle);
        } 
      }, arguments[1] || {}));
}

Effect.Shake = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element, 
      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
        effect.element.undoPositioned();
        effect.element.setStyle(oldStyle);
  }}) }}) }}) }}) }}) }});
}

Effect.SlideDown = function(element) {
  element = $(element);
  element.cleanWhitespace();
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = $(element.firstChild).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.firstChild.makePositioned();
      if(window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping();
      effect.element.setStyle({height: '0px'});
      effect.element.show(); },
    afterUpdateInternal: function(effect) {
      effect.element.firstChild.setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping(); 
      // IE will crash if child is undoPositioned first
      if(/MSIE/.test(navigator.userAgent)){
        effect.element.undoPositioned();
        effect.element.firstChild.undoPositioned();
      }else{
        effect.element.firstChild.undoPositioned();
        effect.element.undoPositioned();
      }
      effect.element.firstChild.setStyle({bottom: oldInnerBottom}); }
    }, arguments[1] || {})
  );
}
  
Effect.SlideUp = function(element) {
  element = $(element);
  element.cleanWhitespace();
  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
  return new Effect.Scale(element, window.opera ? 0 : 1,
   Object.extend({ scaleContent: false, 
    scaleX: false, 
    scaleMode: 'box',
    scaleFrom: 100,
    restoreAfterFinish: true,
    beforeStartInternal: function(effect) {
      effect.element.makePositioned();
      effect.element.firstChild.makePositioned();
      if(window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping();
      effect.element.show(); },  
    afterUpdateInternal: function(effect) {
      effect.element.firstChild.setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); },
    afterFinishInternal: function(effect) {
      effect.element.hide();
      effect.element.undoClipping();
      effect.element.firstChild.undoPositioned();
      effect.element.undoPositioned();
      effect.element.setStyle({bottom: oldInnerBottom}); }
   }, arguments[1] || {})
  );
}

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

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();
      effect.element.makeClipping();
      effect.element.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'});
               effect.effects[0].element.show(); 
             },
             afterFinishInternal: function(effect) {
               effect.effects[0].element.undoClipping();
               effect.effects[0].element.undoPositioned();
               effect.effects[0].element.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();
           effect.effects[0].element.makeClipping(); },
         afterFinishInternal: function(effect) {
           effect.effects[0].element.hide();
           effect.effects[0].element.undoClipping();
           effect.effects[0].element.undoPositioned();
           effect.effects[0].element.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)) };
  reverser.bind(transition);
  return new Effect.Opacity(element, 
    Object.extend(Object.extend({  duration: 3.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(element);
  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();
        effect.element.undoClipping(); 
        effect.element.setStyle(oldStyle);
      } });
  }}, arguments[1] || {}));
};

['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( 
  function(f) { Element.Methods[f] = Element[f]; }
);

Element.Methods.visualEffect = function(element, effect, options) {
  s = effect.gsub(/_/, '-').camelize();
  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
  new Effect[effect_class](element, options);
  return $(element);
};

Element.addMethods();
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
// Contributors:
//  Richard Livsey
//  Rahul Bhargava
//  Rob Wills
// 
// See scriptaculous.js for full license.

// Autocompleter.Base handles all the autocompletion functionality 
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least, 
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method 
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most 
// useful when one of the tokens is \n (a newline), as it 
// allows smart autocompletion after linebreaks.

var Autocompleter = {}
Autocompleter.Base = function() {};
Autocompleter.Base.prototype = {
  baseInitialize: function(element, update, options) {
    this.element     = $(element); 
    this.update      = $(update);  
    this.hasFocus    = false; 
    this.changed     = false; 
    this.active      = false; 
    this.index       = 0;     
    this.entryCount  = 0;
    
    if (this.setOptions)
      this.setOptions(options);
    else
      this.options = options || {};

    this.options.paramName    = this.options.paramName || this.element.name;
    this.options.tokens       = this.options.tokens || [];
    this.options.frequency    = this.options.frequency || 0.4;
    this.options.minChars     = this.options.minChars || 1;
    this.options.onShow       = this.options.onShow || 
    function(element, update){ 
      if(!update.style.position || update.style.position=='absolute') {
        update.style.position = 'absolute';
        Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
      }
      Effect.Appear(update,{duration:0.15});
    };
    this.options.onHide = this.options.onHide || 
    function(element, update){ new Effect.Fade(update,{duration:0.15}) };

    if (typeof(this.options.tokens) == 'string') 
      this.options.tokens = new Array(this.options.tokens);

    this.observer = null;
    
    this.element.setAttribute('autocomplete','off');

    Element.hide(this.update);

    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
  },

  show: function() {	
  	if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
    if(!this.iefix && 
      (navigator.appVersion.indexOf('MSIE')>0) &&
      (navigator.userAgent.indexOf('Opera')<0) &&
      (Element.getStyle(this.update, 'position')=='absolute')) {
      new Insertion.After(this.update, 
       '<iframe id="' + this.update.id + '_iefix" '+
       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
      this.iefix = $(this.update.id+'_iefix');
    }
    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
  },
  
  fixIEOverlapping: function() {
    Position.clone(this.update, this.iefix);
    this.iefix.style.zIndex = 1;
    this.update.style.zIndex = 2;
    Element.show(this.iefix);
  },

  hide: function() {
    this.stopIndicator();
    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
    if(this.iefix) Element.hide(this.iefix);
  },

  startIndicator: function() {
    if(this.options.indicator) Element.show(this.options.indicator);
  },

  stopIndicator: function() {
    if(this.options.indicator) Element.hide(this.options.indicator);
  },

  onKeyPress: function(event) {
    if(this.active)
      switch(event.keyCode) {
       case Event.KEY_TAB:
       case Event.KEY_RETURN:
         this.selectEntry();
         Event.stop(event);
       case Event.KEY_ESC:
         this.hide();
         this.active = false;
         Event.stop(event);
         return;
       case Event.KEY_LEFT:
       case Event.KEY_RIGHT:
         return;
       case Event.KEY_UP:
         this.markPrevious();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
       case Event.KEY_DOWN:
         this.markNext();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
      }
     else 
       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
         (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;

    this.changed = true;
    this.hasFocus = true;

    if(this.observer) clearTimeout(this.observer);
      this.observer = 
        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  },

  activate: function() {
    this.changed = false;
    this.hasFocus = true;
    this.getUpdatedChoices();
  },

  onHover: function(event) {
    var element = Event.findElement(event, 'LI');
    if(this.index != element.autocompleteIndex) 
    {
        this.index = element.autocompleteIndex;
        this.render();
    }
    Event.stop(event);
  },
  
  onClick: function(event) {
    var element = Event.findElement(event, 'LI');
    this.index = element.autocompleteIndex;
    this.selectEntry();
    this.hide();
  },
  
  onBlur: function(event) {
    // needed to make click events working
    setTimeout(this.hide.bind(this), 250);
    this.hasFocus = false;
    this.active = false;     
  }, 
  
  render: function() {
    if(this.entryCount > 0) {
      for (var i = 0; i < this.entryCount; i++)
        this.index==i ? 
          Element.addClassName(this.getEntry(i),"selected") : 
          Element.removeClassName(this.getEntry(i),"selected");
        
      if(this.hasFocus) { 
        this.show();
        this.active = true;
      }
    } else {
      this.active = false;
      this.hide();
    }
  },
  
  markPrevious: function() {
    if(this.index > 0) this.index--
      else this.index = this.entryCount-1;
  },
  
  markNext: function() {
    if(this.index < this.entryCount-1) this.index++
      else this.index = 0;
  },
  
  getEntry: function(index) {
    return this.update.firstChild.childNodes[index];
  },
  
  getCurrentEntry: function() {
    return this.getEntry(this.index);
  },
  
  selectEntry: function() {
    this.active = false;
    this.updateElement(this.getCurrentEntry());
  },

  updateElement: function(selectedElement) {
    if (this.options.updateElement) {
      this.options.updateElement(selectedElement);
      return;
    }
    var value = '';
    if (this.options.select) {
      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
    } else
      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
    
    var lastTokenPos = this.findLastToken();
    if (lastTokenPos != -1) {
      var newValue = this.element.value.substr(0, lastTokenPos + 1);
      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
      if (whitespace)
        newValue += whitespace[0];
      this.element.value = newValue + value;
    } else {
      this.element.value = value;
    }
    this.element.focus();
    
    if (this.options.afterUpdateElement)
      this.options.afterUpdateElement(this.element, selectedElement);
  },

  updateChoices: function(choices) {
    if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.firstChild);

      if(this.update.firstChild && this.update.firstChild.childNodes) {
        this.entryCount = 
          this.update.firstChild.childNodes.length;
        for (var i = 0; i < this.entryCount; i++) {
          var entry = this.getEntry(i);
          entry.autocompleteIndex = i;
          this.addObservers(entry);
        }
      } else { 
        this.entryCount = 0;
      }

      this.stopIndicator();

      this.index = 0;
      this.render();
    }
  },

  addObservers: function(element) {
    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
  },

  onObserverEvent: function() {
    this.changed = false;   
    if(this.getToken().length>=this.options.minChars) {
      this.startIndicator();
      this.getUpdatedChoices();
    } else {
      this.active = false;
      this.hide();
    }
  },

  getToken: function() {
    var tokenPos = this.findLastToken();
    if (tokenPos != -1)
      var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
    else
      var ret = this.element.value;

    return /\n/.test(ret) ? '' : ret;
  },

  findLastToken: function() {
    var lastTokenPos = -1;

    for (var i=0; i<this.options.tokens.length; i++) {
      var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
      if (thisTokenPos > lastTokenPos)
        lastTokenPos = thisTokenPos;
    }
    return lastTokenPos;
  }
}

Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
  initialize: function(element, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = url;
  },

  getUpdatedChoices: function() {
    entry = encodeURIComponent(this.options.paramName) + '=' + 
      encodeURIComponent(this.getToken());

    this.options.parameters = this.options.callback ?
      this.options.callback(this.element, entry) : entry;

    if(this.options.defaultParams) 
      this.options.parameters += '&' + this.options.defaultParams;

    new Ajax.Request(this.url, this.options);
  },

  onComplete: function(request) {
    this.updateChoices(request.responseText);
  }

});

// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
//                    text only at the beginning of strings in the 
//                    autocomplete array. Defaults to true, which will
//                    match text at the beginning of any *word* in the
//                    strings in the autocomplete array. If you want to
//                    search anywhere in the string, additionally set
//                    the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
//                   a partial match (unlike minChars, which defines
//                   how many characters are required to do any match
//                   at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
//                 Defaults to true.
//
// It's possible to pass in a custom function as the 'selector' 
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.

Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
  initialize: function(element, update, array, options) {
    this.baseInitialize(element, update, options);
    this.options.array = array;
  },

  getUpdatedChoices: function() {
    this.updateChoices(this.options.selector(this));
  },

  setOptions: function(options) {
    this.options = Object.extend({
      choices: 10,
      partialSearch: true,
      partialChars: 2,
      ignoreCase: true,
      fullSearch: false,
      selector: function(instance) {
        var ret       = []; // Beginning matches
        var partial   = []; // Inside matches
        var entry     = instance.getToken();
        var count     = 0;
		      
        for (var i = 0; i < instance.options.array.length &&  
          ret.length < instance.options.choices ; i++) { 

          var elem = instance.options.array[i];
          
          var foundPos = instance.options.ignoreCase ? 
            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
            elem.indexOf(entry);

          while (foundPos != -1) {
            if (foundPos == 0 && elem.length != entry.length) { 
              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
                elem.substr(entry.length) + "</li>");
              break;
            } else if (entry.length >= instance.options.partialChars && 
              instance.options.partialSearch && foundPos != -1) {
              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
                  foundPos + entry.length) + "</li>");
                break;
              }
            }

            foundPos = instance.options.ignoreCase ? 
              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
              elem.indexOf(entry, foundPos + 1);

          }
        }
        if (partial.length)
          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
        return "<ul>" + ret.join('') + "</ul>";
      }
    }, options || {});
  }
});

// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor

// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
  setTimeout(function() {
    Field.activate(field);
  }, 1);
}

Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
  initialize: function(element, url, options) {
    this.url = url;
    this.element = $(element);

    this.options = Object.extend({
      okButton: true,
      okText: "ok",
      cancelLink: true,
      cancelText: "cancel",
      savingText: "Saving...",
      clickToEditText: "Click to edit",
      okText: "ok",
      rows: 1,
      onComplete: function(transport, element) {
        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
      },
      onFailure: function(transport) {
        alert("Error communicating with the server: " + transport.responseText.stripTags());
      },
      callback: function(form) {
        return Form.serialize(form);
      },
      handleLineBreaks: true,
      loadingText: 'Loading...',
      savingClassName: 'inplaceeditor-saving',
      loadingClassName: 'inplaceeditor-loading',
      formClassName: 'inplaceeditor-form',
      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
      highlightendcolor: "#FFFFFF",
      externalControl: null,
      submitOnBlur: false,
      ajaxOptions: {},
      evalScripts: false
    }, options || {});

    if(!this.options.formId && this.element.id) {
      this.options.formId = this.element.id + "-inplaceeditor";
      if ($(this.options.formId)) {
        // there's already a form with that name, don't specify an id
        this.options.formId = null;
      }
    }
    
    if (this.options.externalControl) {
      this.options.externalControl = $(this.options.externalControl);
    }
    
    this.originalBackground = Element.getStyle(this.element, 'background-color');
    if (!this.originalBackground) {
      this.originalBackground = "transparent";
    }
    
    this.element.title = this.options.clickToEditText;
    
    this.onclickListener = this.enterEditMode.bindAsEventListener(this);
    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
    Event.observe(this.element, 'click', this.onclickListener);
    Event.observe(this.element, 'mouseover', this.mouseoverListener);
    Event.observe(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.observe(this.options.externalControl, 'click', this.onclickListener);
      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  },
  enterEditMode: function(evt) {
    if (this.saving) return;
    if (this.editing) return;
    this.editing = true;
    this.onEnterEditMode();
    if (this.options.externalControl) {
      Element.hide(this.options.externalControl);
    }
    Element.hide(this.element);
    this.createForm();
    this.element.parentNode.insertBefore(this.form, this.element);
    Field.scrollFreeActivate(this.editField);
    // stop the event to avoid a page refresh in Safari
    if (evt) {
      Event.stop(evt);
    }
    return false;
  },
  createForm: function() {
    this.form = document.createElement("form");
    this.form.id = this.options.formId;
    Element.addClassName(this.form, this.options.formClassName)
    this.form.onsubmit = this.onSubmit.bind(this);

    this.createEditField();

    if (this.options.textarea) {
      var br = document.createElement("br");
      this.form.appendChild(br);
    }

    if (this.options.okButton) {
      okButton = document.createElement("input");
      okButton.type = "submit";
      okButton.value = this.options.okText;
      okButton.className = 'editor_ok_button';
      this.form.appendChild(okButton);
    }

    if (this.options.cancelLink) {
      cancelLink = document.createElement("a");
      cancelLink.href = "#";
      cancelLink.appendChild(document.createTextNode(this.options.cancelText));
      cancelLink.onclick = this.onclickCancel.bind(this);
      cancelLink.className = 'editor_cancel';      
      this.form.appendChild(cancelLink);
    }
  },
  hasHTMLLineBreaks: function(string) {
    if (!this.options.handleLineBreaks) return false;
    return string.match(/<br/i) || string.match(/<p>/i);
  },
  convertHTMLLineBreaks: function(string) {
    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
  },
  createEditField: function() {
    var text;
    if(this.options.loadTextURL) {
      text = this.options.loadingText;
    } else {
      text = this.getText();
    }

    var obj = this;
    
    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
      this.options.textarea = false;
      var textField = document.createElement("input");
      textField.obj = this;
      textField.type = "text";
      textField.name = "value";
      textField.value = text;
      textField.style.backgroundColor = this.options.highlightcolor;
      textField.className = 'editor_field';
      var size = this.options.size || this.options.cols || 0;
      if (size != 0) textField.size = size;
      if (this.options.submitOnBlur)
        textField.onblur = this.onSubmit.bind(this);
      this.editField = textField;
    } else {
      this.options.textarea = true;
      var textArea = document.createElement("textarea");
      textArea.obj = this;
      textArea.name = "value";
      textArea.value = this.convertHTMLLineBreaks(text);
      textArea.rows = this.options.rows;
      textArea.cols = this.options.cols || 40;
      textArea.className = 'editor_field';      
      if (this.options.submitOnBlur)
        textArea.onblur = this.onSubmit.bind(this);
      this.editField = textArea;
    }
    
    if(this.options.loadTextURL) {
      this.loadExternalText();
    }
    this.form.appendChild(this.editField);
  },
  getText: function() {
    return this.element.innerHTML;
  },
  loadExternalText: function() {
    Element.addClassName(this.form, this.options.loadingClassName);
    this.editField.disabled = true;
    new Ajax.Request(
      this.options.loadTextURL,
      Object.extend({
        asynchronous: true,
        onComplete: this.onLoadedExternalText.bind(this)
      }, this.options.ajaxOptions)
    );
  },
  onLoadedExternalText: function(transport) {
    Element.removeClassName(this.form, this.options.loadingClassName);
    this.editField.disabled = false;
    this.editField.value = transport.responseText.stripTags();
  },
  onclickCancel: function() {
    this.onComplete();
    this.leaveEditMode();
    return false;
  },
  onFailure: function(transport) {
    this.options.onFailure(transport);
    if (this.oldInnerHTML) {
      this.element.innerHTML = this.oldInnerHTML;
      this.oldInnerHTML = null;
    }
    return false;
  },
  onSubmit: function() {
    // onLoading resets these so we need to save them away for the Ajax call
    var form = this.form;
    var value = this.editField.value;
    
    // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
    // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
    // to be displayed indefinitely
    this.onLoading();
    
    if (this.options.evalScripts) {
      new Ajax.Request(
        this.url, Object.extend({
          parameters: this.options.callback(form, value),
          onComplete: this.onComplete.bind(this),
          onFailure: this.onFailure.bind(this),
          asynchronous:true, 
          evalScripts:true
        }, this.options.ajaxOptions));
    } else  {
      new Ajax.Updater(
        { success: this.element,
          // don't update on failure (this could be an option)
          failure: null }, 
        this.url, Object.extend({
          parameters: this.options.callback(form, value),
          onComplete: this.onComplete.bind(this),
          onFailure: this.onFailure.bind(this)
        }, this.options.ajaxOptions));
    }
    // stop the event to avoid a page refresh in Safari
    if (arguments.length > 1) {
      Event.stop(arguments[0]);
    }
    return false;
  },
  onLoading: function() {
    this.saving = true;
    this.removeForm();
    this.leaveHover();
    this.showSaving();
  },
  showSaving: function() {
    this.oldInnerHTML = this.element.innerHTML;
    this.element.innerHTML = this.options.savingText;
    Element.addClassName(this.element, this.options.savingClassName);
    this.element.style.backgroundColor = this.originalBackground;
    Element.show(this.element);
  },
  removeForm: function() {
    if(this.form) {
      if (this.form.parentNode) Element.remove(this.form);
      this.form = null;
    }
  },
  enterHover: function() {
    if (this.saving) return;
    this.element.style.backgroundColor = this.options.highlightcolor;
    if (this.effect) {
      this.effect.cancel();
    }
    Element.addClassName(this.element, this.options.hoverClassName)
  },
  leaveHover: function() {
    if (this.options.backgroundColor) {
      this.element.style.backgroundColor = this.oldBackground;
    }
    Element.removeClassName(this.element, this.options.hoverClassName)
    if (this.saving) return;
    this.effect = new Effect.Highlight(this.element, {
      startcolor: this.options.highlightcolor,
      endcolor: this.options.highlightendcolor,
      restorecolor: this.originalBackground
    });
  },
  leaveEditMode: function() {
    Element.removeClassName(this.element, this.options.savingClassName);
    this.removeForm();
    this.leaveHover();
    this.element.style.backgroundColor = this.originalBackground;
    Element.show(this.element);
    if (this.options.externalControl) {
      Element.show(this.options.externalControl);
    }
    this.editing = false;
    this.saving = false;
    this.oldInnerHTML = null;
    this.onLeaveEditMode();
  },
  onComplete: function(transport) {
    this.leaveEditMode();
    this.options.onComplete.bind(this)(transport, this.element);
  },
  onEnterEditMode: function() {},
  onLeaveEditMode: function() {},
  dispose: function() {
    if (this.oldInnerHTML) {
      this.element.innerHTML = this.oldInnerHTML;
    }
    this.leaveEditMode();
    Event.stopObserving(this.element, 'click', this.onclickListener);
    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  }
};

Ajax.InPlaceCollectionEditor = Class.create();
Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
  createEditField: function() {
    if (!this.cached_selectTag) {
      var selectTag = document.createElement("select");
      var collection = this.options.collection || [];
      var optionTag;
      collection.each(function(e,i) {
        optionTag = document.createElement("option");
        optionTag.value = (e instanceof Array) ? e[0] : e;
        if(this.options.value==optionTag.value) optionTag.selected = true;
        optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
        selectTag.appendChild(optionTag);
      }.bind(this));
      this.cached_selectTag = selectTag;
    }

    this.editField = this.cached_selectTag;
    if(this.options.loadTextURL) this.loadExternalText();
    this.form.appendChild(this.editField);
    this.options.callback = function(form, value) {
      return "value=" + encodeURIComponent(value);
    }
  }
});

// Delayed observer, like Form.Element.Observer, 
// but waits for delay after last key input
// Ideal for live-search fields

Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
  initialize: function(element, delay, callback) {
    this.delay     = delay || 0.5;
    this.element   = $(element);
    this.callback  = callback;
    this.timer     = null;
    this.lastValue = $F(this.element); 
    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
  },
  delayedListener: function(event) {
    if(this.lastValue == $F(this.element)) return;
    if(this.timer) clearTimeout(this.timer);
    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
    this.lastValue = $F(this.element);
  },
  onTimerEvent: function() {
    this.timer = null;
    this.callback(this.element, $F(this.element));
  }
};

// -----------------------------------------------------------------------------------
//
//	Lightbox v2.02
//	by Lokesh Dhakar - http://www.huddletogether.com
//	3/31/06
//
//	For more information on this script, visit:
//	http://huddletogether.com/projects/lightbox2/
//
//	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
//
//	Credit also due to those who have helped, inspired, and made their code available to the public.
//	Including: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.org), Thomas Fuchs(mir.aculo.us), and others.
//
//
// -----------------------------------------------------------------------------------
/*

	Table of Contents
	-----------------
	Configuration
	Global Variables

	Extending Built-in Objects
	- Object.extend(Element)
	- Array.prototype.removeDuplicates()
	- Array.prototype.empty()

	Lightbox Class Declaration
	- initialize()
	- start()
	- changeImage()
	- resizeImageContainer()
	- showImage()
	- updateDetails()
	- updateNav()
	- enableKeyboardNav()
	- disableKeyboardNav()
	- keyboardAction()
	- preloadNeighborImages()
	- end()

	Miscellaneous Functions
	- getPageScroll()
	- getPageSize()
	- getKey()
	- listenKey()
	- showSelectBoxes()
	- hideSelectBoxes()
	- pause()
	- initLightbox()

	Function Calls
	- addLoadEvent(initLightbox)

*/
// -----------------------------------------------------------------------------------

//
//	Configuration
//
var fileLoadingImage = "static/images/layout/lb/loading.gif";
var fileBottomNavCloseImage = "static/images/layout/lb/close.gif";

var resizeSpeed = 7;	// controls the speed of the image resizing (1=slowest and 10=fastest)

var borderSize = 10;	//if you adjust the padding in the CSS, you will need to update this variable

// -----------------------------------------------------------------------------------

//
//	Global Variables
//
var imageArray = new Array;
var activeImage;

if(resizeSpeed > 10){ resizeSpeed = 10;}
if(resizeSpeed < 1){ resizeSpeed = 1;}
resizeDuration = (11 - resizeSpeed) * 0.15;

// -----------------------------------------------------------------------------------

//
//	Additional methods for Element added by SU, Couloir
//	- further additions by Lokesh Dhakar (huddletogether.com)
//
Object.extend(Element, {
	getWidth: function(element) {
	   	element = $(element);
	   	return element.offsetWidth;
	},
	setWidth: function(element,w) {
	   	element = $(element);
    	element.style.width = w +"px";
	},
	setHeight: function(element,h) {
   		element = $(element);
    	element.style.height = h +"px";
	},
	setTop: function(element,t) {
	   	element = $(element);
    	element.style.top = t +"px";
	},
	setSrc: function(element,src) {
    	element = $(element);
    	element.src = src;
	},
	setHref: function(element,href) {
    	element = $(element);
    	element.href = href;
	},
	setInnerHTML: function(element,content) {
		element = $(element);
		element.innerHTML = content;
	}
});

// -----------------------------------------------------------------------------------

//
//	Extending built-in Array object
//	- array.removeDuplicates()
//	- array.empty()
//
Array.prototype.removeDuplicates = function () {
	for(i = 1; i < this.length; i++){
		if(this[i][0] == this[i-1][0]){
			this.splice(i,1);
		}
	}
}

// -----------------------------------------------------------------------------------

Array.prototype.empty = function () {
	for(i = 0; i <= this.length; i++){
		this.shift();
	}
}

// -----------------------------------------------------------------------------------

//
//	Lightbox Class Declaration
//	- initialize()
//	- start()
//	- changeImage()
//	- resizeImageContainer()
//	- showImage()
//	- updateDetails()
//	- updateNav()
//	- enableKeyboardNav()
//	- disableKeyboardNav()
//	- keyboardNavAction()
//	- preloadNeighborImages()
//	- end()
//
//	Structuring of code inspired by Scott Upton (http://www.uptonic.com/)
//
var Lightbox = Class.create();

Lightbox.prototype = {

	// initialize()
	// Constructor runs on completion of the DOM loading. Loops through anchor tags looking for
	// 'lightbox' references and applies onclick events to appropriate links. The 2nd section of
	// the function inserts html at the bottom of the page which is used to display the shadow
	// overlay and the image container.
	//
	initialize: function() {
		if (!document.getElementsByTagName){ return; }
		var anchors = document.getElementsByTagName('a');

		// loop through all anchor tags
		for (var i=0; i<anchors.length; i++){
			var anchor = anchors[i];

			var relAttribute = String(anchor.getAttribute('rel'));

			// use the string.match() method to catch 'lightbox' references in the rel attribute
			if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
				anchor.onclick = function () {myLightbox.start(this); return false;}
			}
		}

		// The rest of this code inserts html at the bottom of the page that looks similar to this:
		//
		//	<div id="overlay"></div>
		//	<div id="lightbox">
		//		<div id="outerImageContainer">
		//			<div id="imageContainer">
		//				<img id="lightboxImage">
		//				<div style="" id="hoverNav">
		//					<a href="#" id="prevLink"></a>
		//					<a href="#" id="nextLink"></a>
		//				</div>
		//				<div id="loading">
		//					<a href="#" id="loadingLink">
		//						<img src="images/loading.gif">
		//					</a>
		//				</div>
		//			</div>
		//		</div>
		//		<div id="imageDataContainer">
		//			<div id="imageData">
		//				<div id="imageDetails">
		//					<span id="caption"></span>
		//					<span id="numberDisplay"></span>
		//				</div>
		//				<div id="bottomNav">
		//					<a href="#" id="bottomNavClose">
		//						<img src="images/close.gif">
		//					</a>
		//				</div>
		//			</div>
		//		</div>
		//	</div>


		var objBody = document.getElementsByTagName("body").item(0);

		var objOverlay = document.createElement("div");
		objOverlay.setAttribute('id','overlay');
		objOverlay.style.display = 'none';
		objOverlay.onclick = function() { myLightbox.end(); return false; }
		objBody.appendChild(objOverlay);

		var objLightbox = document.createElement("div");
		objLightbox.setAttribute('id','lightbox');
		objLightbox.style.display = 'none';
		objBody.appendChild(objLightbox);

		var objOuterImageContainer = document.createElement("div");
		objOuterImageContainer.setAttribute('id','outerImageContainer');
		objLightbox.appendChild(objOuterImageContainer);

		var objImageContainer = document.createElement("div");
		objImageContainer.setAttribute('id','imageContainer');
		objOuterImageContainer.appendChild(objImageContainer);

		var objLightboxImage = document.createElement("img");
		objLightboxImage.setAttribute('id','lightboxImage');
		objImageContainer.appendChild(objLightboxImage);

		var objHoverNav = document.createElement("div");
		objHoverNav.setAttribute('id','hoverNav');
		objImageContainer.appendChild(objHoverNav);

		var objPrevLink = document.createElement("a");
		objPrevLink.setAttribute('id','prevLink');
		objPrevLink.setAttribute('href','#');
		objHoverNav.appendChild(objPrevLink);

		var objNextLink = document.createElement("a");
		objNextLink.setAttribute('id','nextLink');
		objNextLink.setAttribute('href','#');
		objHoverNav.appendChild(objNextLink);

		var objLoading = document.createElement("div");
		objLoading.setAttribute('id','loading');
		objImageContainer.appendChild(objLoading);

		var objLoadingLink = document.createElement("a");
		objLoadingLink.setAttribute('id','loadingLink');
		objLoadingLink.setAttribute('href','#');
		objLoadingLink.onclick = function() { myLightbox.end(); return false; }
		objLoading.appendChild(objLoadingLink);

		var objLoadingImage = document.createElement("img");
		objLoadingImage.setAttribute('src', fileLoadingImage);
		objLoadingLink.appendChild(objLoadingImage);

		var objImageDataContainer = document.createElement("div");
		objImageDataContainer.setAttribute('id','imageDataContainer');
		objImageDataContainer.className = 'clearfix';
		objLightbox.appendChild(objImageDataContainer);

		var objImageData = document.createElement("div");
		objImageData.setAttribute('id','imageData');
		objImageDataContainer.appendChild(objImageData);

		var objImageDetails = document.createElement("div");
		objImageDetails.setAttribute('id','imageDetails');
		objImageData.appendChild(objImageDetails);

		var objCaption = document.createElement("span");
		objCaption.setAttribute('id','caption');
		objImageDetails.appendChild(objCaption);

		var objNumberDisplay = document.createElement("span");
		objNumberDisplay.setAttribute('id','numberDisplay');
		objImageDetails.appendChild(objNumberDisplay);

		var objBottomNav = document.createElement("div");
		objBottomNav.setAttribute('id','bottomNav');
		objImageData.appendChild(objBottomNav);

		var objBottomNavCloseLink = document.createElement("a");
		objBottomNavCloseLink.setAttribute('id','bottomNavClose');
		objBottomNavCloseLink.setAttribute('href','#');
		objBottomNavCloseLink.onclick = function() { myLightbox.end(); return false; }
		objBottomNav.appendChild(objBottomNavCloseLink);

		var objBottomNavCloseImage = document.createElement("img");
		objBottomNavCloseImage.setAttribute('src', fileBottomNavCloseImage);
		objBottomNavCloseLink.appendChild(objBottomNavCloseImage);
	},

	//
	//	start()
	//	Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
	//
	start: function(imageLink) {

		hideSelectBoxes();

		// stretch overlay to fill page and fade in
		var arrayPageSize = getPageSize();
		Element.setHeight('overlay', arrayPageSize[1]);
		new Effect.Appear('overlay', { duration: 0.2, from: 0.0, to: 0.8 });

		imageArray = [];
		imageNum = 0;

		if (!document.getElementsByTagName){ return; }
		var anchors = document.getElementsByTagName('a');

		// if image is NOT part of a set..
		if((imageLink.getAttribute('rel') == 'lightbox')){
			// add single image to imageArray
			imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));
		} else {
		// if image is part of a set..

			// loop through anchors, find other images in set, and add them to imageArray
			for (var i=0; i<anchors.length; i++){
				var anchor = anchors[i];
				if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel'))){
					imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
				}
			}
			imageArray.removeDuplicates();
			while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
		}

		// calculate top offset for the lightbox and display
		var arrayPageSize = getPageSize();
		var arrayPageScroll = getPageScroll();
		var lightboxTop = arrayPageScroll[1] + (arrayPageSize[3] / 15);

		Element.setTop('lightbox', lightboxTop);
		Element.show('lightbox');

		this.changeImage(imageNum);
	},

	//
	//	changeImage()
	//	Hide most elements and preload image in preparation for resizing image container.
	//
	changeImage: function(imageNum) {

		activeImage = imageNum;	// update global var

		// hide elements during transition
		Element.show('loading');
		Element.hide('lightboxImage');
		Element.hide('hoverNav');
		Element.hide('prevLink');
		Element.hide('nextLink');
		Element.hide('imageDataContainer');
		Element.hide('numberDisplay');

		imgPreloader = new Image();

		// once image is preloaded, resize image container
		imgPreloader.onload=function(){
			Element.setSrc('lightboxImage', imageArray[activeImage][0]);
			myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
		}
		imgPreloader.src = imageArray[activeImage][0];
	},

	//
	//	resizeImageContainer()
	//
	resizeImageContainer: function( imgWidth, imgHeight) {

		// get current height and width
		this.wCur = Element.getWidth('outerImageContainer');
		this.hCur = Element.getHeight('outerImageContainer');

		// scalars based on change from old to new
		this.xScale = ((imgWidth  + (borderSize * 2)) / this.wCur) * 100;
		this.yScale = ((imgHeight  + (borderSize * 2)) / this.hCur) * 100;

		// calculate size difference between new and old image, and resize if necessary
		wDiff = (this.wCur - borderSize * 2) - imgWidth;
		hDiff = (this.hCur - borderSize * 2) - imgHeight;

		if(!( hDiff == 0)){ new Effect.Scale('outerImageContainer', this.yScale, {scaleX: false, duration: resizeDuration, queue: 'front'}); }
		if(!( wDiff == 0)){ new Effect.Scale('outerImageContainer', this.xScale, {scaleY: false, delay: resizeDuration, duration: resizeDuration}); }

		// if new and old image are same size and no scaling transition is necessary,
		// do a quick pause to prevent image flicker.
		if((hDiff == 0) && (wDiff == 0)){
			if (navigator.appVersion.indexOf("MSIE")!=-1){ pause(250); } else { pause(100);}
		}

		Element.setHeight('prevLink', imgHeight);
		Element.setHeight('nextLink', imgHeight);
		Element.setWidth( 'imageDataContainer', imgWidth + (borderSize * 2));

		this.showImage();
	},

	//
	//	showImage()
	//	Display image and begin preloading neighbors.
	//
	showImage: function(){
		Element.hide('loading');
		new Effect.Appear('lightboxImage', { duration: 0.5, queue: 'end', afterFinish: function(){	myLightbox.updateDetails(); } });
		this.preloadNeighborImages();
	},

	//
	//	updateDetails()
	//	Display caption, image number, and bottom nav.
	//
	updateDetails: function() {

		Element.show('caption');
		Element.setInnerHTML( 'caption', imageArray[activeImage][1]);

		// if image is part of set display 'Image x of x'
		if(imageArray.length > 1){
			Element.show('numberDisplay');
			Element.setInnerHTML( 'numberDisplay', "Image " + eval(activeImage + 1) + " of " + imageArray.length);
		}

		new Effect.Parallel(
			[ new Effect.SlideDown( 'imageDataContainer', { sync: true, duration: resizeDuration + 0.25, from: 0.0, to: 1.0 }),
			  new Effect.Appear('imageDataContainer', { sync: true, duration: 1.0 }) ],
			{ duration: 0.65, afterFinish: function() { myLightbox.updateNav();} }
		);
	},

	//
	//	updateNav()
	//	Display appropriate previous and next hover navigation.
	//
	updateNav: function() {

		Element.show('hoverNav');

		// if not first image in set, display prev image button
		if(activeImage != 0){
			Element.show('prevLink');
			document.getElementById('prevLink').onclick = function() {
				myLightbox.changeImage(activeImage - 1); return false;
			}
		}

		// if not last image in set, display next image button
		if(activeImage != (imageArray.length - 1)){
			Element.show('nextLink');
			document.getElementById('nextLink').onclick = function() {
				myLightbox.changeImage(activeImage + 1); return false;
			}
		}

		this.enableKeyboardNav();
	},

	//
	//	enableKeyboardNav()
	//
	enableKeyboardNav: function() {
		document.onkeydown = this.keyboardAction;
	},

	//
	//	disableKeyboardNav()
	//
	disableKeyboardNav: function() {
		document.onkeydown = '';
	},

	//
	//	keyboardAction()
	//
	keyboardAction: function(e) {
		if (e == null) { // ie
			keycode = event.keyCode;
		} else { // mozilla
			keycode = e.which;
		}

		key = String.fromCharCode(keycode).toLowerCase();

		if((key == 'x') || (key == 'o') || (key == 'c')){	// close lightbox
			myLightbox.end();
		} else if(key == 'p'){	// display previous image
			if(activeImage != 0){
				myLightbox.disableKeyboardNav();
				myLightbox.changeImage(activeImage - 1);
			}
		} else if(key == 'n'){	// display next image
			if(activeImage != (imageArray.length - 1)){
				myLightbox.disableKeyboardNav();
				myLightbox.changeImage(activeImage + 1);
			}
		}


	},

	//
	//	preloadNeighborImages()
	//	Preload previous and next images.
	//
	preloadNeighborImages: function(){

		if((imageArray.length - 1) > activeImage){
			preloadNextImage = new Image();
			preloadNextImage.src = imageArray[activeImage + 1][0];
		}
		if(activeImage > 0){
			preloadPrevImage = new Image();
			preloadPrevImage.src = imageArray[activeImage - 1][0];
		}

	},

	//
	//	end()
	//
	end: function() {
		this.disableKeyboardNav();
		Element.hide('lightbox');
		new Effect.Fade('overlay', { duration: 0.2});
		showSelectBoxes();
	}
}

// -----------------------------------------------------------------------------------

//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.org
//
function getPageScroll(){

	var yScroll;

	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
	}

	arrayPageScroll = new Array('',yScroll)
	return arrayPageScroll;
}

// -----------------------------------------------------------------------------------

//
// getPageSize()
// Returns array with page width, height and window width, height
// Core code from - quirksmode.org
// Edit for Firefox by pHaez
//
function getPageSize(){

	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){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else {
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}


	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
	return arrayPageSize;
}

// -----------------------------------------------------------------------------------

//
// getKey(key)
// Gets keycode. If 'x' is pressed then it hides the lightbox.
//
function getKey(e){
	if (e == null) { // ie
		keycode = event.keyCode;
	} else { // mozilla
		keycode = e.which;
	}
	key = String.fromCharCode(keycode).toLowerCase();

	if(key == 'x'){
	}
}

// -----------------------------------------------------------------------------------

//
// listenKey()
//
function listenKey () {	document.onkeypress = getKey; }

// ---------------------------------------------------

function showSelectBoxes(){
	selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "visible";
	}
}

// ---------------------------------------------------

function hideSelectBoxes(){
	selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "hidden";
	}
}

// ---------------------------------------------------

//
// pause(numberMillis)
// Pauses code execution for specified time. Uses busy code, not good.
// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
//
function pause(numberMillis) {
	var now = new Date();
	var exitTime = now.getTime() + numberMillis;
	while (true) {
		now = new Date();
		if (now.getTime() > exitTime)
			return;
	}
}

// ---------------------------------------------------



function initLightbox() {
	myLightbox = new Lightbox();
}
Event.observe(window, 'load', initLightbox, false);




var config_enabled=false;
if(EC==null||typeof (EC)!="object"){
var EC=new Object();
}
if(EC.F==null||typeof (EC.F)!="object"){
EC.F=new Object();
}
if(EC.F["setCookie"]==null){
EC.F.setCookie=function(_1,_2){
var _3=_1+"="+escape(_2);
document.cookie=_3;
return null;
};
EC.F.getCookie=function(_4){
var _5=_4+"=";
var _6=document.cookie;
var _7=null;
if(_6.length>0){
offset=_6.indexOf(_5);
if(offset!=-1){
offset+=_5.length;
end=_6.indexOf(";",offset);
if(end==-1){
end=_6.length;
}
_7=unescape(_6.substring(offset,end));
}
}
return _7;
};
}
var jslog=new function(){
bPersistState=true;
var _8="ec_debug_logging";
var _9="jslog";
var _a=_8+"_"+_9;
var _b=config_enabled;
if(_b==false&&location.href.match(/enablejslog/)){
_b=true;
}
var _c=false;
var _d=0;
function $(o){
return document.getElementById(o);
}
function debug(_f){
logMsg("DEBUG",_f);
}
function info(msg){
logMsg("INFO",msg);
}
function warning(msg){
logMsg("WARN",msg);
}
function error(msg){
logMsg("ERROR",msg);
}
function toggleDisplay(){
var _13=$(_a+"_body");
if(_13.style.display=="none"){
_13.style.display="block";
}else{
_13.style.display="none";
}
if(bPersistState){
EC.F.setCookie(_9+"_visibility",_13.style.display);
}
}
function clearLog(){
$(_a+"_logDisplay").innerHTML="";
_d=0;
$(_a+"_handle").innerHTML=_d;
}
function enable(){
if(!_c){
initializeDisplay();
}
}
function text(_14){
$(_a+"_textArea").value=_14;
}
function getHTML(){
var _15=$(_a+"_idToInspect").value;
if(_15==""){
warning("Provide a non-blank id");
}else{
try{
var _16=$(_a+"_textArea").value=$(_15).innerHTML;
info(_15+" innerHTML is now in the text box below!");
}
catch(e){
error("Could not get innerHTML of id="+_15+": "+e.message);
}
EC.F.setCookie(_9+"_idToInspect",_15);
}
}
this.debug=debug;
this.info=info;
this.warning=warning;
this.error=error;
this.toggleDisplay=toggleDisplay;
this.clearLog=clearLog;
this.text=text;
this.enable=enable;
this.getHTML=getHTML;
function logMsg(_17,msg){
if(_b){
_d+=1;
$(_a+"_handle").innerHTML=_d;
var _19=$(_a+"_logDisplay");
if(_19.childNodes.length==0){
_19.appendChild(createDisplayRow(_17,msg));
}else{
_19.insertBefore(createDisplayRow(_17,msg),_19.childNodes[0]);
}
}
}
function createDisplayRow(_1a,_1b){
if(document.all){
var _1c="styleFloat";
}else{
var _1c="cssFloat";
}
var _1d=document.createElement("div");
if(_d/2==Math.floor(_d/2)){
_1d.style.backgroundColor="#FFF";
}else{
_1d.style.backgroundColor="#F6F6F6";
}
_1d.style.borderBottom="1px solid #AAA";
_1d.style.verticalAlign="top";
var _1e=document.createElement("div");
_1e.style.width="40px";
_1e.style.paddingLeft="3px";
_1e.style[_1c]="left";
if(_1a=="DEBUG"){
_1e.style.backgroundColor="#1515FF";
}else{
if(_1a=="INFO"){
_1e.style.backgroundColor="#10FF10";
}else{
if(_1a=="WARN"){
_1e.style.backgroundColor="yellow";
}else{
if(_1a=="ERROR"){
_1e.style.backgroundColor="#FF7070";
}
}
}
}
_1e.appendChild(document.createTextNode(_1a));
_1d.appendChild(_1e);
var _1f=document.createElement("span");
_1f.style.paddingLeft="3px";
_1f.style.paddingRight="8px";
_1e.style[_1c]="left";
_1f.appendChild(document.createTextNode(getCurrentTimeFormatted()));
_1d.appendChild(_1f);
_1d.appendChild(document.createTextNode(_1b));
var _20=document.createElement("div");
_20.style.clear="both";
_1d.appendChild(_20);
return _1d;
}
function getCurrentTimeFormatted(){
var now=new Date();
var _22=now.getHours();
var _23=now.getMinutes();
var _24=now.getSeconds();
var _25=""+((_22>12)?_22-12:_22);
if(_25=="0"){
_25=12;
}
_25+=((_23<10)?":0":":")+_23;
_25+=((_24<10)?":0":":")+_24;
_25+=(_22>=12)?" PM":" AM";
return _25;
}
if(_b){
initializeDisplay();
}
function initializeDisplay(){
if(!_c){
try{
var _26=2;
var _27=2;
var _28="none";
if(bPersistState){
try{
var _29=EC.F.getCookie(_9+"_position");
if(_29!=null){
var _2a=_29.split("|");
if(!isNaN(parseInt(_2a[0]))){
_27=_2a[0];
}
if(!isNaN(parseInt(_2a[1]))){
_26=_2a[1];
}
}
if(EC.F.getCookie(_9+"_visibility")=="block"){
_28="block";
}
}
catch(e){
}
}
var _2b=EC.F.getCookie(_9+"_idToInspect");
_2b=_2b==null?"":_2b;
document.write("<div id=\""+_a+"_container\" style=\"font-family:arial; color:black; font-size:9px; line-height:normal; letter-spacing: normal; position:absolute; z-index:10000;top:"+_26+"px; left:"+_27+"px; \">"+"<div id=\""+_a+"_handle\" style=\"cursor:move; position: absolute; background-color:#FFFFCC; border:1px solid #FF0400; color:black; padding:2px;\" ondblclick=\""+_9+".toggleDisplay()\">0</div>"+"<div id=\""+_a+"_body\" style=\"text-align:left; border:1px solid #FF0400; width:300px; position: absolute; top:20px; left:0px; background-color:white; display:"+_28+"\">"+"<div id=\""+_a+"_header\" style=\"height:10px; padding:2px; border-bottom:1px solid black; background-color:#FFFFCC;\">"+"<span id=\""+_a+"_clear\" style=\"color: blue;\" onclick=\""+_9+".clearLog()\">clear</span>"+"</div>"+"<div id=\""+_a+"_logDisplay\" style=\"height:240px; overflow:auto;\"></div>"+"<div id=\""+_a+"_footer\" style=\"padding-left:2px; border-top:1px solid black; background-color:#FFFFCC;\">"+"get html:<input id=\""+_a+"_idToInspect\" style=\"font-size:9px; height:18px;\" value=\""+_2b+"\" size=42/> <span id=\""+_a+"_go\" style=\"color: blue;\" onclick=\""+_9+".getHTML()\">go</span>"+"<textarea id=\""+_a+"_textArea\" style=\"width:99%; font-size:9px;\"></textarea>"+"</div></div></div></div>");
$(_a+"_clear").style.cursor="pointer";
$(_a+"_go").style.cursor="pointer";
if(window["Draggable"]!=null){
new Draggable(_a+"_container",{handle:_a+"_handle",revert:false,starteffect:false,endeffect:false});
if(bPersistState){
var _2c=new function(){
this.onStart=function(){
};
this.onEnd=function(s,o){
if(o.element.id==_a+"_container"){
var pos=Position.cumulativeOffset(o.element);
EC.F.setCookie(_9+"_position",+pos[0]+"|"+pos[1]);
}
};
};
Draggables.addObserver(_2c);
}
}else{
$(_a+"_handle").style.cursor="pointer";
}
_c=true;
}
catch(e){
alert("Code-level error initializing jslog: "+e.description);
}
}
}
};
debug=jslog.debug;






var ajaxServiceURL = 'http://secure.intersportrent.at/buchung/index.php';

var actualStep;

var loadingShop = false;

var isrEffects;

var isrjsdebug = false;



var currentItem = "iic_location_by_city";

var dealer_result_box = false;

var all_dealers_list = 0;

var shop_selected = false;

var selectedStore = -1;

var selectedSetOfStores;

var lastDealer = 0;

var azListDisplayed = false;

var googleMapsLoaded = false;

var markerLoaded = 0;

var changingTabs = false;



var current_product_list = "product_select_by_category";

var product_selected = 0;

var current_step2_item = 'product_selection';




var payerForm = false;


var isrEffects = {

    initialize: function () {
    },

    toggle: function( element ) {
        if ( true ) {
            if ( ! $(element).visible() )
                $(element).show();
            else
                $(element).hide();
        } else
            Effect.toggle(element,'blind');
    },

    BlindUp: function ( element ) {
        if ( true ) {
            $(element).show();
        } else
            Effect.BlindUp(element);
    },

    Fade: function ( element ) {
        if ( true ) {
            $(element).hide();
        } else
            Effect.Fade(element);
    },

    Appear: function ( element ) {
        if ( true ) {
            $(element).show();
        } else
            Effect.Appear(element);
    }

}



var historyText = '';
var last = '';

var isrHistory = {

    dealerSearch: function(tabId) {
    },

    timeSelection: function(dealerId) {
    },

    productSelection: function(crplist) {
    },

    basket: function() {
    },

    historyListener: function(historyHash, historyData) {
    },

    parseUrl: function(url) {
        return false;
    }

}



var isrHelper = Class.create();

isrHelper.prototype = {

	
	initialize: function()
	{
		try {
			dhtmlHistory.initialize();
			dhtmlHistory.addListener(isrHistory.historyListener);
		} catch (exception) {}
	},

	showProcessingInfo: function(text)
	{
		if (text) {
			$('wait_while_processing_info').innerHTML = text;
		}
		else {
			$('wait_while_processing_info').innerHTML = 'Please wait. The data is being validated.';
		}

		var arrayPageSize = getPageSize();
		Element.setHeight('processing_info_overlay', arrayPageSize[1]);
		Element.setStyle('processing_info_overlay', {display:'block'});
		offset = Position.realOffset($('wait_while_processing'));
		newOffset = offset[1]+50;
		$('wait_while_processing').style.top = newOffset+'px';
		Element.setStyle('wait_while_processing', {display:'block'});

		Element.setStyle('wait_while_processing_content', {display:'block'});
		Element.setStyle('wait_while_processing_content_text', {display:'block'});
		Element.setStyle('wait_while_processing_info', {display:'block'});
	},

	hideProcessingInfo: function() {
		Element.setStyle('processing_info_overlay', {display:'none'});
		Element.setStyle('wait_while_processing', {display:'none'});
		Element.setStyle('wait_while_processing_content', {display:'none'});
		Element.setStyle('wait_while_processing_content_text', {display:'none'});
		Element.setStyle('wait_while_processing_info', {display:'none'});
	},


	UnCryptLocation: function(s) {
		var n=0;
		var r='';
		for(var i=0; i < s.length; i++) {
			n=s.charCodeAt(i);
			if (n>=8364) {n = 128;}
			r += String.fromCharCode(n-(2));
		}
		return r;
	},


	setUrchinTracker: function(s) {
		try { urchinTracker( s ); }
		catch (exc) {}
	},


	mailto: function(s)    {  

		location.href=this.UnCryptLocation(s);
	},

	liveHelp: function() {
		return;
	},

	offlineHelp: function() {
		alert ( 'Offline Help' );
	}

};


function LZ(x)
{
	return(x<0||x>9?"":"0")+x;
}



function printContent(content)
{
	var sOption="toolbar=yes,location=no,directories=yes,menubar=yes,";
	sOption+="scrollbars=yes,width=750,height=600,left=100,top=25";
	var winprint=window.open("","",sOption);
	winprint.document.open();
	winprint.document.write('<html><LINK href=/eggheadcafe.css rel=Stylesheet><body>');
	winprint.document.write(content);
	winprint.document.write('<scr'+'ipt>window.print();</scr'+'ipt>');
	winprint.document.write('</body></html>');
	winprint.document.close();
	winprint.focus();
}


var isrSession = {

    hasBuyer: function(doOnTrue, doOnFalse) {
        var url = 'http://secure.intersportrent.at/buchung/index.php';
        new Ajax.Request ( ajaxServiceURL, {
            method: 'post',
            postBody: 'ajax=1&session=1&ask=buyer',
            onSuccess : function(resp) {

                var xml = resp.responseXML;
                var results = xml.getElementsByTagName ( 'result' );
                var result = 0;
                if ( results && results.length > 0 ) {
                    var id = parseInt ( results [ 0 ].firstChild.nodeValue );
                    if ( id && id > 0 ) {
                        doOnTrue();
                    }
                    else {
                        doOnFalse();
                    }
                }
                else {
                    doOnFalse();
                }
            },
            onFailure: function(resp) {
            	doOnFalse();
            },
            onException: function(resp, exception) {
            	doOnFalse();
            	if (false) {
            		alert ( 'Session.hasBuyer - Exception [ ' + exception + ' ] ');
            	}
            }
        });
    }
}
﻿

var isrStep1 = Class.create();

isrStep1.prototype = {

	handleError: function ( statusText ) {
		if (isrjsdebug) {
			alert (statusText)
			try {
				console.log (statusText);

			}
			catch (e) {}
		}

		iH.hideProcessingInfo();
	},
	handleException: function ( statusText ) {
		
		if (isrjsdebug) {
			alert (statusText)
			try {
				console.log (statusText);

			}
			catch (e) {}
		}
		iH.hideProcessingInfo();
	},
	
	
	initialize: function() {
		actualStep = 'location';
		var url = window.document.location.href;
		var hHash = url.lastIndexOf ( '#' ) > 0 ? url.substr ( url.lastIndexOf ( '#' ) + 1 ) : '';
		var hasTime = false;

		if ( hHash.length > 0 && hHash.lastIndexOf ( 'location' ) > 0 ) {
			currentItem = hHash.substr ( 4 );
			if ( ! $(currentItem) || typeof $(currentItem) == 'undefined' ) {
				currentItem = 'iic_location_by_city';
			}
			isrHistory.dealerSearch(currentItem);
			Element.setStyle($(currentItem),{display:'block'});
		}
		else if ( hHash.length == 0 ) {
			isrHistory.dealerSearch(currentItem);
			Element.setStyle($(currentItem),{display:'block'});
		}

		if (navigator.appVersion.indexOf('MSIE')>0) {
			this.adjustContainerHeight();
		}

		var autocompleteUrl = 'http://secure.intersportrent.at/buchung/';
		new Ajax.Autocompleter ('iic_select_by_city', 'iic_autocomplete_box', autocompleteUrl, {
				minChars: 1,
				partialSearch: true,
				fullSearch: true,
				highlightcolor: "#ffffff"
			});

		new Ajax.Autocompleter('iic_select_by_quarters','iic_autocomplete_box','http://secure.intersportrent.at/buchung/autocompletedata.php?i=quarters',{
				paramName:'var',
				minChars: 1,
				partialSearch: true,
				fullSearch: true
			});

		iH = new isrHelper();

		try {
			$('iic_select_by_city').value = isrStep1.getSearchCookie();
		}
		catch (exception) {}

		try {
			$('iic_select_by_quarters').value = isrStep1.getQuartersCookie();
		}
		catch (exception) {}

	},

	
	toggleTabs: function(selectedItem,selector) {

	


		try {
			Element.setStyle($(currentItem), {display:'none'});
		}
		catch ( exception ) {}

		try {
			Element.setStyle($("search_location_dealer_results"), {display:'none'});
		}
		catch ( exception ) {}


		Element.classNames(selector).set('active');
		var nodeList = $('iic_tb_navigation').getElementsByTagName('a');
		var nodes = $A(nodeList);
		nodes.each(function(node) {
			if (node != selector) {
				Element.classNames(node).set("");
			}
		});
		Element.setStyle($(selectedItem), {display:'block'});
		currentItem = selectedItem;

		isrHistory.dealerSearch(currentItem);

		if ( selectedItem == 'iic_location_by_city' ) {
			$('iic_select_by_city').value = isrStep1.getSearchCookie();
		}
		else if (selectedItem == 'iic_location_by_map' && googleMapsLoaded == false) {

			markerLoaded = 0;

			iH.showProcessingInfo('Please wait. The map is being created...');
			var timer = setTimeout(iH.hideProcessingInfo, 4000);
			var timer = setTimeout(this.googleMaps.bind(this), 500);
		}

		var step = selectedItem.replace ( /iic_location_by_/g, '' );
		iH.setUrchinTracker( '/buchung/funnel/location_' + step + '.php' );

	},

	
	toggleAZlist: function() {
		isrEffects.toggle ( 'iic_location_az_list' );

		if (azListDisplayed == false) {
			azListDisplayed = true;
		}
		else {
			azListDisplayed = false;
		}
	},

	
	writeCityListEntry: function (id, city) {
		$('iic_select_by_city_id').value = id;
		$('iic_select_by_city').value = city;
		$('iic_select_by_city').focus();
		if ( Element.visible ( 'iic_location_city_search' ) ) {
			isrEffects.toggle('iic_location_city_search');
		}
		if ( Element.visible ( 'iic_location_az_list' ) ) {
			isrEffects.toggle('iic_location_az_list');
		}
	},

	writeCitySearchEntry: function (id, city) {
		$('iic_select_by_city_id').value = id;
		$('iic_select_by_city').value = city;
		$('iic_select_by_city').focus();
		if ( Element.visible ( 'iic_location_city_search' ) ) {
			isrEffects.toggle('iic_location_city_search');
		}
		if ( Element.visible ( 'iic_location_az_list' ) ) {
			isrEffects.toggle('iic_location_city_search');
		}
	},

	setSearchCookie: function(entry) {
		if ( entry.length == 0 ) {
			return;
		}
		var myCookie = document.cookie;
		if ( myCookie.length == 0 ) {
			myCookie = 'citysearch=' + entry + "::";
		}
		else {
			if ( myCookie.lastIndexOf('citysearch') > 0 ) {
				myCookie = myCookie.substr(0, myCookie.lastIndexOf ( 'citysearch' ) - 1 );
			}
			myCookie += '&citysearch=' + entry + "::";
		}

		document.cookie = myCookie;
	},

	getSearchCookie: function() {
		var myCookie = " " + document.cookie;
		if ( myCookie.lastIndexOf ( 'citysearch' ) > 0 ) {
			myCookie = myCookie.substr ( myCookie.lastIndexOf ( 'citysearch' ) );
			myCookie = myCookie.substr ( 0, myCookie.lastIndexOf ( '::' ) );

			myCookie = myCookie.substr ( myCookie.indexOf ( '=' ) + 1 );
		}
		else {
			myCookie = "";
		}
		return myCookie;
	},
	getQuartersCookie: function() {
		var myCookie = " " + document.cookie;
		if ( myCookie.lastIndexOf ( 'quarterssearch' ) > 0 ) {
			myCookie = myCookie.substr ( myCookie.lastIndexOf ( 'quarterssearch' ) );
			myCookie = myCookie.substr ( 0, myCookie.lastIndexOf ( '::' ) );

			myCookie = myCookie.substr ( myCookie.indexOf ( '=' ) + 1 );
		}
		else {
			myCookie = "";
		}
		return myCookie;
	},


	
	citySearch: function () {
		if ($('iic_select_by_city').value.length != 0) {
			if (dealer_result_box == true) {
				Element.setStyle($('search_location_dealer_results'), {display:'none'});
			}
			if (azListDisplayed == true || Element.visible ( 'iic_location_az_list') ) {
				isrEffects.BlindUp ( 'iic_location_az_list' );
				azListDisplayed = false;
			}
			if ( Element.visible ( 'iic_location_city_search') ) {
				isrEffects.BlindUp ( 'iic_location_city_search' );
			}

			$('search_location_dealer_results').innerHTML = '';
			$('iic_no_dealer_found').innerHTML = '';
			Element.hide ( 'iic_no_dealer_found' );

			isrStep1.setSearchCookie($('iic_select_by_city').value);

			new Ajax.Request ( ajaxServiceURL, {
				method: 'post',

				postBody: 'ajax=1&state=0reservation&use=city&json=true&id=' + ($('iic_select_by_city').value) + '&quarters=' + ($('iic_select_by_quarters').value),
				onComplete: function (resp) {
					iH.showProcessingInfo();
					var response = resp.responseText;

					var data = eval('(' + response + ')');

					
					if (data.shops.length == 1) {

						var myresult = TrimPath.processDOMTemplate("tpl_location_by_resort", data);
						this.doLocationSearchSuccess(myresult);
					
						if (document.URL.indexOf("quickinfo") != '-1')
						{
							isrStep1.quickinfo( '0', '1', 'cityHeader_1' );
						}
						else if(document.URL.indexOf("priceinfo") != '-1')
						{
							isrStep1.priceinfo( '0', '1', 'cityHeader_1' );
					    }
						else
					    {
							isrStep1.selectShop( '0', '1', 'cityHeader_1' );

							window.setTimeout(function () {
								$('google_location_by_resort').hide();
								iH.hideProcessingInfo();
							},1000);
					    }
					}
					else {
					
						
						googleMapsLoaded = false;

						
						var myresult = TrimPath.processDOMTemplate("tpl_location_by_resort", data);

						this.doLocationSearchSuccess(myresult);

						

						$('iic_select_by_quarters_label').setStyle({display:"block"});
						$('iic_select_by_quarters').setStyle({display:"block"});


						$('google_location_by_resort').show();
						
						window.setTimeout(function () {
							googleLogic = new isrStep1ext(data);
							googleLogic.initMap($('google_location_by_resort'));
							iH.hideProcessingInfo();
						}, 1500);
					}



				}.bind(this),
				onFailure: function(resp) {isrStep1.handleError ( resp.statusText );},
				onException: function(resp, exception) {isrStep1.handleException ( exception );}
			});
		}
		else {
			return false;
		}
	},

	localize: function(token ) {
		var result = '';
		var done = false;
		var i = 0;

		new Ajax.Request ( ajaxServiceURL, {
			method: 'post',
			postBody: 'ajax.php?localize=1&token=' + token,
			onSuccess : function(resp) {result = resp.responseText;},
			onFailure: function(resp) {isrStep1.handleError ( resp.statusText );},
			onException: function(resp, exception) {isrStep1.handleException ( exception );}
		});
		while ( ! done && i < 1000 ) {
			i++;
		}
		return result;
	},

	
	regionSearch: function() {
		if (dealer_result_box == true) {
			Element.setStyle($('search_location_dealer_results'), {display:'none'});
		}

		if (azListDisplayed == true || Element.visible ( 'iic_location_az_list') ) {
			isrEffects.BlindUp ( 'iic_location_az_list' );
			azListDisplayed = false;
		}

		$('search_location_dealer_results').innerHTML = '';
		$('iic_no_region_found').innerHTML = '';

		var element = $F('iic_select_by_region');
		if ( element.length > 5 ) {
			$('iic_no_region_found').innerHTML = '<u>Notify</u>: Please choose a resort';
			isrEffects.toggle('iic_no_region_found');
			iH.hideProcessingInfo();
			return;
		}

		new Ajax.Request ( ajaxServiceURL, {
			method: 'post',
			postBody: 'ajax=1&state=0reservation&use=region&json=true&id=' + encodeURI(element),
			onComplete: function (resp) {
				iH.showProcessingInfo();
				var response = resp.responseText;
				var data = eval('(' + response + ')');
				
				var myresult = TrimPath.processDOMTemplate("tpl_location_by_resort", data);

				this.doLocationSearchSuccess(myresult);
				
				googleMapsLoaded = false;

				window.setTimeout(function () {
					googleLogic = new isrStep1ext(data);
					googleLogic.initMap($('google_location_by_resort'));
					iH.hideProcessingInfo();
				}, 1500);
			}.bind(this),
			onFailure: function(resp) {
				alert (resp);
				isrStep1.handleError ( resp.statusText );
			},
			onException: function(resp, exception) {
				isrStep1.handleException ( exception );
			}
		});
	},

	dealerSearch: function(id) {
		if (dealer_result_box == true) {
			Element.setStyle($('search_location_dealer_results'), {display:'none'});
		}

		if (azListDisplayed == true || Element.visible ( 'iic_location_az_list') ) {
			isrEffects.BlindUp ( 'iic_location_az_list' );
			azListDisplayed = false;
		}
		$('search_location_dealer_results').innerHTML = '';
		$('iic_no_dealer_found').innerHTML = '';
		Element.hide ( 'iic_no_dealer_found' );

		new Ajax.Request ( ajaxServiceURL, {
			method: 'post',
			postBody: 'ajax=1&state=0reservation&use=dealer&id=' + id,
			onSuccess : this.locationSearchSuccess,
			onFailure: function(resp) {isrStep1.handleError ( resp.statusText );},
			onException: function(resp, exception) {isrStep1.handleException ( exception );}
		});
	},

	
	locationSearchSuccess: function (res) {
		if (res.responseText.length == 0) {
			return;
		}
		res.responseText.evalScripts();

		isrStep1.doLocationSearchSuccess ( res.responseText );
		iH.setUrchinTracker( '/buchung/funnel/cityselect.php' );
	},

	doLocationSearchSuccess: function (response) {
		if (response.length > 0) {
			$('search_location_dealer_results').innerHTML = response;
		}

		if ( $('totalSets' ) || typeof $('totalSets') != 'undefined' ) {
			totalSets = parseInt ( $('totalSets').innerHTML );
		}
		else {
			return;
		}

		if ( totalSets == '0' ) {
			if (response.length > 0) {
				var resText = response;
				$('iic_no_dealer_found').innerHTML = resText;
			}
			isrEffects.toggle('iic_no_dealer_found');
			iH.setUrchinTracker( '/buchung/funnel/nodealer.php' );
		}
		else {
			totalShops = parseInt ($('totalShops').innerHTML);
			if (navigator.appVersion.indexOf('MSIE')>0) {
				Element.setStyle('search_location_dealer_results', {height:''});
				Element.setStyle('iic_select_store_box', {height:''});
				Element.setStyle('iic_tabbed_box_ID205', {height:''});
			}
			isrEffects.toggle('search_location_dealer_results');
			iH.setUrchinTracker( '/buchung/funnel/dealerselect.php' );
			dealer_result_box = true;
		}
	},

	tryAgain: function () {
		var selected = selectedStore;
		var set = selectedSetOfStores;
		try {
			if ( $('pickup_time_' + selected + '_' + set ) && $('pickup_time_' + selected + '_' + set ).innerHTML.length > 10 ) {
				$('collect_products_time').innerHTML = '&sup1;' + $('pickup_time_' + selected + '_' + set ).innerHTML;
				$('label_from_day').innerHTML = 'First day of rental&sup1;'
			}

			if ( $('openings_' + selected + '_' + set ) ) {
				$('openingTimesEntries').innerHTML = $('openings_' + selected + '_' + set ).innerHTML;
				Element.show ('openingTimesButton');
			}
			else {
				Element.hide ('openingTimesButton');
			}
		}
		catch (exception) {}
	},

	
	selectShop: function (selected, set, cityHeader) {
		iH.showProcessingInfo();
		actualStep = actualStep == 'time' ? 'location' : 'time';
		try {
			isrEffects.toggle('google_location_by_resort');
		}
		catch(e) {}

		try {
			isrEffects.toggle('iic_select_store_box');
		}
		catch(e) {}


		try {
			isrEffects.toggle('dealermapscontrol');
		}
		catch (e) {}

		try {
			if ( cityHeader && cityHeader.length > 11 ) {
				this.highlightCityHeader ( cityHeader );
			}
		}
		catch ( exception ) {}

		this.highlightSelectedShop(selected,set);
		this.changeLayoutOfSelectedShop();

		isrEffects.toggle ( 'iic_time_selection_box' );
		iH.setUrchinTracker( '/buchung/funnel/time.php' );
		iH.hideProcessingInfo();

		
		if ( $('search_location_dealer_results').innerHTML.length == 0 ) {
			window.setTimeout ( 'isrStep1.tryAgain()', 2000 );
		}

		if ( $('pickup_time_' + selected + '_' + set ) && $('pickup_time_' + selected + '_' + set ).innerHTML.length > 10 ) {
			$('collect_products_time').innerHTML = '&sup1;' + $('pickup_time_' + selected + '_' + set ).innerHTML;
			$('label_from_day').innerHTML = 'First day of rental&sup1;'
		}
		selectedStore = selected;
		selectedSetOfStores = set;

		isrStep1.initCalendar();
		all_dealers_list = totalShops;
		if ( $('shop_id_' + selectedStore + '_' + selectedSetOfStores ) ) {
			isrStep1.showDealerInformation($F('shop_id_' + selectedStore + '_' + selectedSetOfStores ));
			lastDealer = $F('shop_id_' + selectedStore + '_' + selectedSetOfStores );
		}

		if ( $('openings_' + selected + '_' + set ) ) {
			$('openingTimesEntries').innerHTML = $('openings_' + selected + '_' + set ).innerHTML;
			Element.show ('openingTimesButton');
		}
		else {
			Element.hide ('openingTimesButton');
		}

		iH.hideProcessingInfo();

		if (actualStep == 'time') {
			isrHistory.timeSelection(lastDealer);
		}
		else {
			isrHistory.dealerSearch(currentItem);
		}

	},

	selectShopExt: function (selected, set, cityHeader) {
		this.selectShop (selected, set, cityHeader);
	},

	
	changeLayoutOfSelectedShop: function() {
		var beforeelements = getElementsByClassName(document, "span", "dealerBeforeSelection");

		for(m=0; m<beforeelements.length; m++) {
			beforeelements[m].style.display = "none";
		}
		if (navigator.appVersion.indexOf('MSIE')>0) {
			Element.setStyle('search_location_dealer_results', {height:''});
		}
		var afterelements = getElementsByClassName(document, "span", "dealerAfterSelection");

		for(m=0; m<afterelements.length; m++) {
			afterelements[m].style.display = "block";
		}
	},

	
	highlightCityHeader: function( cityHeader ) {
		var beforeelements = getElementsByClassName(document, "table", "cityHeaders");
		for(m=0; m<beforeelements.length; m++) {
			beforeelements[m].style.display = "none";
		}
		if ( $(cityHeader) ) {
			$(cityHeader).style.display = "block";
		}
	},

	
	highlightSelectedShop: function (selected,set) {
		try {
			finished = false;
			for (i=1;i<=totalSets;i++) {
				if (i != set) {
					element = "dealerSet"+i;
					isrEffects.Fade(element);
				}
			}
			for(i=0;i<totalShops;i++) {
				actual_row = 'iic_shop_list_dealer_' + i;
				if (i != selected) {
					isrEffects.Fade(actual_row);
				}
			}
		}
		catch(exception) {}
	},

	handleDateSelection: function(prefix) {
		var hidden = $(prefix + '_hidden' );

		if ( ! hidden.value || hidden.value.length <= 0 ) {
			return '';
		}
		var date = hidden.value;
		var day = date.substr ( 0, date.indexOf ( '.' ) );
		$( prefix + '_day' ).selectedIndex = day - 1;

		var month = date.substr ( date.indexOf ( '.' ) + 1, 2 );
		$( prefix + '_month' ).selectedIndex = month - 1;

		var year = date.substr ( date.lastIndexOf ( '.' ) + 1 );
		$( prefix + '_year' ).value = year;
	},

	updateHiddenDate: function(prefix) {
		var hidden = $(prefix + '_hidden' );
		if ( ! hidden.value ) {
			return '';
		}

		var day = LZ($F(prefix + '_day' ));
		var month = LZ($F(prefix + '_month' ));
		var year = LZ($F(prefix + '_year' ));
		hidden.value = day + '.' + month + '.' + year;
	},

	getShopDate: function(prefix) {
		var set = selectedSetOfStores;
		var selected = selectedStore;
		var newDate = new Date();
		if ( $(prefix + selected + '_' + set ) && $(prefix + selected + '_' + set ).innerHTML.length == 10 ) {
			var myDate = $(prefix + selected + '_' + set ).innerHTML;

			var nday = myDate.substr ( 0, myDate.indexOf ( '.' ) ) ;
			var nmonth = myDate.substr ( myDate.indexOf ( '.' ) + 1, 2 );
			var nyear = myDate.substr ( myDate.lastIndexOf ( '.' ) + 1 );

			if ( nyear > 0 && nmonth > 0 && nday > 0 ) {
				newDate.setDate(nday);
				newDate.setMonth(nmonth);
				newDate.setFullYear(nyear);
			}
		}

		return newDate;
	},

	dateState: function(date) {
		var min = isrStep1.getShopDate( 'season_start_' );
		var max = isrStep1.getShopDate( 'season_end_' );
		if (date.getTime() < min.getTime() || date.getTime() > max.getTime())
		return true;
		return false;
	},

	
	initCalendar: function() {
		var seasonStart = isrStep1.getShopDate ( 'season_start_' );
		var seasonEnd = isrStep1.getShopDate ( 'season_end_' );
		if ( seasonStart == seasonEnd ) {
			seasonEnd.setFullYear(seasonStart.getFullYear() + 1);
		}
		Calendar.setup ({
			inputField  : "from_hidden",
			ifFormat    : "%d.%m.%Y",
			daFormat    : "%d.%m.%Y",
			firstDay: 1,
			showsTime: false,
			showOthers: true,
			timeFormat: 24,
			button      : "selectDateOne",
			range   : [seasonStart.getFullYear(),seasonEnd.getFullYear()]
		});

		Calendar.setup ({
			inputField  : "until_hidden",
			ifFormat    : "%d.%m.%Y",
			daFormat    : "%d.%m.%Y",
			firstDay: 1,
			showsTime: false,
			showOthers: true,
			timeFormat: 24,
			button      : "selectDateTwo",
			range   : [seasonStart.getFullYear(),seasonEnd.getFullYear()]
		});
	},

	
	gotoStepTwo: function() {
		if (googleMapsLoaded == true) {
			GUnload();
			googleMapsLoaded = false;
		}
		iH.showProcessingInfo();
		try {
			$('iic_no_dealer_found').innerHTML = '';
			Element.hide ( 'iic_no_dealer_found' );
		}
		catch (e) {};
		try {
			var element = $('iic_select_by_region').options [ $('iic_select_by_region').selectedIndex ];
			var shop_id = $('shop_id_' + selectedStore + '_' + selectedSetOfStores ).value;
		}
		catch (e) {
			var element = "";
			var shop_id = "";
		}
		var params = 'loaded=1&ajax=1&use=dealer&check=timestamp&id=' + shop_id + '&from_day=' + $('from_day').value;
			params += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
			params += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
			params += '&until_year=' + $('until_year').value;

		new Ajax.Request ( ajaxServiceURL, {
			method: 'post',
			postBody: params,
			onSuccess : this.determineTimestamp,
			onFailure: function(resp) {isrStep1.handleError ( resp.statusText );},
			onException: function(resp, exception) {isrStep1.handleException ( exception );}
		});
	},

	
	determineTimestamp: function(res) {

		var test='http://secure.intersportrent.at/buchung/?state=2&use=dealer&id=' + shop_id + '&from_day=' + $('from_day').value;
		test += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
		test += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
		test += '&until_year=' + $('until_year').value;

		if ( res.responseText.length > 50 ) {
			var problems = res.responseXML.getElementsByTagName ( "problem" );
			var error = 'Error';
			if ( problems && problems.length > 0 ) {
				error = '<u>Notify</u>: ' + problems [ 0 ].firstChild.nodeValue;
			}
			$('timeSpanErrorError').innerHTML = error;
			isrEffects.Appear ( 'timeSpanError' );
			iH.hideProcessingInfo();
			return;

		}
		var shop_id = $('shop_id_' + selectedStore + '_' + selectedSetOfStores ).value;
		var url='http://secure.intersportrent.at/buchung/?state=2&use=dealer&id=' + shop_id + '&from_day=' + $('from_day').value;
		url += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
		url += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
		url += '&until_year=' + $('until_year').value;

		iH.setUrchinTracker( '/buchung/funnel/prd_available.php' );

		window.document.location.href = url;
	},


	loadShop: function (id) {

		iH.hideProcessingInfo();
		isrStep1.dealerSearch(id);

		isrEffects.toggle('iic_select_store_box');

		isrEffects.toggle('iic_time_selection_box');

		selectedStore = 0;
		selectedSetOfStores = 1;

		isrStep1.selectShop(0,1);
		iH.hideProcessingInfo();

	},
	
	loadShopExt: function (id) {
		var url='http://secure.intersportrent.at/buchung/index.php?use=dealer&id=' + id;
		window.document.location.href = url;
		return;
	},

	showDealerInformation: function(id) {
		if ( $('small_dealer') && typeof $('small_dealer') != 'undefined' ) {
			isrStep1.reloadSmallDealer(id);
		}
		else {
			isrStep1.reloadBox ( 'progress_info_box', 'progress', [ 'dealer=' + id ] );
		}
	},

	reloadSmallDealer: function (id) {
		var smallDealer = $('small_dealer' );
		if ( typeof smallDealer == 'undefined' ) {
			return;
		}

		smallDealer.innerHTML = '';
		new Ajax.Request ( 'http://secure.intersportrent.at/buchung/ajaxbox.php', {
			method: 'post',
			postBody: 'box=smalldealer&dealer=' + id,
			onSuccess : function(resp){$('small_dealer').innerHTML = resp.responseText;},
			onFailure: function(resp) {},
			onException: function(resp, exception) {}
		});
	},

	reloadBox: function (elemId, boxname, vars) {
		var box = $(elemId);
		if ( typeof box == 'undefined' ) {
			return;
		}

		var params = 'box=' + boxname;
		try {
			if ( vars && typeof vars != 'undefined' ) {
				for ( var idx = 0; idx < vars.length; idx++ )
				params += '&' + vars [ idx ];
			}
		}
		catch(exception) {}

		box.innerHTML = '';
		new Ajax.Request ( 'http://secure.intersportrent.at/buchung/ajaxbox.php', {
			method: 'post',
			postBody: params,
			onSuccess : function(resp){$(elemId).innerHTML = resp.responseText;},
			onFailure: function(resp) {},
			onException: function(resp, exception) {}
		});
	},

	quickinfo: function (selected, set) {
		var shop_id = $('shop_id_' + selected + '_' + set ).value;
		var url='http://secure.intersportrent.at/buchung/quickinfo.php?shop_id=' + shop_id;
		window.document.location.href = url;
		return;
	},

	priceinfo: function (selected, set) {
		var shop_id = $('shop_id_' + selected + '_' + set ).value;
		var url='http://secure.intersportrent.at/buchung/priceinfo.php?shop_id=' + shop_id;
		window.document.location.href = url;
		return;
	},

	
	adjustContainerHeight: function() {
		var l1elements = document.getElementsByClassName("iic_L1_content");
		for(m=0; m<l1elements.length; m++) {
			Element.setStyle(l1elements[m], {height:'500px'});
		}

		Element.setStyle("search_location_dealer_results", {height:'200px'});
		Element.setStyle("iic_select_store_box", {height:'100px'});
		Element.setStyle("iic_location_az_list", {height:'500px'});
	},

	googleMaps: function() {
		icon.image = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarker.png";
		icon.iconSize = new GSize(23, 20);
		icon.iconAnchor = new GPoint(6, 20);
		icon.infoWindowAnchor = new GPoint(5, 1);

		if (GBrowserIsCompatible()) {
			map = new GMap2($('iic_mapping'));
			map.addControl(new GSmallMapControl());
			map.setCenter(new GLatLng(47.8057, 13.0297), 7);
			var mt = map.getMapTypes();

			for (var i=0; i<mt.length; i++) {
				mt[i].getMinimumResolution = function() {return 7;}
				mt[i].getMaximumResolution = function() {return 26;}
			}

			dealers = this.googleMapsData();
			for (i=0; i < dealers.length; i++) {
				d = dealers[i];
				this.googleMapsSetMarker(d,icon,map);
			}
			Element.setStyle($('iic_mapping_selector'), {display:'block'});
			googleMapsLoaded = true;
		}
	},

	googleMapsSetMarker: function(d,icon,map) {
		marker = new PdMarker(new GLatLng(d.poilat,d.poilong),icon);
		var html = this.googleMapsInfoBox(d.poilat,d.poilong,d.name,d.location,d.street,d.plz,d.city,d.tel,d.email,d.shop_id);
		marker.setDetailWinHTML(html);
		marker.setHoverImage("http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarker2.png");
		map.addOverlay(marker);
		GEvent.addListener(marker, "click", function() {
			var myMarker = map.getFirstMarker();
			while ( myMarker != null ) {

				if ( myMarker.detailOpen == true ) {
					if ( markerLoaded != 0 && markerLoaded != myMarker.getId() ) {
						var loadedMarker = map.getMarkerById(markerLoaded);
						loadedMarker.closeDetailWin();
						markerLoaded = 0;
					}

					markerLoaded = myMarker.getId();
				}
				myMarker = map.getNextMarker();
			}
		});
	},

	googleMapsInfoBox: function(plat, plong, name, location, street, plz, city, tel, email, shop_id) {
		var infobox = '<div id="infoBox"><div class="iic_info_box_ID211"><div><h3>'+name+'</h3><p>'+location+' <a style="color:#FFF" href="javascript:isrStep1.googleMapsZoom('+plat+','+plong+')">[zoom]</a><br />'+street+'<br />A-'+plz+' '+city+'<br />Phone: '+tel+'<br />';
		if ( email != 'undefined' && email.length > 0 ) {
		
		}

		infobox += '<br /></p><p><strong>Options</strong><br />- <a href="#" style="color:#FFF" onclick="isrStep1.loadShopExt(\'' + shop_id + '\');">Online Reservation</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/priceinfo.php?lang=en&shop_id=' + shop_id + '">Price Info</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/quickinfo.php?lang=en&shop_id=' + shop_id + '">Shop-Info</a><br /></p></div></div></div>';

		return infobox;
	},

	googleMapsSelector: function(plat, plong, name) {
		var optn = document.createElement("OPTION");
		optn.text = name;
		optn.value = plat+"|"+plong + "|12";
		$('iic_mapping_selector').options.add(optn);
	},

	googleMapsZoom: function(plat,plong,joined) {

		
		var myMarker = map.getFirstMarker();
		while ( myMarker != null ) {

			if ( myMarker.detailOpen == true ) {
				myMarker.closeDetailWin();
				markerLoaded = 0;
			}
			myMarker = map.getNextMarker();
		}

		if (joined)
		{
			co=joined.split("|");

			if (co[0] == 'x') {
				map.setCenter(new GLatLng(47.8057, 13.0297), 7);
			}
			else if (co[0] == 'vb') {
				map.setCenter(new GLatLng(47.240084, 9.882202), 9);
			}
			else if (co[0] == 't') {
				map.setCenter(new GLatLng(47.297859, 11.491699), 8);
			}
			else if (co[0] == 'sbg') {
				map.setCenter(new GLatLng(47.50606978, 13.0078125), 8);
			}
			else if (co[0] == 'k') {
				map.setCenter(new GLatLng(46.86770273, 13.81530761), 8);
			}
			else if (co[0] == 'st') {
				map.setCenter(new GLatLng(47.24567802, 14.8809814453125), 8);
			}
			else if (co[0] == 'oo') {
				map.setCenter(new GLatLng(47.7504047, 14.19433593), 9);
			}
			else if (co[0] == 'no') {
				map.setCenter(new GLatLng(48.0633965, 15.40283203), 9);
			}
			else {
				map.setCenter(new GLatLng(co[0],co[1]), 12);
			}
		}
		else {
			var zoom = map.getZoom();
			if (zoom < 15) {
				zoom = zoom + 1;
			}
			else {
				zoom = 15;
			}
			map.setCenter(new GLatLng(plat,plong), zoom);
		}
	},

	googleMapsData: function() {
		var dealers = googleMapDealers;
		return dealers;
	}
}



var isrStep1ext = Class.create();

isrStep1ext.prototype = {

	handleError: function ( statusText ) {
		iH.hideProcessingInfo();
	},
	handleException: function ( statusText ) {
		iH.hideProcessingInfo();
	},

	initialize: function(data) {
		this.lifts = data.lifts;
		this.orte = data.orte;
		this.quarters = data.quarters;
		this.shops = data.shops;
		this.markers = new Array();
	},

	initMap: function(element) {

		if (GBrowserIsCompatible()) {

			try {

				var points = new Array();
				var zoompoints = new Array();

				this.map = new GMap2(element);

				this.map.addControl(new GSmallMapControl());

				for ( var i = 0; i < this.shops.length; i++) {
					var iconShops = new GIcon();
					iconShops.iconSize = new GSize(17, 22);
					iconShops.iconAnchor = new GPoint(6, 20);
					iconShops.infoWindowAnchor = new GPoint(5, 1);
					iconShops.image = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerShops_" +  i + ".png";
					var shop = this.shops[i];

					var html = "";
					if ((typeof (shop.countshop) != undefined) && (typeof (shop.countmember) != undefined)) {

						if (this.orte.length > 0) {
							ort = this.orte[0];
						}
						else {
							ort.id = 0;
						}

						html = this.googleMapsInfoShop(shop.lat,shop.lng,shop.name,shop.standort,shop.strasse,shop.plz,shop.ort,shop.telefon,shop.showemail,shop.id,shop.countshop,shop.countmember,ort.id);
					}
					else {
						html = this.googleMapsInfoBox(shop.lat,shop.lng,shop.name,shop.standort,shop.strasse,shop.plz,shop.ort,shop.telefon,shop.showemail,shop.id);
					}
					shop.html = html;
					shop.icon = iconShops;
					shop.hover = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerShops_" +  i + ".png";
					shop.type = "shops";

					this.markers.push(shop);
				}
				
				
				for ( i = 0; i < this.markers.length; i++) {
					mark = this.markers[i];
					zoompoints.push(new GLatLng(mark.lat,mark.lng));
					this.googleMapsSetMarker (mark.lat,mark.lng,mark.html,mark.icon,mark.type);

				}
				var polyline =  new GPolyline(zoompoints);
				var bounds = polyline.getBounds();
				var zoomlevel = (this.map.getBoundsZoomLevel(bounds));
				if (zoomlevel > 16) {
					zoomlevel = 16;
				}

				this.map.setCenter(bounds.getCenter(), zoomlevel);
				
				var iconQuarters = new GIcon();
				iconQuarters.image = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerQuarters.png";
				iconQuarters.iconSize = new GSize(20, 23);
				iconQuarters.iconAnchor = new GPoint(9, 23);
				iconQuarters.infoWindowAnchor = new GPoint(5, 1);
				for ( i = 0; i < this.quarters.length; i++) {
					var q = this.quarters[i];
					var html2 = this.googleMapsInfoHotels(q.lat,q.lng,q.name,q.adress,q.zip,q.city,q.url);
					q.html = html2;
					q.icon = iconQuarters;
					q.hover = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerQuarters.png";
					q.type = "quarters";
					this.markers.push(q);
				}

				var iconLift = new GIcon();
				iconLift.image = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerLifts.png";
				iconLift.iconSize = new GSize(20, 23);
				iconLift.iconAnchor = new GPoint(9, 23);
				iconLift.infoWindowAnchor = new GPoint(5, 1);

				for ( i = 0; i < this.lifts.length; i++) {
					var lift = this.lifts[i];
					var html3 = this.googleMapsInfoLifts(lift.lat,lift.lng,lift.name,lift.skiname);
					lift.html = html3;
					lift.icon = iconLift;
					lift.hover = "http://secure.intersportrent.at/buchung/themes/_default/images/layout/mapMarkerLifts.png";
					lift.type = "lift";
					this.markers.push(lift);

				}
				
				for ( i = 0; i < this.markers.length; i++) {
					mark = this.markers[i];
					points.push(new GLatLng(mark.lat,mark.lng));
					this.googleMapsSetMarker (mark.lat,mark.lng,mark.html,mark.icon,mark.type, mark.hover);

				}
				this.googleMapsClearMarker();
			
			}
			catch (e) {

			}
		}
	},
	googleMapsSetMarker: function(lat,lng,html,icon,type,hover) {
		var marker = new PdMarker(new GLatLng(lat,lng),icon);
		marker.type = type;
		marker.setDetailWinHTML(html);
		
		marker.setHoverImage(hover);

	
		marker.setMarkerOnClick(false);

		this.map.addOverlay(marker);

		GEvent.addListener(marker, "mouseover", function() {

			var myMarker = this.map.getFirstMarker();
			detailOpen = true;
			while ( myMarker != null ) {
				if ( myMarker.detailOpen == true ) {
					if ( markerLoaded != 0 && markerLoaded != myMarker.getId() ) {
						var loadedMarker = this.map.getMarkerById(markerLoaded);
						loadedMarker.closeDetailWin();
						markerLoaded = 0;
					}
					markerLoaded = myMarker.getId();
				}
				myMarker = this.map.getNextMarker();
			}
		});
	},
	googleMapsInfoBox: function(plat, plong, name, location, street, plz, city, tel, email, shop_id) {

		var i = 0;
		var infobox = '<div id="infoBox"><div class="iic_info_box_ID211"><div><h3>'+name+'</h3><p>'+location+' <a style="color:#FFF" href="javascript:isrStep1.googleMapsZoom('+plat+','+plong+')">[zoom]</a><br />'+street+'<br />A-'+plz+' '+city+'<br />Phone: '+tel+'<br />';
		if ( typeof(email) != 'undefined' && email.length > 0 ) {
		
		}
		infobox += '<br /></p><p><strong>Options</strong><br />- <a href="#" style="color:#FFF" onclick="isrStep1.loadShopExt(\'' + shop_id + '\');">Online Reservation</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/priceinfo.php?lang=en&shop_id=' + shop_id + '">Price Info</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/quickinfo.php?lang=en&shop_id=' + shop_id + '">Shop-Info</a><br /></p></div></div></div>';

		return infobox;
	},

	googleMapsInfoShop: function(plat, plong, name, location, street, plz, city, tel, email, shop_id, shopcount, shopmember, cityId) {

		
		var infobox = '<div id="infoBox"><div class="iic_info_box_ID211"><div><h3>'+name+'</h3><p>'+location+' <a style="color:#FFF" href="javascript:isrStep1.googleMapsZoom('+plat+','+plong+')">[zoom]</a><br />'+street+'<br />A-'+plz+' '+city+'<br />Phone: '+tel+'<br />';

		infobox += '<br /></p><p><strong>Options</strong><br />- <a href="#" style="color:#FFF" onclick="isrStep1.selectShopExt(\'' + shopcount + '\',\''+ shopmember  + '\',\'cityHeader_' + cityId + '\');">Online Reservation</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/priceinfo.php?lang=en&shop_id=' + shop_id + '">Price Info</a><br />- <a style="color:#FFF" href="http://secure.intersportrent.at/buchung/quickinfo.php?lang=en&shop_id=' + shop_id + '">Shop-Info</a><br /></p></div></div></div>';

		return infobox;
	},


	googleMapsInfoHotels: function(plat, plong, name, street, plz, city, url) {
		var infobox = '<div id="infoBox"><div class="iic_info_box_ID211"><div><h3>'+name+'</h3><p> <a style="color:#FFF" href="javascript:isrStep1.googleMapsZoom('+plat+','+plong+')">[zoom]</a><br />'+street+'<br />A-'+plz+' '+city;

		infobox += '<br /></p><p><strong>Options</strong><br />- <a target="_blank" href="http://www.bergfex.at' + url + '" style="color:#FFF">Online Reservation</a><br /></p></div></div></div>';

		return infobox;
	},

	googleMapsInfoLifts: function(plat, plong, name, location) {
		var infobox = '<div id="infoBox"><div class="iic_info_box_ID211"><div><h3>'+name+'</h3><p>'+location+' <a style="color:#FFF" href="javascript:isrStep1.googleMapsZoom('+plat+','+plong+')">[zoom]</a><br />';
		infobox += '</div></div></div>';
		return infobox;
	},
	showhide: function (input,type) {

		var myMarker = this.map.getFirstMarker();
		while ( myMarker != null ) {
			if (myMarker.type == input.value) {


				if (input.checked == true) {
					myMarker.show();
				}
				else {
					myMarker.hide();
				}
			}
			myMarker = this.map.getNextMarker();

		}
	},
	googleMapsClearMarker: function(type) {
		var myMarker = this.map.getFirstMarker();
		while ( myMarker != null ) {

			if (myMarker.type == "quarters" && this.quarters.length == 1) {
			
				try {
					$('googlecontrolquartersselect').checked = true;
					var zoomlevel = this.map.getZoom();
					var lat = this.quarters[0].lat;
					var lng = this.quarters[0].lng;
					this.map.setCenter(new GLatLng(lat,lng), zoomlevel);
				}
				catch (e) { }
			}
			else if (myMarker.type == "quarters" || myMarker.type == "lift") {
				myMarker.hide();
			}
			if (this.lifts.length == 0 ) {
				$('googlecontrollifts').removeClassName('lifts');
				$('googlecontrollifts').update('');
			}
			myMarker = this.map.getNextMarker();
		}
	},
	array_merge: function (one, two) {
		one.push(two);
		return one.flatten();
	}
}


var shopStartInterval;

function shopstart() {
	 shopStartInterval = window.setInterval("shopstartHelper()", 100);
}

function shopstartHelper() {

	if(typeof isrStep1.selectShop == "function") {
		if($("iic_time_selection_box")) {
			isrStep1.selectShop( '0', '1', 'cityHeader_' );
			
			if ( typeof(shopStartInterval) != undefined) {
				clearInterval(shopStartInterval);
			}
		}
	}
}




﻿

var checkRunning = false;

var isrStep2 = {

	handleError: function ( statusText ) {
		if (isrjsdebug) {
			try {
				console.log (statusText);
			}
			catch (e) {}
		}
		iH.hideProcessingInfo();
	},
	handleException: function ( statusText, func ) {
		if (isrjsdebug) {
			try {
				console.log (statusText);
			}
			catch (e) {}
		}
		iH.hideProcessingInfo();
	},

	
	gotoStepTwo: function() {
		$('iic_no_dealer_found').innerHTML = '';
		var element = $('iic_select_by_region').options [ $('iic_select_by_region').selectedIndex ];
		var shop_id = $('shop_id_' + selectedshowPersonalDataFormStore + '_' + selectedSetOfStores ).value;
		var params = 'ajax=1&use=dealer&check=timestamp&id=' + shop_id + '&from_day=' + $('from_day').value;
		params += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
		params += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
		params += '&until_year=' + $('until_year').value;
		new Ajax.Request ( ajaxServiceURL, {
			method: 'post',
			postBody: params,
			onSuccess : this.determineTimestamp,
			onFailure: function(resp) { isrStep2.handleError ( resp.statusText, 'gotoStepTwo' ); },
			onException: function(resp, exception) { isrStep2.handleException ( exception, 'gotoStepTwo' ); }
		});
	},

	gotoPayment: function() {
		isrSession.hasBuyer(
			function () { window.document.location.href = 'http://secure.intersportrent.at/buchung/?state=6'; },
			function () { Checkout.showBuyerDataForm(); }
		);
	},


	toggleSelectProductList: function(myObj,selector) {
		if ( typeof selector == 'undefined' ) {
			return;
		}
		if ( $(current_product_list) ) {
			$(current_product_list).style.display = "none";
		}
		selector.className = "active";
		selectors = $('iic_tbw_navigation').getElementsByTagName('a');
		for(i_selector=0;i_selector<selectors.length;i_selector++) {
			if(selectors[i_selector] != selector) {
				selectors[i_selector].className = "";
			}
		}
		$(myObj).style.display = "block";
		current_product_list = myObj;
		isrHistory.productSelection ( current_product_list );
	},


	setCategoryStatus: function (tab,category,active,gruppe) {
		if ( checkRunning ) {
			return;
		}
		if(active.title == "active") {
			active.title = "";
			product_selected = product_selected > 0 ? product_selected - 1 : 0;
		}
		else {
			active.title = "active";
			product_selected ++;
		}
		
		if ($('a_product_select_by_feature')) {
			switch (tab) {
				case "category":
					var other1 = "product";
					var other2 = "feature";
					break;
				case "product":
					var other1 = "category";
					var other2 = "feature";
					break;
				case "feature":
					var other1 = "category";
					var other2 = "product";
					break;
				case "default":
					alert("error");
			}
			checkRunning = true;
			if ( ! gruppe ) {
				this.setTabEntries ( tab, category, active.title == 'active', active );
				this.setTabEntries ( other1, category, active.title == 'active', active );
				this.setTabEntries ( other2, category, active.title == 'active', active );
			}
			else if ( gruppe && gruppe.length > 0 ) {
				var len = gruppe.length;
				for ( kdx = 0; kdx < gruppe.length; kdx++ ) {
					this.setTabEntries ( tab, gruppe[kdx], active.title == 'active', active );
					this.setTabEntries ( other1, gruppe[kdx], active.title == 'active', active );
					this.setTabEntries ( other2, gruppe[kdx], active.title == 'active', active );
				}
			}
		}
		else {
			var other = tab == 'category' ? 'product' : 'category';

			checkRunning = true;
			if ( ! gruppe ) {
				this.setTabEntries ( tab, category, active.title == 'active', active );
				this.setTabEntries ( other, category, active.title == 'active', active );
			}
			else if ( gruppe && gruppe.length > 0 ) {
				var len = gruppe.length;
				for ( kdx = 0; kdx < gruppe.length; kdx++ ) {
					this.setTabEntries ( tab, gruppe[kdx], active.title == 'active', active );
					this.setTabEntries ( other, gruppe[kdx], active.title == 'active', active );
				}
			}
		}
		checkRunning = false;
		return true;
	},
	setTabEntries: function(tab, category, isActive, active) {
		if ( ! $(tab + '_category_' + category) ) {
			return;
		}
		var checkboxes = $(tab + '_category_' + category).getElementsByTagName("input");

		for( idx = 0; idx < checkboxes.length; idx++) {
			if(isActive) {
				if(checkboxes[idx] != active) {
					checkboxes[idx].disabled = true;
				}
			}
			else {
				if(checkboxes[idx] != active)
				checkboxes[idx].disabled = false;
			}
		}
	},

	resetProductCategories: function() {
		product_selected
		var checkboxes = document.getElementsByName("select_product");
		for(xdx=0;xdx<checkboxes.length;xdx++) {
			checkboxes[xdx].disabled = false;
			checkboxes[xdx].checked = false;
			checkboxes[xdx].title = '';
		}
	},

	showProductSelection: function () {
		if ( current_step2_item == 'product_selection' ) {
			return;
		}
		current_step2_item = 'product_selection';

		var products = $('product_selection');

		if ( typeof products == 'undefined' ) {
			window.document.location.href = 'http://secure.intersportrent.at/buchung/?state=2&basket=0#product_select_by_category';
		}
		else {
			current_step2_item = 'product_selection';
			checkRunning = false;
			product_selected = 0;
		
			isrEffects.toggle ( 'product_selection', 'blind' );
			isrEffects.toggle ( 'shopping_cart_detail', 'blind' );
			$('person_data_overlay').style.display = 'none';
			$('person_data_box').style.display = 'none';
			this.resetProductCategories();
			Basket.reloadSmallBasket();
			this.showCheckout();

			isrHistory.productSelection ( current_product_list );
		}
	},

	showCheckout: function () {
		if ( ! $('product_selection' ) ) {
			return;
		}

		new Ajax.Request ( 'http://secure.intersportrent.at/buchung/ajaxbox.php', {
			method: 'post',
			postBody: 'box=smallbasket&count=1',
			onSuccess : function(resp) {
				var xml = resp.responseXML;
				var results = xml.getElementsByTagName ( 'result' );

				var result = 0;
				if ( results && results.length > 0 ) {
					result = parseInt ( results [ 0 ].firstChild.nodeValue );
				}

				if ( result <= 0 ) {
					Element.hide ( 'button_checkout_cat_top' );
					Element.hide ( 'button_checkout_cat_bottom' );
					Element.hide ( 'button_checkout_prd_top' );
					Element.hide ( 'button_checkout_prd_bottom' );
					Element.hide ( 'button_checkout_fea_top' );
					Element.hide ( 'button_checkout_fea_bottom' );
				}
				else {
					Element.show ( 'button_checkout_cat_top' );
					Element.show ( 'button_checkout_cat_bottom' );
					Element.show ( 'button_checkout_prd_top' );
					Element.show ( 'button_checkout_prd_bottom' );
					Element.show ( 'button_checkout_fea_top' );
					Element.show ( 'button_checkout_fea_bottom' );
				}
			},
			onFailure: function(resp) {},
		
			onException: function(resp, exception) {}
		});
	},

	loadExistingCustomer:function (productIds) {
		var elementId = $('existingCustomer').options [ $('existingCustomer').selectedIndex ];
		if ( typeof elementId.value == 'undefined' ) {
			return;
		}
		if ( elementId.value != 0 ) {
			var params = ""
			for ( i = 0; i < productIds.length; i++ ) {
				if ( params.length > 0 ) params += '&';
				params += 'product[]=' + productIds [ i ];
			}
			var url =  'http://secure.intersportrent.at/buchung/index.php';

			iH.showProcessingInfo();
			Element.setStyle('person_data_container', {display:'none'});
			Element.setStyle('person_data_overlay', {display:'none'});

			new Ajax.Request ( url, {
				method: 'post',
				postBody: 'ajax=1&' + params + '&loaduser=' + elementId.value,
				onSuccess : isrStep2.doSuccessLoadPersonForm,
				onFailure: function(resp) { isrStep2.handleError ( resp.statusText, 'loadExistingCustomer' ); },
				onException: function(resp, exception) { isrStep2.handleException ( exception, 'loadExistingCustomer' ); }
			});
		}
	},

	loadNewCustomer:function (productIds) {
		var params = ""
		for ( i = 0; i < productIds.length; i++ ) {
			if ( params.length > 0 ) params += '&';
			params += 'product[]=' + productIds [ i ];
		}
		var url =  'http://secure.intersportrent.at/buchung/index.php';

		iH.showProcessingInfo();
		Element.setStyle('person_data_container', {display:'none'});
		Element.setStyle('person_data_overlay', {display:'none'});

		new Ajax.Request ( url, {
			method: 'post',
			postBody: 'ajax=1&' + params + '&loaduser=0',
			onSuccess : isrStep2.doSuccessLoadPersonForm,
			onFailure: function(resp) { isrStep2.handleError ( resp.statusText, 'loadNewCustomer' ); },
			onException: function(resp, exception) { isrStep2.handleException ( exception, 'loadNewCustomer' ); }
		});
	},


	showPersonalDataForm:function()
	{
		var productIds = new Array();
		var boxes = document.getElementsByTagName('input');
		var counter = 0;

		for ( i = 0; i < boxes.length; i++ ) {
			if ( boxes [ i ].title == 'active' ) {
				productIds [ counter ] = boxes [ i ].value;
				counter++;
			}
		}

		if ( productIds.length <= 0 ) {
			return;
		}
		iH.showProcessingInfo();

		isrStep2.loadPersonDataForm( productIds );
	},

	loadPersonDataForm: function( productIds ) {
		iH.showProcessingInfo();
		var params = ""
		for ( i = 0; i < productIds.length; i++ ) {
			if ( params.length > 0 ) params += '&';
			params += 'product[]=' + productIds [ i ];
		}
		var url =  'http://secure.intersportrent.at/buchung/index.php';
		$('person_data_container').innerHTML = '';
		new Ajax.Request ( url, {
			method: 'post',
			postBody: 'ajax=1&reload=1&' + params,
			onSuccess : isrStep2.doSuccessLoadPersonForm,
			onFailure: function(resp) { isrStep2.handleError ( resp.statusText, 'loadPersonDataForm' ); },
			onException: function(resp, exception) { isrStep2.handleException ( exception, 'loadPersonDataForm' ); }
		});
	},

	doSuccessLoadPersonForm: function( res ) {
		if ( res.responseText.length < 50 ) {
			isrStep2.closePersonalDataForm();

			try {
				Element.setStyle('person_data_container', {display:'none'});
				Element.setStyle('person_data_overlay', {display:'none'});
				Element.setStyle('person_data_box', {display:'none'});
				Element.setStyle('processing_info_overlay', {display:'none'});

			}
			catch (exception) {}

			if ( 'true' == 'true' ) {
				window.document.location.href = 'http://secure.intersportrent.at/buchung/?state=2&basket=1';
			}
			else {
				Basket.show();
			}
			return;
		}
		$('person_data_container').innerHTML = res.responseText;
		isrStep2.hideSelectBoxes();

		offset = Position.realOffset($('person_data_box'));
		newOffset = offset[1]+50;
		$('person_data_box').style.top = newOffset+'px';
		$('person_data_overlay').style.display = 'block';
		$('person_data_box').style.display = 'block';
		var arrayPageSize = getPageSize();
		Element.setHeight('person_data_overlay', arrayPageSize[1]);
		iH.hideProcessingInfo();
		Element.setStyle('person_data_overlay', {display:'block'});
		Element.setStyle('person_data_container', {display:'block'});
		isrStep2.showPersonalDataFormSelectBoxes();
		new Ajax.Autocompleter('age_day','age_day_update','/buchung/autocompletedata.php?i=day',{paramName:'var',tokens:[',', ' ']});
		new Ajax.Autocompleter('age_month','age_month_update','/buchung/autocompletedata.php?i=month',{paramName:'var',tokens:[',', ' ']});
		new Ajax.Autocompleter('age_year','age_year_update','/buchung/autocompletedata.php?i=year',{paramName:'var',tokens:[',', ' ']});
		new Ajax.Autocompleter('AccomodationatDestination','AccomodationatDestination_update','/buchung/autocompletedata.php?i=quarters',{paramName:'var',tokens:[',', ' ']});
	},

	closePersonalDataForm: function()
	{
		isrStep2.hidePersonalDataFormSelectBoxes();
		$('person_data_overlay').style.display = 'none';
		$('person_data_box').style.display = 'none';
		isrStep2.showSelectBoxes();
	},

	submitUserData: function(productIds) {
		var params = 'ajax=1';
		if ( typeof $('existingCustomer') != undefined ) {
			var elementId = $('existingCustomer').options [ $('existingCustomer').selectedIndex ];
			if ( typeof elementId.value == 'undefined' )

			if ( elementId.value != 0 )
			params += '&loaduser=' + elementId.value;
		}
		for ( i = 0; i < productIds.length; i++ ) {
			params += '&product[]=' + productIds [ i ];
		}
		var selectBoxen = $('personal_data_form').getElementsByTagName ( 'select' );
		for ( i = 0; i < selectBoxen.length; i++ ) {
			params += '&' + selectBoxen[i].name + '=' + $F(selectBoxen[i].id);
		}
		var selectBoxen = $('personal_data_form').getElementsByTagName ( 'input' );
		for ( i = 0; i < selectBoxen.length; i++ ) {
			params += '&' + selectBoxen[i].name + '=' + selectBoxen[i].value;
		}
		params += '&note=' + $('FurtherInformation').value;
		var url =  'http://secure.intersportrent.at/buchung/index.php';

		Element.setStyle('person_data_container', {display:'none'});
		Element.setStyle('person_data_overlay', {display:'none'});
		iH.showProcessingInfo();
		
		new Ajax.Request ( url, {
			method: 'post',
			postBody: params,
			onSuccess : isrStep2.doSuccessLoadPersonForm,
			onFailure: function(resp) { isrStep2.handleError ( resp.statusText, 'submitUserData' ); },
			onException: function(resp, exception) { isrStep2.handleException ( exception, 'submitUserData' ); }
		});
	},


	showSelectBoxes: function(){
		selects = document.getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			Element.setStyle ( selects[i], {visibility: 'visible'} );
		}
	},


	hideSelectBoxes: function(){
		selects = document.getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			Element.setStyle ( selects[i], {visibility: 'hidden'} );
		}
	},


	showPersonalDataFormSelectBoxes: function()
	{
		selects = $('person_data_box').getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			Element.setStyle ( selects[i], {visibility: 'visible'} );
		}
	},

	hidePersonalDataFormSelectBoxes: function()
	{
		selects = $('person_data_box').getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			Element.setStyle ( selects[i], {visibility: 'hidden'} );
		}
	},

	showHideImages: function(element,elementClassName)
	{
		var nodeList = document.getElementsByClassName(elementClassName);
		var nodes = $A(nodeList);

		nodes.each(function(node)
		{
			if (element.checked == true)
			{
				Element.setStyle(node, {display:'block'});
			}
			else
			Element.setStyle(node, {display:'none'});
		});

		$('iic_product_images_cat_checkbox').checked = element.checked;
		$('iic_product_images_prod_checkbox').checked = element.checked;
	}
}

function showfeature(element,featureelement) {
	try {
		if ($(featureelement)) {

			if (element.checked) {

				$(featureelement).setStyle({display:'block'});
			}
			else {
				$(featureelement).setStyle({display:'none'});
			}
		}
		return true;
	}
	catch (exception) {
		alert (exception);
	}

	return true;
}


var isrSchool = {

	showError : function ( errText ) {
		if ( ! $('iic_school_error' ) )
			return;
		if ( ! Element.visible ( 'iic_school_error' ) )
			Effect.BlindDown ( 'iic_school_error' );
		$('iic_school_error').innerHTML = errText;
		isrSchool.hideProcessingInfo();
	},

	hideError: function () {
		isrSchool.hideProcessingInfo();
		if ( ! $('iic_school_error' ) )
			return;
		if ( Element.visible ( 'iic_school_error' ) )
			Effect.BlindUp ( 'iic_school_error' );
		$('iic_school_error').innerHTML = '';
	},

	showProcessingInfo: function () {
		try { iH.showProcessingInfo(); }
		catch (exception) {}
	},

	hideProcessingInfo: function () {
		try { iH.hideProcessingInfo(); }
		catch (exception) {}
	},

	
	loadSchoolContent : function( func, params ) {
		isrSchool.showProcessingInfo();
		new Ajax.Request ( 'http://secure.intersportrent.at/buchung/ajax.php',
		{
			method: 'post',
			postBody: encodeURI ( 'module=sportwochen&noxml=1&ajax=1&method=' + func + params ),
			onSuccess : function(resp) {
		
			$('school_content').innerHTML = resp.responseText;
			isrSchool.hideError();
			},
			onFailure: function(resp) { isrSchool.hideProcessingInfo(); },
			onException: function(resp, exception) { isrSchool.hideProcessingInfo(); }
		});
	},

	firstStep: function (add)
	{
		var params = ( add && typeof (add) != 'undefined' ) ? add : '';

		var fields = $('iic_school_form').getElementsByTagName ( "input" );
		for ( var i = 0; i < fields.length; i++ ) {
			if ( fields [ i ].type == 'hidden' ) {
				params += '&' + fields [ i ].name + '=' + fields [ i ].value;
			}
		}

		var keys = [ 'name', 'street', 'plz', 'city' ];
		var errs = [ 'Please enter the name of your school', 'Please enter the address for your school',
			'Please provide the postal code and city for your school', 'Please provide the postal code and city for your school' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var fieldId = 'iic_school_' + keys [ i ];
			var err = errs [ i ];

			if ( $(fieldId) && typeof $(fieldId) != 'undefined' ) {
				if ( $F(fieldId).length == 0 ) {
					isrSchool.showError ( err ); return;
				} else {
					params += '&schule_' + keys [ i ] + '=' + $F(fieldId);
				}
			}
		}

		if ( $F('iic_school_phone').length == 0 && $F('iic_school_fax').length == 0 && $F('iic_school_email').length == 0 ) {
			isrSchool.showError ( 'We need a contact for your school. Please provide either the phone number, a fax number or an e-mail address' );
			return;
		}

		var keys = [ 'phone', 'fax', 'email', 'homepage' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var fieldId = 'iic_school_' + keys [ i ];
			if ( $(fieldId) && typeof $(fieldId) != 'undefined' ) {
				if ( $F(fieldId).length != 0 )
					params += '&schule_' + keys [ i ] + '=' + $F(fieldId);
			}
		}

		this.loadSchoolContent ( 'teacher ', params );
	},

	secondStep: function (add)
	{
		var params = ( add && typeof (add) != 'undefined' ) ? add : '';

		var fields = $('iic_school_form').getElementsByTagName ( "input" );
		for ( var i = 0; i < fields.length; i++ ) {
			if ( fields [ i ].type == 'hidden' ) {
				params += '&' + fields [ i ].name + '=' + fields [ i ].value;
			}
		}

		var keys = [ 'name' ];
		var errs = [ 'You must define a name!' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var field_id = 'iic_teacher_' + keys [ i ];
			var err = errs [ i ];

			if ( $(field_id) && typeof $(field_id) != 'undefined' ) {
				if ( $F(field_id).length == 0 ) {
					isrSchool.showError ( err ); return;
				} else {
					params += '&teacher_' + keys [ i ] + '=' + $F(field_id);
				}
			}
		}

		if ( $F('iic_teacher_phone').length == 0 && $F('iic_teacher_fax').length == 0 && $F('iic_teacher_email').length == 0 ) {
			isrSchool.showError ( 'We need a way of contacting you. Please fill out either the phonenumber, the fax or provide an email address.' );
			return;
		}

		var keys = [ 'phone', 'fax', 'email' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var fieldId = 'iic_teacher_' + keys [ i ];
			if ( $(fieldId) && typeof $(fieldId) != 'undefined' ) {
				if ( $F(fieldId).length != 0 )
					params += '&teacher_' + keys [ i ] + '=' + $F(fieldId);
			}
		}
		params += '&teacher_newsletter=' + ( $('iic_teacher_newsletter').checked ? '1' : '0' );

		this.loadSchoolContent ( 'unterkunft', params );
	},

	thirdStep: function (add)
	{
		var params = ( add && typeof (add) != 'undefined' ) ? add : '';

		var fields = $('iic_school_form').getElementsByTagName ( "input" );
		for ( var i = 0; i < fields.length; i++ ) {
			if ( fields [ i ].type == 'hidden' ) {
				params += '&' + fields [ i ].name + '=' + fields [ i ].value;
			}
		}
		var keys = [ 'name' ];
		var errs = [ 'Please provide us with the name of your accomodation' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var field_id = 'iic_accomodation_' + keys [ i ];
			var err = errs [ i ];

			if ( $(field_id) && typeof $(field_id) != 'undefined' ) {
				if ( $F(field_id).length == 0 ) {
					isrSchool.showError ( err ); return;
				} else {
					params += '&accomodation_' + keys [ i ] + '=' + $F(field_id);
				}
			}
		}

		if ( $F('iic_accomodation_phone').length == 0 && $F('iic_accomodation_email').length == 0 ) {
			isrSchool.showError ( 'We need a contact for your accomodation. Please provide us with either a phone number, a fax number or an e-mail address.' );
			return;
		}

		var keys = [ 'phone', 'email', 'street', 'plz', 'city', 'contact' ];
		for ( var i = 0; i < keys.length; i++ ) {
			var fieldId = 'iic_accomodation_' + keys [ i ];

			if ( $(fieldId) && typeof $(fieldId) != 'undefined' ) {
				if ( $F(fieldId).length != 0 )
					params += '&accomodation_' + keys [ i ] + '=' + $F(fieldId);
			}
		}

		this.loadSchoolContent ( 'times', params );
	},

	fourthStep: function (add)
	{
		var params = ( add && typeof (add) != 'undefined' ) ? add : '';

		var fields = $('iic_school_form').getElementsByTagName ( "input" );
		for ( var i = 0; i < fields.length; i++ ) {
			if ( fields [ i ].type == 'hidden' ) {
				params += '&' + fields [ i ].name + '=' + fields [ i ].value;
			}
		}

		if ( $F('iic_ort_name').length == 0 ) {
			isrSchool.showError ( 'You must provide a travel location' );
			return;
		} else
			params += '&ort_name=' + $F('iic_ort_name');

		if ( $F ( 'iic_ort_bundesland' ) == 0 ) {
			isrSchool.showError ( 'Please select a district' );
			return;
		} else
			params += '&ort_bundesland=' + $F('iic_ort_bundesland');

		params += '&anreise_datum=' + $F('datum_anreise_day') + '.' + $F('datum_anreise_month') + '.' + $F('datum_anreise_year');

		var __today = new Date();
		var __year = parseInt(__today.getYear());

		if (__year < 1000) __year += 1900;

		var __month = parseInt(__today.getMonth())+1;
		var __day = parseInt(__today.getDate());

		var __utc_day = parseInt(Date.UTC(__year,__month, __day , 0, 0, 0));
		var __utc_today = parseInt(Date.UTC(parseInt($F('datum_anreise_year')), parseInt($F('datum_anreise_month')), parseInt($F('datum_anreise_day')) , 0, 0, 0));

		var __diff =  __utc_today - __utc_day;

	
		if ( __diff < 604800000 ) {
			isrSchool.showError ( '1. Rental must be at least 7 days ahead' );
			return;
		}

		if ( $F ( 'datum_days' ) == 0 ) {
			isrSchool.showError ( 'You must provide the number of days your are going to stay.' );
			return;
		}
		else {
			params += '&datum_days=' + $F('datum_days');
		}

		if ( $F ( 'anzahl' ) == 0 ) {
			isrSchool.showError ( 'Please provide the number of pupils.' );
			return;
		}
		else {
			params += '&anzahl=' + $F('anzahl');
		}

		this.loadSchoolContent ( 'kids', params );
	},

	fifthStep: function (add) {

		$('iic_school_form').submit();
		return;
	},

	handleDateSelection: function(prefix) {
		var hidden = $(prefix + '_hidden' );


		if ( ! hidden.value || hidden.value.length <= 0 )
			return '';
		var date = hidden.value;
		var day = date.substr ( 0, date.indexOf ( '.' ) );
		$( prefix + '_day' ).selectedIndex = day - 1;

		var month = date.substr ( date.indexOf ( '.' ) + 1, 2 );
		$( prefix + '_month' ).selectedIndex = month - 1;

		var year = date.substr ( date.lastIndexOf ( '.' ) + 1 );
		$( prefix + '_year' ).value = year;
	},

	updateHiddenDate: function(prefix) {
		var hidden = $(prefix + '_hidden' );
		if ( ! hidden.value )
			return '';

		var day = LZ($F(prefix + '_day' ));
		var month = LZ($F(prefix + '_month' ));
		var year = LZ($F(prefix + '_year' ));
		hidden.value = day + '.' + month + '.' + year;
	},

	getStartDate: function(myDate) {
		var newDate = new Date();
		if ( myDate && myDate.length == 10 ) {

			var nday = myDate.substr ( 0, myDate.indexOf ( '.' ) ) ;
			var nmonth = myDate.substr ( myDate.indexOf ( '.' ) + 1, 2 );
			var nyear = myDate.substr ( myDate.lastIndexOf ( '.' ) + 1 );

			if ( nyear > 0 && nmonth > 0 && nday > 0 ) {
				newDate.setDate(nday);
				newDate.setMonth(nmonth);
				newDate.setFullYear(nyear);
			}
		}

		return newDate;
	},

	
	initCalendar: function()
	{
		var seasonStart = isrSchool.getStartDate ( $('datum_anreise_hidden') );

		Calendar.setup
		(
			{
			inputField  : "datum_anreise_hidden",
			ifFormat    : "%d.%m.%Y",
			daFormat    : "%d.%m.%Y",
			firstDay: 1,
			showsTime: false,
			showOthers: true,
			timeFormat: 24,
			button      : "selectDateAnreise",
			range   : [seasonStart.getFullYear(),seasonEnd.getFullYear()]
			}
		);
	},

	
	adjustContainerHeight: function()
	{
		var l1elements = document.getElementsByClassName("iic_L1_content");
		for(m=0; m<l1elements.length; m++)
		Element.setStyle(l1elements[m], {height:'500px'});

		Element.setStyle("search_location_dealer_results", {height:'200px'});
		Element.setStyle("iic_select_store_box", {height:'100px'});
		Element.setStyle("iic_location_az_list", {height:'500px'});
	}

}



var Basket = {

    
    load: function()
    {

        current_step2_item = 'basket_display';
       
        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/index.php', {
            method: 'post',
            postBody: 'ajax=1&basket=1&state=2',
            onSuccess : function(resp)
             {
                $('shopping_cart_detail').innerHTML = resp.responseText;
                Basket.reloadSmallBasket();
                Profile.reloadProfileBox();
             },
            onFailure: function(resp) {},
            onException: function(resp, exception) { alert ( 'Load: ' + exception ); }
        });
    },

    show: function() {
        if ( current_step2_item == 'basket_display' ) {
            Basket.reloadSmallBasket();
            return;
        }
        iH.showProcessingInfo();

        var basket = $('shopping_cart_detail');
        if ( typeof basket == 'undefined' )
            window.document.location.href = 'http://secure.intersportrent.at/buchung/?state=2&basket=1';
        else {
            isrEffects.toggle ( 'product_selection', 'blind' );
            isrEffects.toggle ( 'shopping_cart_detail', 'blind' );
            $('person_data_overlay').style.display = 'none';
            $('person_data_box').style.display = 'none';
            try {
            Element.setStyle('person_data_container', {display:'none'});
            Element.setStyle('person_data_overlay', {display:'none'});
            Element.setHeight('person_data_container', 0);
            Element.setHeight('person_data_overlay', 0);
            } catch (exception) {}
            this.load();
            iH.hideProcessingInfo();
            isrStep2.resetProductCategories();
            isrHistory.basket();
        }
    },

    loadLastReservation: function() {

        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/index.php', {
            method: 'post',
            postBody: 'ajax=1&basket=1&state=2&loadprofile=1',
            onSuccess : function(resp)
             {
                $('shopping_cart_detail').innerHTML = resp.responseText;
                Basket.reloadSmallBasket()
                Profile.reloadProfileBox();
                Basket.show();
                iH.hideProcessingInfo();
             },
            onFailure: function(resp) {},
            onException: function(resp, exception) { alert ( 'Load: ' + exception ); }
        });
    },

    remove: function(user_id, product_id)
    {
        iH.showProcessingInfo();
        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/index.php', {
            method: 'post',
            postBody: 'ajax=1&basket=1&state=2&user=' + user_id + '&remove=' + product_id,
            onSuccess : function(resp)
             {
                $('shopping_cart_detail').innerHTML = resp.responseText;
                Basket.reloadSmallBasket()
                Profile.reloadProfileBox();
                iH.hideProcessingInfo();
             },
            onFailure: function(resp) {iH.hideProcessingInfo();},
            onException: function(resp, exception) {iH.hideProcessingInfo();}
        });
    },

    emptyBasket: function()
    {
        iH.showProcessingInfo();
        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/index.php', {
            method: 'post',
            postBody: 'ajax=1&basket=1&state=2&empty=1',
            onSuccess : function(resp)
             {
                $('shopping_cart_detail').innerHTML = resp.responseText;
                Profile.reloadProfileBox();
                Basket.show();
                iH.hideProcessingInfo();
             },
            onFailure: function(resp) {iH.hideProcessingInfo();},
            onException: function(resp, exception) {iH.hideProcessingInfo();}
        });
    },

    reloadBasket: function()
    {
        iH.showProcessingInfo();
        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/index.php', {
            method: 'post',
            postBody: 'ajax=1&basket=1&state=2',
            onSuccess : function(resp)
             {
                $('shopping_cart_detail').innerHTML = resp.responseText;
                iH.hideProcessingInfo();
             },
            onFailure: function(resp) {iH.hideProcessingInfo();},
            onException: function(resp, exception) {iH.hideProcessingInfo();}
        });
    },

    reloadSmallBasket: function ()
    {
        var smallBasket = $('small_basket' );
        var boxname = 'smallbasket';

        if ( typeof smallBasket == 'undefined' ) {
            smallBasket = $('progress_info_box');
            boxname = 'progress';
           
            return;
        }
        if ( typeof smallBasket == 'undefined' ) {
            return;
        }

        smallBasket.innerHTML = '';

        new Ajax.Request ( 'http://secure.intersportrent.at/buchung/ajaxbox.php', {
            method: 'post',
            postBody: 'box=' + boxname + '&current=' + current_step2_item,
            onSuccess : function(resp){
            	smallBasket.innerHTML = resp.responseText;
            },
            onFailure: function(resp) {},
            onException: function(resp, exception) {}
        });
    },

    showSmallDetails: function ()
    {
        isrEffects.toggle('iic_yc_details','blind');
    }

}


var Checkout = {

   
    showBuyerDataForm: function()
    {
    	iH.showProcessingInfo();
    	var params = ""
        var url =  'http://secure.intersportrent.at/buchung/index.php';
        $('person_data_container').innerHTML = '';
        new Ajax.Request ( url, {
            method: 'post',
            postBody: 'ajax=1&state=6&' + params,
            onSuccess : Checkout.doSuccessLoadPersonForm,
            onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
            onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
        });
    },

   
    showSelectBoxes: function(){
        selects = document.getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
            selects[i].style.visibility = "visible";
        }
    },

   
    hideSelectBoxes: function(){
        selects = document.getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
            selects[i].style.visibility = "hidden";
        }
    },


    closeBuyerDataForm: function()
    {
        Checkout.hidePersonalDataFormSelectBoxes();
        $('person_data_overlay').style.display = 'none';
        $('person_data_box').style.display = 'none';
        Checkout.showSelectBoxes();
    },

   
    showPersonalDataFormSelectBoxes: function()
    {
        selects = $('person_data_box').getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
            selects[i].style.visibility = "visible";
        }
    },

    hidePersonalDataFormSelectBoxes: function()
    {
        selects = $('person_data_box').getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
            selects[i].style.visibility = "hidden";
        }
    },

    loadPersonDataForm: function() {
        var elementId = $('existingCustomer').options [ $('existingCustomer').selectedIndex ];
        if ( typeof elementId.value == 'undefined' )
            return;
        if ( elementId.value != 0 ) {
            var params = ""

            var url =  'http://secure.intersportrent.at/buchung/index.php';
            iH.showProcessingInfo();
            $('person_data_container').innerHTML = '';
            new Ajax.Request ( url, {
                method: 'post',
                postBody: 'ajax=1&loaduser=' + elementId.value,
                onSuccess : Checkout.doSuccessLoadPersonForm,
                onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
                onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
            });
        }
    },

    doSuccessLoadPersonForm: function( res ) {
        if ( res.responseText.length < 50 ) {
            var url = 'http://secure.intersportrent.at/buchung/index.php?state=6';
            window.document.location.href = url;
            Checkout.closeBuyerDataForm();
            return;
        }
        $('person_data_container').innerHTML = res.responseText;
        Checkout.hideSelectBoxes();

        offset = Position.realOffset($('person_data_box'));
        newOffset = offset[1]+50;
        $('person_data_box').style.top = newOffset+'px';
        $('person_data_overlay').style.display = 'block';
        $('person_data_box').style.display = 'block';
        var arrayPageSize = getPageSize();
        Element.setHeight('person_data_overlay', arrayPageSize[1]);
        iH.hideProcessingInfo();
        Element.setStyle('person_data_overlay', {display:'block'});
        Element.setStyle('person_data_container', {display:'block'});
        Checkout.showPersonalDataFormSelectBoxes();
        payerForm = true;
	new Ajax.Autocompleter('age_day','age_day_update','/buchung/autocompletedata.php?i=day',{paramName:'var',tokens:[',', ' ']});
	new Ajax.Autocompleter('age_month','age_month_update','/buchung/autocompletedata.php?i=month',{paramName:'var',tokens:[',', ' ']});
	new Ajax.Autocompleter('age_year','age_year_update','/buchung/autocompletedata.php?i=year',{paramName:'var',tokens:[',', ' ']});
    },

    submitBuyerData: function() {
        var params = 'ajax=1&state=6';
        if ( $('existingCustomer') && typeof $('existingCustomer') != undefined ) {
            var elementId = $('existingCustomer').options [ $('existingCustomer').selectedIndex ];
            if ( typeof elementId.value == 'undefined' )

            if ( elementId.value != 0 )
                params += '&loaduser=' + elementId.value;
        }
        var selectBoxen = $('personal_data_form').getElementsByTagName ( 'select' );
        for ( i = 0; i < selectBoxen.length; i++ )
            params += '&' + selectBoxen[i].name + '=' + $F( selectBoxen[i].id );
        var selectBoxen = $('personal_data_form').getElementsByTagName ( 'input' );
        for ( i = 0; i < selectBoxen.length; i++ )
            params += '&' + selectBoxen[i].name + '=' + selectBoxen[i].value;
        params += '&note=' + $('FurtherInformation').value;

        var url =  'http://secure.intersportrent.at/buchung/index.php';
        iH.showProcessingInfo();
       

        $('person_data_container').innerHTML = '';
        $('person_data_box').style.display = 'none';
        $('person_data_overlay').style.display = 'none';


        new Ajax.Request ( url, {
            method: 'post',
            postBody: params,
            onSuccess : Checkout.doSuccessLoadPersonForm,
            onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
            onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
        });
    },

    changeMarketingAllow: function( checkboxobject ){
		if(checkboxobject.value=='1'){
			checkboxobject.value=0;
		}else{
			checkboxobject.value=1;
		}    
    },

    loadExistingCustomer: function () {
        var elementId = $('existingCustomer').options [ $('existingCustomer').selectedIndex ];
        if ( typeof elementId.value == 'undefined' )
            return;
        if ( elementId.value != 0 ) {
            var url =  'http://secure.intersportrent.at/buchung/index.php';
            iH.showProcessingInfo();
            $('person_data_container').innerHTML = '';
            new Ajax.Request ( url, {
                method: 'post',
                postBody: 'ajax=1&state=6&loaduser=' + elementId.value,
                onSuccess : Checkout.doSuccessLoadPersonForm,
                onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
                onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
            });
        }
    },

    newCustomer: function()
    {
    		isrEffects.toggle('iic_pdp_enter_data','blind');
    }
}


var dealer_result_box = false;
var all_dealers_list = 0;
var actual_step = 1;

var shop_selected = false;
var selectedStore = -1;
var selectedSetOfStores = 0;

function toggleSelectStoreForm (myObj,selector)
{
    document.getElementById(current_store_form).style.display = "none";
    selector.className = "active";
    selectors = document.getElementById('iic_tb_navigation').getElementsByTagName('a');
    {
        if(selectors[i_selector] != selector)
        {
            selectors[i_selector].className = "";
        }
    }
    document.getElementById(myObj).style.display = "block";
    current_store_form = myObj;
    if (myObj == "iic_location_by_map")
        load();
}

                                        function infoBox(plat,plong)
                                        {
                                            return '';
                                        }
                                                                                function zoom (plat,plong,level)
                                        {
                                            if (!level) level = 13;
                                            map.setCenter(new GLatLng(plat,plong), level);
                                        }


function submit_location_search ()
{
   
    if (dealer_result_box == true)
    {
        document.getElementById('search_location_dealer_results').style.display = 'none';
    }

    $('search_location_dealer_results').innerHTML = '';
    var url =  'http://secure.intersportrent.at/buchung/index.php';
    $('iic_no_dealer_found').innerHTML = '';
    new Ajax.Request ( url, {
        method: 'post',
        postBody: 'ajax=1&use=city&id=' + ($('iic_select_by_city').value ),
        onSuccess : doSuccess,
        onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
        onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
    });
}

function submit_location_region_search() {
   
    if (dealer_result_box == true)
    {
        document.getElementById('search_location_dealer_results').style.display = 'none';
    }
    var url =  'http://secure.intersportrent.at/buchung/index.php';
    $('iic_no_dealer_found').innerHTML = '';
    var element = $('iic_select_by_region').options [ $('iic_select_by_region').selectedIndex ];

    new Ajax.Request ( url, {
        method: 'post',
        postBody: 'ajax=1&use=region&id=' + encodeURI(element.value),
        onSuccess : doSuccess,
        onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
        onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
    });

}

function doSuccess (res) {
    if ( res.responseText.length == 0 )
        return;

    $('search_location_dealer_results').innerHTML = res.responseText;

    if ( typeof $('totalSets') != 'undefined' ) {
        totalSets = parseInt ( $('totalSets').innerHTML );
    }
    else {
        return;
    }

    if ( totalSets == '0' ) {
        $('iic_no_dealer_found').innerHTML = res.responseText;
        isrEffects.toggle('iic_no_dealer_found', 'blind');
    }
    else {
        totalShops = parseInt ( $('totalShops').innerHTML );
        isrEffects.toggle('search_location_dealer_results','blind');
        dealer_result_box = true;
    }
}


function showSmallCartDetails() {
    isrEffects.toggle('iic_yc_details','blind');
}


function LZ(x) {
    return(x<0||x>9?"":"0")+x;
}

function checkDate(fmt,str,element)
{
    days = 0;
    var a = str.split(/\W+/);
    if (a.length == 3)
    {
        ms = Date.UTC(a[2],a[1]-1,a[0],0,0,0);
        ms += 1000*60*60*24*days;
        var f = new Date(ms);
        var d = LZ(f.getDate());
        var m = LZ(f.getMonth() + 1);
        var y = f.getFullYear();

        if(element == "first")
        {
            document.getElementById("from_day").value = d;
            document.getElementById("from_month").value = m;
            document.getElementById("from_year").value = y;
        }

        if(element == "last")
        {
            document.getElementById("until_day").value = d;
            document.getElementById("until_month").value = m;
            document.getElementById("until_year").value = y;
        }

    }
}


function gotoStepTwo ()
{
    var url =  'http://secure.intersportrent.at/buchung/index.php';
    $('iic_no_dealer_found').innerHTML = '';
    var element = $('iic_select_by_region').options [ $('iic_select_by_region').selectedIndex ];
    var shop_id = $('shop_id_' + selectedStore + '_' + selectedSetOfStores ).value;
    var params = 'ajax=1&use=dealer&check=timestamp&id=' + shop_id + '&from_day=' + $('from_day').value;
    params += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
    params += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
    params += '&until_year=' + $('until_year').value;

    new Ajax.Request ( url, {
        method: 'post',
        postBody: params,
        onSuccess : determineTimestamp,
        onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
        onException: function(resp, exception) { alert ( 'Ausnahme: ' + exception); }
    });

}

function determineTimestamp ( ref ) {

    if ( ref.responseText.length > 50 ) {
        var problems = ref.responseXML.getElementsByTagName ( "problem" );
        var error = '<u>Notify</u>: ' + problems [ 0 ].firstChild.nodeValue;
        $('timeSpanErrorError').innerHTML = error;
        isrEffects.Appear ( 'timeSpanError' );
        return;
    }
    var shop_id = $('shop_id_' + selectedStore + '_' + selectedSetOfStores ).value;

    var url='http://secure.intersportrent.at/buchung/?state=2&use=dealer&id=' + shop_id + '&from_day=' + $('from_day').value;
    url += '&from_month=' + $('from_month').value + '&from_year=' + $('from_year').value;
    url += '&until_day=' + $('until_day').value + '&until_month=' + $('until_month').value;
    url += '&until_year=' + $('until_year').value;

    window.document.location.href = url;
}

function setActualStep (id)
{
    actual_point = "step_" + id;
    if ( typeof actual_point == 'undefined' )
        return;
    classnames = "iic_" + id + "gr";
    document.getElementById(actual_point).className = classnames;
    id = id+1;
    actual_point = "step_" + id;
    classnames = "iic_" + id + "r";
    document.getElementById(actual_point).className = classnames;
    actual_step++;
}




var shown = false;
var hideit = false;

var docEl = (
             typeof document.compatMode != "undefined" &&
             document.compatMode        != "BackCompat"
            )? "documentElement" : "body";


function showToolTip(id) {
        if(document.layers) document.captureEvents(Event.MOUSEMOVE);
        if (id == "price"){
	        document.onmousemove =  dpl_mouse_pos_price;
        }else{
        document.onmousemove =  dpl_mouse_pos;
        }

        overlayer = document.getElementById("tool_tip");
        id = "tooltipp_" + id;
        overlayer.innerHTML = document.getElementById(id).innerHTML;
        showLayer();
}


function dpl_mouse_pos(e) {
    var xPos    =  e? e.pageX : window.event.clientX;
    var yPos    =  e? e.pageY : window.event.clientY;

    if (document.all && !document.captureEvents) {
        xPos    += document[docEl].scrollLeft;
        yPos    += document[docEl].scrollTop;
    }

    document.getElementById("tool_tip").style.left = xPos + "px";
    document.getElementById("tool_tip").style.top = yPos + "px";

    if (document.layers) routeEvent(e);
}

function dpl_mouse_pos_price(e) {
    var xPos    =  e? e.pageX : window.event.clientX;
    var yPos    =  e? e.pageY : window.event.clientY;


	xPos = xPos - 215;
	yPos = yPos + 2;

    if (document.all && !document.captureEvents) {
        xPos    += document[docEl].scrollLeft;
        yPos    += document[docEl].scrollTop;
    }

    document.getElementById("tool_tip").style.left = xPos + "px";
    document.getElementById("tool_tip").style.top = yPos + "px";

    if (document.layers) routeEvent(e);
}


function hideToolTip ()
{
    document.getElementById("tool_tip").style.zIndex = '100000';
    document.getElementById("tool_tip").style.display = 'none';
    shown = false;

}

function showLayer ()
{
    if (shown == false)
    {
        document.getElementById("tool_tip").style.display = 'block';
        shown = true;
    }
}





function setCategoryStatus (tab,category,active)
{
    checkboxes = document.getElementById(tab + '_category_' + category).getElementsByTagName("input");
    if(active.title == "active")
    {
        active.title = "";
    }

    else
    {
        active.title = "active";
    }

    for(i=0;i<checkboxes.length;i++)
    {
        if(active.title == "active")
        {
            if(checkboxes[i] != active)
            {
                checkboxes[i].disabled = true;
            }
        }

        else
        {
            if(checkboxes[i] != active)
            {
                checkboxes[i].disabled = false;
            }
        }
    }

}

function gotoStepThree()
{
    setActualStep(actual_step);
    document.getElementById('shopping_cart_detail').style.display = 'none';
    isrEffects.toggle('payment_form','blind');
}

function getElementsByClassName(oElm, strTagName, strClassName){
    var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    strClassName = strClassName.replace(/\-/g, "\\-");
    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    var oElement;
    for(var i=0; i<arrElements.length; i++){
        oElement = arrElements[i];
        if(oRegExp.test(oElement.className)){
            arrReturnElements.push(oElement);
        }
    }
    return (arrReturnElements);
}



function handleLiveError(message,uri,nr) {
	return true;
}

function handleDevError(message,uri,nr) {
	try {
		var errortext = "ISR - E: " + message + " | Nr: " + nr + " | Uri: " + uri;
		window.status = errortext;
		console.log (errortext);
	}
	catch (e) {
	}
	return true;
}

if (false) {
	window.onerror = handleDevError;
}
else {
	window.onerror = handleLiveError;
}




var Profile = {

    showProfileError:function ( fieldId, msg ) {
        iH.hideProcessingInfo();
        if ( fieldId.length > 0 )
            $(fieldId).style.backgroundColor = '#e60000';
        $('ccc_profile_error').style.display = 'block';
        $('ccc_profile_error').innerHTML = '<u>Notify</u>: ' + msg;
    },

    hideError:function ( fieldId ) {
        if ( fieldId.length > 0 )
            $(fieldId).style.backgroundColor = '#FFFFFF';
        $('ccc_profile_error').innerHTML = '';
        $('ccc_profile_error').style.display = 'none';
    },

    reloadProfileBox:function () {
        var url =  'http://secure.intersportrent.at/buchung/ajaxbox.php';
        var box = 'profile';
        if ( ! Profile.isCCCLogin() )
            box = 'affiliate';
        new Ajax.Request ( url, {
            method: 'post',
            postBody: 'session=9ddcab4b6149cb37159595e4af6bcbd2&box=' + box + '&reload=1',
            onSuccess : Profile.doAjaxBoxReload,
            onFailure: function(resp) { Profile.showProfileError('', resp.statusText); iH.hideProcessingInfo(); },
            onException: function(resp, exception) {iH.hideProcessingInfo(); }
        });
    },

    reloaddblreservationboxBox: function() {
        try {
            var url =  'http://secure.intersportrent.at/buchung/ajaxbox.php';
            var box = 'dblreservation';
            new Ajax.Request ( url, {
                method: 'post',
                postBody: 'session=9ddcab4b6149cb37159595e4af6bcbd2&box=' + box + '&reload=1',
                onSuccess : function (res) {
                    $('dblreservationbox').innerHTML = res.responseText;
                    iH.hideProcessingInfo();
                },
                onFailure: function(resp) { Profile.showProfileError('', resp.statusText); iH.hideProcessingInfo(); },
                onException: function(resp, exception) {iH.hideProcessingInfo(); }
            });

        } catch (exception) {}
    },

    isCCCLogin: function() {
        if ( ! $('ccc_login_box') || typeof $('ccc_login_box') == 'undefined' )
            return false;
        return true;
    },

    doAjaxBoxReload:function(res) {
        if ( ! Profile.isCCCLogin() ) {
            $('affiliate_login_box').innerHTML = res.responseText;
        } else {
            $('ccc_login_box').innerHTML = res.responseText;
        }
        iH.hideProcessingInfo();
    },

    sendLogin:function() {
        $('ccc_profile_error').innerHTML = '';
        $('ccc_profile_note').innerHTML = '';
        var email = $('login').value;
        if ( email.length <= 0 ) {
            Profile.showProfileError ( 'login', 'Please enter your email address.' );
            return;
        }
        var pwd = $('pwd').value;
        if ( pwd.length <= 0 ) {
            Profile.showProfileError ( 'pwd', 'No password provided' );
            return;
        }
        iH.showProcessingInfo();

        $('ccc_profile_error').style.display = 'none';
        $('ccc_profile_note').style.display = 'none';
        Profile.ajaxSendLogin ( email, pwd );
    },

    sendLogout:function() {
        $('ccc_profile_error').innerHTML = '';
        $('ccc_profile_note').innerHTML = '';
        $('ccc_profile_error').style.display = 'none';
        $('ccc_profile_note').style.display = 'none';
        Profile.ajaxSendLogout ();
    },

    sendPassword:function() {
        $('ccc_profile_error').innerHTML = '';
        $('ccc_profile_note').innerHTML = '';
        var email = $('login').value;
        if ( email.length <= 0 ) {
            Profile.showProfileError ( 'login', 'Please enter your email address.' );
            return;
        }
        $('ccc_profile_error').style.display = 'none';
        $('ccc_profile_note').style.display = 'none';
        Profile.ajaxSendPassword ( email );
    },

    ajaxSendPassword:function ( email ) {
        Profile.hideError('login');
        Profile.hideError('pwd');
        var url =  'http://secure.intersportrent.at/buchung/ajax.php';
        new Ajax.Request ( url, {
            method: 'post',
            postBody: 'module=cccprofile&action=sendpwd&email=' + email,
            onSuccess : Profile.doAjaxSendPassword,
            onFailure: function(resp) { Profile.showProfileError('', resp.statusText); },
            onException: function(resp, exception) {}
        });
    },

    doAjaxSendPassword:function ( res ) {
        var errors = res.responseXML.getElementsByTagName ( "error" );
        if ( errors.length > 0 ) {
            Profile.showProfileError ( 'login', errors [ 0 ].firstChild.nodeValue );
            return;
        }
        var result = res.responseXML.getElementsByTagName ( "result" );
        if ( result.length > 0 ) {
            $('ccc_profile_note').innerHTML = '<u>Notify</u>: ' + result [ 0 ].firstChild.nodeValue;
            $('ccc_profile_note').style.display = 'block';
        }
    },

    ajaxSendLogin:function ( email, pwd ) {
        Profile.hideError('login');
        Profile.hideError('pwd');
        var url =  'http://secure.intersportrent.at/buchung/ajax.php';
        new Ajax.Request ( url, {
            method: 'post',
            postBody: 'module=cccprofile&action=login&email=' + email + '&pwd=' + pwd,
            onSuccess : Profile.doAjaxSendLogin,
            onFailure: function(resp) { Profile.showProfileError('', resp.statusText); iH.hideProcessingInfo(); },
            onException: function(resp, exception) { iH.hideProcessingInfo(); }
        });
    },

    doAjaxSendLogin:function ( res ) {
        var errors = res.responseXML.getElementsByTagName ( "error" );
        if ( errors.length > 0 ) {
            Profile.showProfileError ( 'login', errors [ 0 ].firstChild.nodeValue );
            return;
        }
        var result = res.responseXML.getElementsByTagName ( "result" );
        if ( result.length > 0 ) {
            isrEffects.toggle ( 'iic_profile_login', 'blind' );
            isrEffects.toggle ( 'iic_profile_logged_in', 'blind' );
            Profile.reloadProfileBox();
            Profile.reloaddblreservationboxBox();
            try {
                Basket.reloadBasket();
                Basket.reloadSmallBasket();
                Profile.reloadProfileBox();
            } catch (exception) {}
            iH.hideProcessingInfo();
        }
    },

    ajaxSendLogout:function() {
        Profile.hideError('login');
        Profile.hideError('pwd');
        var url =  'http://secure.intersportrent.at/buchung/ajax.php';
        new Ajax.Request ( url, {
            method: 'post',
            postBody: 'module=cccprofile&action=logout',
            onSuccess : Profile.doAjaxSendLogout,
            onFailure: function(resp) { Profile.showProfileError('', resp.statusText); },
            onException: function(resp, exception) { alert ( exception ); }
        });
    },

    doAjaxSendLogout:function ( res ) {
        var errors = res.responseXML.getElementsByTagName ( "error" );
        if ( errors.length > 0 ) {
            var errorText = errors [ 0 ].childNodes[0].nodeValue;
            if ( errorText == 'value_profile_no_login' && Element.visible ( 'iic_profile_logged_in' ) ) {
                isrEffects.toggle ( 'iic_profile_login', 'blind' );
                isrEffects.toggle ( 'iic_profile_logged_in', 'blind' );
                try { $('dblreservationbox').innerHTML = ''; } catch (exception) {}

                try {
                    Basket.reloadBasket();
                    Basket.reloadSmallBasket();
                    Profile.reloadProfileBox();
                } catch (exception) {}
            }
            return;
        }

        var result = res.responseXML.getElementsByTagName ( "result" );
        if ( result.length > 0 ) {
            isrEffects.toggle ( 'iic_profile_login', 'blind' );
            isrEffects.toggle ( 'iic_profile_logged_in', 'blind' );
            try { $('dblreservationbox').innerHTML = ''; } catch (exception) {}
            try {
                Basket.reloadBasket();
                Basket.reloadSmallBasket();
                Profile.reloadProfileBox();
            } catch (exception) {}
        }
    },

    gotoCCC: function() {
        window.document.location.href = 'http://secure.intersportrent.at/buchung/../ccc/?season=w&lang=en';
    },

    gotoBlankCCC: function() {
        window.open('http://secure.intersportrent.at/buchung/../ccc/?season=w&lang=en' );
    },

    gotoCCCSommer: function() {
        window.document.location.href = 'http://secure.intersportrent.at/buchung/../ccc/?season=s&lang=en';
    },

    gotoBlankCCCSommer: function() {
        window.open('http://secure.intersportrent.at/buchung/../ccc/?season=s&lang=en' );
    }

}
var CustomerRegistration = {

	showBuyerDataForm: function() {
	
		iH.showProcessingInfo();
		var params = ""
		var url =  'http://secure.intersportrent.at/buchung/index.php';
		$('person_data_container').innerHTML = '';
		new Ajax.Request ( url, {
			method: 'post',
			postBody: 'ajax=1&state=0&showbuyerform=1&loaded=1&' + params,
			onSuccess : CustomerRegistration.doSuccessLoadPersonForm,
			onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
			onException: function(resp, exception) { alert ( 'Ausnahme [14] : ' + exception);}
		});
	},
	doSuccessLoadPersonForm: function( res ) {

		if ( res.responseText.length < 50 ) {
			CustomerRegistration.closeBuyerDataForm();
			return;
		}
		$('person_data_container').innerHTML = res.responseText;
		CustomerRegistration.hideSelectBoxes();

		offset = Position.realOffset($('person_data_box'));
		newOffset = offset[1]+50;
		$('person_data_box').style.top = newOffset+'px';
		$('person_data_overlay').style.display = 'block';
		$('person_data_box').style.display = 'block';
		var arrayPageSize = getPageSize();
		Element.setHeight('person_data_overlay', arrayPageSize[1]);
		iH.hideProcessingInfo();
		Element.setStyle('person_data_overlay', {display:'block'});
		Element.setStyle('person_data_container', {display:'block'});
		CustomerRegistration.showPersonalDataFormSelectBoxes();
		payerForm = true;
		CustomerRegistration.newCustomer();
		try {
			new Ajax.Autocompleter('age_day','age_day_update','/buchung/autocompletedata.php?i=day',{paramName:'var',tokens:[',', ' ']});
			new Ajax.Autocompleter('age_month','age_month_update','/buchung/autocompletedata.php?i=month',{paramName:'var',tokens:[',', ' ']});
			new Ajax.Autocompleter('age_year','age_year_update','/buchung/autocompletedata.php?i=year',{paramName:'var',tokens:[',', ' ']});
		}
		catch (e) {}
	},
	submitBuyerData: function() {

		var params = 'ajax=1&state=0&showbuyerform=1';

		var selectBoxen = $('personal_data_form').getElementsByTagName ( 'select' );
		for ( i = 0; i < selectBoxen.length; i++ ) {
			params += '&' + selectBoxen[i].name + '=' + $F( selectBoxen[i].id );
		}
		var selectBoxen = $('personal_data_form').getElementsByTagName ( 'input' );
		for ( i = 0; i < selectBoxen.length; i++ ) {
			params += '&' + selectBoxen[i].name + '=' + selectBoxen[i].value;
		}

		var url =  'http://secure.intersportrent.at/buchung/index.php';
		iH.showProcessingInfo();

	
	
		$('person_data_box').style.display = 'none';
		$('person_data_overlay').style.display = 'none';

		
	
	
	
		new Ajax.Request ( url, {
			method: 'post',
			postBody: params,
			onSuccess : CustomerRegistration.doSuccessLoadPersonForm,
		
			onFailure: function(resp) { alert ( 'Fehler: ' + resp.statusText); },
			onException: function(resp, exception) { alert ( 'Ausnahme [82] : ' + exception);  }
		});
	},

	closeBuyerDataForm: function(){
	

		var email = $('personal_data_form').getElementsByTagName('input')['email'].value;
		var pwd   = $('personal_data_form').getElementsByTagName('input')['password'].value;

		if (email != '' && pwd != ''){
			Profile.ajaxSendLogin(email,pwd);
		}
		$('person_data_container').innerHTML = '';

		CustomerRegistration.hidePersonalDataFormSelectBoxes();
		$('person_data_overlay').style.display = 'none';
		$('person_data_box').style.display = 'none';
		CustomerRegistration.showSelectBoxes();

		iH.hideProcessingInfo();
	},


	showPersonalDataFormSelectBoxes: function()
	{
		selects = $('person_data_box').getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			selects[i].style.visibility = "visible";
		}
	},

	hidePersonalDataFormSelectBoxes: function()
	{
		selects = $('person_data_box').getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			selects[i].style.visibility = "hidden";
		}
	},


	showSelectBoxes: function(){
		selects = document.getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			selects[i].style.visibility = "visible";
		}
	},


	hideSelectBoxes: function(){
		selects = document.getElementsByTagName("select");
		for (i = 0; i != selects.length; i++) {
			selects[i].style.visibility = "hidden";
		}
	},
	newCustomer: function(){
	
		isrEffects.Appear('iic_pdp_enter_data','blind');
	}

}

var TrimPath;


(function() {              
    if (TrimPath == null)
        TrimPath = new Object();
    if (TrimPath.evalEx == null)
        TrimPath.evalEx = function(src) { return eval(src); };

    var UNDEFINED;
    if (Array.prototype.pop == null) 
        Array.prototype.pop = function() {
            if (this.length === 0) {return UNDEFINED;}
            return this[--this.length];
        };
    if (Array.prototype.push == null)
        Array.prototype.push = function() {
            for (var i = 0; i < arguments.length; ++i) {this[this.length] = arguments[i];}
            return this.length;
        };

    TrimPath.parseTemplate = function(tmplContent, optTmplName, optEtc) {
        if (optEtc == null)
            optEtc = TrimPath.parseTemplate_etc;
        var funcSrc = parse(tmplContent, optTmplName, optEtc);
        var func = TrimPath.evalEx(funcSrc, optTmplName, 1);
        if (func != null)
            return new optEtc.Template(optTmplName, tmplContent, funcSrc, func, optEtc);
        return null;
    }
    
    try {
        String.prototype.process = function(context, optFlags) {
            var template = TrimPath.parseTemplate(this, null);
            if (template != null)
                return template.process(context, optFlags);
            return this;
        }
    } catch (e) {
    }
    
    TrimPath.parseTemplate_etc = {};           
    TrimPath.parseTemplate_etc.statementTag = "forelse|for|if|elseif|else|var|macro";
    TrimPath.parseTemplate_etc.statementDef = {
        "if"     : { delta:  1, prefix: "if (", suffix: ") {", paramMin: 1 },
        "else"   : { delta:  0, prefix: "} else {" },
        "elseif" : { delta:  0, prefix: "} else if (", suffix: ") {", paramDefault: "true" },
        "/if"    : { delta: -1, prefix: "}" },
        "for"    : { delta:  1, paramMin: 3, 
                     prefixFunc : function(stmtParts, state, tmplName, etc) {
                        if (stmtParts[2] != "in")
                            throw new etc.ParseError(tmplName, state.line, "bad for loop statement: " + stmtParts.join(' '));
                        var iterVar = stmtParts[1];
                        var listVar = "__LIST__" + iterVar;
                        return [ "var ", listVar, " = ", stmtParts[3], ";",
                            
                             "var __LENGTH_STACK__;",
                             "if (typeof(__LENGTH_STACK__) == 'undefined' || !__LENGTH_STACK__.length) __LENGTH_STACK__ = new Array();", 
                             "__LENGTH_STACK__[__LENGTH_STACK__.length] = 0;",
                             "if ((", listVar, ") != null) { ",
                             "var ", iterVar, "_ct = 0;",      
                             "for (var ", iterVar, "_index in ", listVar, ") { ",
                             iterVar, "_ct++;",
                             "if (typeof(", listVar, "[", iterVar, "_index]) == 'function') {continue;}",
                             "__LENGTH_STACK__[__LENGTH_STACK__.length - 1]++;",
                             "var ", iterVar, " = ", listVar, "[", iterVar, "_index];" ].join("");
                     } },
        "forelse" : { delta:  0, prefix: "} } if (__LENGTH_STACK__[__LENGTH_STACK__.length - 1] == 0) { if (", suffix: ") {", paramDefault: "true" },
        "/for"    : { delta: -1, prefix: "} }; delete __LENGTH_STACK__[__LENGTH_STACK__.length - 1];" },
        "var"     : { delta:  0, prefix: "var ", suffix: ";" },
        "macro"   : { delta:  1, 
                      prefixFunc : function(stmtParts, state, tmplName, etc) {
                          var macroName = stmtParts[1].split('(')[0];
                          return [ "var ", macroName, " = function", 
                                   stmtParts.slice(1).join(' ').substring(macroName.length),
                                   "{ var _OUT_arr = []; var _OUT = { write: function(m) { if (m) _OUT_arr.push(m); } }; " ].join('');
                     } }, 
        "/macro"  : { delta: -1, prefix: " return _OUT_arr.join(''); };" }
    }
    TrimPath.parseTemplate_etc.modifierDef = {
        "eat"        : function(v)    { return ""; },
        "escape"     : function(s)    { return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); },
        "capitalize" : function(s)    { return String(s).toUpperCase(); },
        "default"    : function(s, d) { return s != null ? s : d; }
    }
    TrimPath.parseTemplate_etc.modifierDef.h = TrimPath.parseTemplate_etc.modifierDef.escape;

    TrimPath.parseTemplate_etc.Template = function(tmplName, tmplContent, funcSrc, func, etc) {
        this.process = function(context, flags) {
            if (context == null)
                context = {};
            if (context._MODIFIERS == null)
                context._MODIFIERS = {};
            if (context.defined == null)
                context.defined = function(str) { return (context[str] != undefined); };
            for (var k in etc.modifierDef) {
                if (context._MODIFIERS[k] == null)
                    context._MODIFIERS[k] = etc.modifierDef[k];
            }
            if (flags == null)
                flags = {};
            var resultArr = [];
            var resultOut = { write: function(m) { resultArr.push(m); } };
            try {
                func(resultOut, context, flags);
            } catch (e) {
                if (flags.throwExceptions == true)
                    throw e;
                var result = new String(resultArr.join("") + "[ERROR: " + e.toString() + (e.message ? '; ' + e.message : '') + "]");
                result["exception"] = e;
                return result;
            }
            return resultArr.join("");
        }
        this.name       = tmplName;
        this.source     = tmplContent; 
        this.sourceFunc = funcSrc;
        this.toString   = function() { return "TrimPath.Template [" + tmplName + "]"; }
    }
    TrimPath.parseTemplate_etc.ParseError = function(name, line, message) {
        this.name    = name;
        this.line    = line;
        this.message = message;
    }
    TrimPath.parseTemplate_etc.ParseError.prototype.toString = function() { 
        return ("TrimPath template ParseError in " + this.name + ": line " + this.line + ", " + this.message);
    }
    
    var parse = function(body, tmplName, etc) {
        body = cleanWhiteSpace(body);
        var funcText = [ "var TrimPath_Template_TEMP = function(_OUT, _CONTEXT, _FLAGS) { with (_CONTEXT) {" ];
        var state    = { stack: [], line: 1 };                             
        var endStmtPrev = -1;
        while (endStmtPrev + 1 < body.length) {
            var begStmt = endStmtPrev;
           
            begStmt = body.indexOf("{", begStmt + 1);
            while (begStmt >= 0) {
                var endStmt = body.indexOf('}', begStmt + 1);
                var stmt = body.substring(begStmt, endStmt);
                var blockrx = stmt.match(/^\{(cdata|minify|eval)/);
                if (blockrx) {
                    var blockType = blockrx[1]; 
                    var blockMarkerBeg = begStmt + blockType.length + 1;
                    var blockMarkerEnd = body.indexOf('}', blockMarkerBeg);
                    if (blockMarkerEnd >= 0) {
                        var blockMarker;
                        if( blockMarkerEnd - blockMarkerBeg <= 0 ) {
                            blockMarker = "{/" + blockType + "}";
                        } else {
                            blockMarker = body.substring(blockMarkerBeg + 1, blockMarkerEnd);
                        }                        
                        
                        var blockEnd = body.indexOf(blockMarker, blockMarkerEnd + 1);
                        if (blockEnd >= 0) {                            
                            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
                            
                            var blockText = body.substring(blockMarkerEnd + 1, blockEnd);
                            if (blockType == 'cdata') {
                                emitText(blockText, funcText);
                            } else if (blockType == 'minify') {
                                emitText(scrubWhiteSpace(blockText), funcText);
                            } else if (blockType == 'eval') {
                                if (blockText != null && blockText.length > 0)
                                    funcText.push('_OUT.write( (function() { ' + blockText + ' })() );');
                            }
                            begStmt = endStmtPrev = blockEnd + blockMarker.length - 1;
                        }
                    }                        
                } else if (body.charAt(begStmt - 1) != '$' &&              
                           body.charAt(begStmt - 1) != '\\') {             
                    var offset = (body.charAt(begStmt + 1) == '/' ? 2 : 1);
                                                                           
                    if (body.substring(begStmt + offset, begStmt + 10 + offset).search(TrimPath.parseTemplate_etc.statementTag) == 0) 
                        break;                                             
                }
                begStmt = body.indexOf("{", begStmt + 1);
            }
            if (begStmt < 0)                             
                break;
            var endStmt = body.indexOf("}", begStmt + 1);
            if (endStmt < 0)
                break;
            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
            emitStatement(body.substring(begStmt, endStmt + 1), state, funcText, tmplName, etc);
            endStmtPrev = endStmt;
        }
        emitSectionText(body.substring(endStmtPrev + 1), funcText);
        if (state.stack.length != 0)
            throw new etc.ParseError(tmplName, state.line, "unclosed, unmatched statement(s): " + state.stack.join(","));
        funcText.push("}}; TrimPath_Template_TEMP");
        return funcText.join("");
    }
    
    var emitStatement = function(stmtStr, state, funcText, tmplName, etc) {
        var parts = stmtStr.slice(1, -1).split(' ');
        var stmt = etc.statementDef[parts[0]];
        if (stmt == null) {                   
            emitSectionText(stmtStr, funcText);
            return;
        }
        if (stmt.delta < 0) {
            if (state.stack.length <= 0)
                throw new etc.ParseError(tmplName, state.line, "close tag does not match any previous statement: " + stmtStr);
            state.stack.pop();
        } 
        if (stmt.delta > 0)
            state.stack.push(stmtStr);

        if (stmt.paramMin != null &&
            stmt.paramMin >= parts.length)
            throw new etc.ParseError(tmplName, state.line, "statement needs more parameters: " + stmtStr);
        if (stmt.prefixFunc != null)
            funcText.push(stmt.prefixFunc(parts, state, tmplName, etc));
        else 
            funcText.push(stmt.prefix);
        if (stmt.suffix != null) {
            if (parts.length <= 1) {
                if (stmt.paramDefault != null)
                    funcText.push(stmt.paramDefault);
            } else {
                for (var i = 1; i < parts.length; i++) {
                    if (i > 1)
                        funcText.push(' ');
                    funcText.push(parts[i]);
                }
            }
            funcText.push(stmt.suffix);
        }
    }

    var emitSectionText = function(text, funcText) {
        if (text.length <= 0)
            return;
        var nlPrefix = 0;              
        var nlSuffix = text.length - 1;
        while (nlPrefix < text.length && (text.charAt(nlPrefix) == '\n'))
            nlPrefix++;
        while (nlSuffix >= 0 && (text.charAt(nlSuffix) == ' ' || text.charAt(nlSuffix) == '\t'))
            nlSuffix--;
        if (nlSuffix < nlPrefix)
            nlSuffix = nlPrefix;
        if (nlPrefix > 0) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(0, nlPrefix).replace('\n', '\\n');
            if (s.charAt(s.length - 1) == '\n')
            	s = s.substring(0, s.length - 1);
            funcText.push(s);
            funcText.push('");');
        }
        var lines = text.substring(nlPrefix, nlSuffix + 1).split('\n');
        for (var i = 0; i < lines.length; i++) {
            emitSectionTextLine(lines[i], funcText);
            if (i < lines.length - 1)
                funcText.push('_OUT.write("\\n");\n');
        }
        if (nlSuffix + 1 < text.length) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(nlSuffix + 1).replace('\n', '\\n');
            if (s.charAt(s.length - 1) == '\n')
            	s = s.substring(0, s.length - 1);
            funcText.push(s);
            funcText.push('");');
        }
    }
    
    var emitSectionTextLine = function(line, funcText) {
        var endMarkPrev = '}';
        var endExprPrev = -1;
        while (endExprPrev + endMarkPrev.length < line.length) {
            var begMark = "${", endMark = "}";
            var begExpr = line.indexOf(begMark, endExprPrev + endMarkPrev.length);
            if (begExpr < 0)
                break;
            if (line.charAt(begExpr + 2) == '%') {
                begMark = "${%";
                endMark = "%}";
            }
            var endExpr = line.indexOf(endMark, begExpr + begMark.length);        
            if (endExpr < 0)
                break;
            emitText(line.substring(endExprPrev + endMarkPrev.length, begExpr), funcText);                
           
            var exprArr = line.substring(begExpr + begMark.length, endExpr).replace(/\|\|/g, "#@@#").split('|');
            for (var k in exprArr) {
                if (exprArr[k].replace)
                    exprArr[k] = exprArr[k].replace(/#@@#/g, '||');
            }
            funcText.push('_OUT.write(');
            emitExpression(exprArr, exprArr.length - 1, funcText); 
            funcText.push(');');
            endExprPrev = endExpr;
            endMarkPrev = endMark;
        }
        emitText(line.substring(endExprPrev + endMarkPrev.length), funcText); 
    }
    
    var emitText = function(text, funcText) {
        if (text == null ||
            text.length <= 0)
            return;
        text = text.replace(/\\/g, '\\\\');
        text = text.replace(/\n/g, '\\n');
        text = text.replace(/"/g,  '\\"');
        funcText.push('_OUT.write("');
        funcText.push(text);
        funcText.push('");');
    }
    
    var emitExpression = function(exprArr, index, funcText) {
       
        var expr = exprArr[index];
        if (index <= 0) {         
            funcText.push(expr);
            return;
        }
        var parts = expr.split(':');
        funcText.push('_MODIFIERS["');
        funcText.push(parts[0]);
        funcText.push('"](');
        emitExpression(exprArr, index - 1, funcText);
        if (parts.length > 1) {
            funcText.push(',');
            funcText.push(parts[1]);
        }
        funcText.push(')');
    }

    var cleanWhiteSpace = function(result) {
        result = result.replace(/\t/g,   "    ");
        result = result.replace(/\r\n/g, "\n");
        result = result.replace(/\r/g,   "\n");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1');
        return result;
    }

    var scrubWhiteSpace = function(result) {
        result = result.replace(/^\s+/g,   "");
        result = result.replace(/\s+$/g,   "");
        result = result.replace(/\s+/g,   " ");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1');
        return result;
    }

   
   
   
    TrimPath.parseDOMTemplate = function(elementId, optDocument, optEtc) {
        if (optDocument == null)
            optDocument = document;
        var element = optDocument.getElementById(elementId);
        var content = element.value;    
        if (content == null)
            content = element.innerHTML;
        content = content.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
        return TrimPath.parseTemplate(content, elementId, optEtc);
    }

    TrimPath.processDOMTemplate = function(elementId, context, optFlags, optDocument, optEtc) {
        return TrimPath.parseDOMTemplate(elementId, optDocument, optEtc).process(context, optFlags);
    }
}) ();
