

var cascadeWinTop = 0;
var cascadeWinLeft = 0;



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

var Prototype = {
  Version: '1.6.1',

  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
    }
  })(),

  BrowserFeatures: {
    XPath: !!document.evaluate,
    SelectorsAPI: !!document.querySelector,
    ElementExtensions: (function() {
      var constructor = window.Element || window.HTMLElement;
      return !!(constructor && constructor.prototype);
    })(),
    SpecificElementExtensions: (function() {
      if (typeof window.HTMLDivElement !== 'undefined')
        return true;

      var div = document.createElement('div');
      var form = document.createElement('form');
      var isSupported = false;

      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
        isSupported = true;
      }

      div = form = null;

      return isSupported;
    })()
  },

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

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

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


var Abstract = { };


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

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

    return returnValue;
  }
};

/* Based on Alex Arnell's inheritance implementation. */

var Class = (function() {
  function subclass() {};
  function create() {
    var parent = null, properties = $A(arguments);
    if (Object.isFunction(properties[0]))
      parent = properties.shift();

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

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

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

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

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

    klass.prototype.constructor = klass;
    return klass;
  }

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

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

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

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

    return this;
  }

  return {
    create: create,
    Methods: {
      addMethods: addMethods
    }
  };
})();
(function() {

  var _toString = Object.prototype.toString;

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

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

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

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

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

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

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

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

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

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

  function clone(object) {
    return extend({ }, object);
  }

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

  function isArray(object) {
    return _toString.call(object) == "[object Array]";
  }


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

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

  function isString(object) {
    return _toString.call(object) == "[object String]";
  }

  function isNumber(object) {
    return _toString.call(object) == "[object Number]";
  }

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

  extend(Object, {
    extend:        extend,
    inspect:       inspect,
    toJSON:        toJSON,
    toQueryString: toQueryString,
    toHTML:        toHTML,
    keys:          keys,
    values:        values,
    clone:         clone,
    isElement:     isElement,
    isArray:       isArray,
    isHash:        isHash,
    isFunction:    isFunction,
    isString:      isString,
    isNumber:      isNumber,
    isUndefined:   isUndefined
  });
})();
Object.extend(Function.prototype, (function() {
  var slice = Array.prototype.slice;

  function update(array, args) {
    var arrayLength = array.length, length = args.length;
    while (length--) array[arrayLength + length] = args[length];
    return array;
  }

  function merge(array, args) {
    array = slice.call(array, 0);
    return update(array, args);
  }

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

  function bind(context) {
    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
    var __method = this, args = slice.call(arguments, 1);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(context, a);
    }
  }

  function bindAsEventListener(context) {
    var __method = this, args = slice.call(arguments, 1);
    return function(event) {
      var a = update([event || window.event], args);
      return __method.apply(context, a);
    }
  }

  function curry() {
    if (!arguments.length) return this;
    var __method = this, args = slice.call(arguments, 0);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(this, a);
    }
  }

  function delay(timeout) {
    var __method = this, args = slice.call(arguments, 1);
    timeout = timeout * 1000
    return window.setTimeout(function() {
      return __method.apply(__method, args);
    }, timeout);
  }

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

  function wrap(wrapper) {
    var __method = this;
    return function() {
      var a = update([__method.bind(this)], arguments);
      return wrapper.apply(this, a);
    }
  }

  function methodize() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      var a = update([this], arguments);
      return __method.apply(null, a);
    };
  }

  return {
    argumentNames:       argumentNames,
    bind:                bind,
    bindAsEventListener: bindAsEventListener,
    curry:               curry,
    delay:               delay,
    defer:               defer,
    wrap:                wrap,
    methodize:           methodize
  }
})());


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


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

RegExp.escape = function(str) {
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

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

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

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

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

Object.extend(String.prototype, (function() {

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

  function gsub(pattern, replacement) {
    var result = '', source = this, match;
    replacement = prepareReplacement(replacement);

    if (Object.isString(pattern))
      pattern = RegExp.escape(pattern);

    if (!(pattern.length || pattern.source)) {
      replacement = replacement('');
      return replacement + source.split('').join(replacement) + replacement;
    }

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

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

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

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

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

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

  function stripTags() {
    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
  }

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

  function extractScripts() {
    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];
    });
  }

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

  function escapeHTML() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  }

  function unescapeHTML() {
    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
  }


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

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

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

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

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

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

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

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

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

    return camelized;
  }

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

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

  function dasherize() {
    return this.replace(/_/g, '-');
  }

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

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

  function unfilterJSON(filter) {
    return this.replace(filter || Prototype.JSONFilter, '$1');
  }

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

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

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

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

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

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

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

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

  return {
    gsub:           gsub,
    sub:            sub,
    scan:           scan,
    truncate:       truncate,
    strip:          String.prototype.trim ? String.prototype.trim : strip,
    stripTags:      stripTags,
    stripScripts:   stripScripts,
    extractScripts: extractScripts,
    evalScripts:    evalScripts,
    escapeHTML:     escapeHTML,
    unescapeHTML:   unescapeHTML,
    toQueryParams:  toQueryParams,
    parseQuery:     toQueryParams,
    toArray:        toArray,
    succ:           succ,
    times:          times,
    camelize:       camelize,
    capitalize:     capitalize,
    underscore:     underscore,
    dasherize:      dasherize,
    inspect:        inspect,
    toJSON:         toJSON,
    unfilterJSON:   unfilterJSON,
    isJSON:         isJSON,
    evalJSON:       evalJSON,
    include:        include,
    startsWith:     startsWith,
    endsWith:       endsWith,
    empty:          empty,
    blank:          blank,
    interpolate:    interpolate
  };
})());

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

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

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

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

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

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

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

var $break = { };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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









  return {
    each:       each,
    eachSlice:  eachSlice,
    all:        all,
    every:      all,
    any:        any,
    some:       any,
    collect:    collect,
    map:        collect,
    detect:     detect,
    findAll:    findAll,
    select:     findAll,
    filter:     findAll,
    grep:       grep,
    include:    include,
    member:     include,
    inGroupsOf: inGroupsOf,
    inject:     inject,
    invoke:     invoke,
    max:        max,
    min:        min,
    partition:  partition,
    pluck:      pluck,
    reject:     reject,
    sortBy:     sortBy,
    toArray:    toArray,
    entries:    toArray,
    zip:        zip,
    size:       size,
    inspect:    inspect,
    find:       detect
  };
})();
function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

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

Array.from = $A;


(function() {
  var arrayProto = Array.prototype,
      slice = arrayProto.slice,
      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

  function each(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  }
  if (!_each) _each = each;

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

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

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

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

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

  function without() {
    var values = slice.call(arguments, 0);
    return this.select(function(value) {
      return !values.include(value);
    });
  }

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

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

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


  function clone() {
    return slice.call(this, 0);
  }

  function size() {
    return this.length;
  }

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

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

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

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

  function concat() {
    var array = slice.call(this, 0), item;
    for (var i = 0, length = arguments.length; i < length; i++) {
      item = arguments[i];
      if (Object.isArray(item) && !('callee' in item)) {
        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
          array.push(item[j]);
      } else {
        array.push(item);
      }
    }
    return array;
  }

  Object.extend(arrayProto, Enumerable);

  if (!arrayProto._reverse)
    arrayProto._reverse = arrayProto.reverse;

  Object.extend(arrayProto, {
    _each:     _each,
    clear:     clear,
    first:     first,
    last:      last,
    compact:   compact,
    flatten:   flatten,
    without:   without,
    reverse:   reverse,
    uniq:      uniq,
    intersect: intersect,
    clone:     clone,
    toArray:   clone,
    size:      size,
    inspect:   inspect,
    toJSON:    toJSON
  });

  var CONCAT_ARGUMENTS_BUGGY = (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2)

  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object) {
  return new Hash(object);
};

var Hash = Class.create(Enumerable, (function() {
  function initialize(object) {
    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
  }

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

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

  function get(key) {
    if (this._object[key] !== Object.prototype[key])
      return this._object[key];
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

  return {
    initialize:             initialize,
    _each:                  _each,
    set:                    set,
    get:                    get,
    unset:                  unset,
    toObject:               toObject,
    toTemplateReplacements: toObject,
    keys:                   keys,
    values:                 values,
    index:                  index,
    merge:                  merge,
    update:                 update,
    toQueryString:          toQueryString,
    inspect:                inspect,
    toJSON:                 toJSON,
    clone:                  clone
  };
})());

Hash.from = $H;
Object.extend(Number.prototype, (function() {
  function toColorPart() {
    return this.toPaddedString(2, 16);
  }

  function succ() {
    return this + 1;
  }

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

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

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

  function abs() {
    return Math.abs(this);
  }

  function round() {
    return Math.round(this);
  }

  function ceil() {
    return Math.ceil(this);
  }

  function floor() {
    return Math.floor(this);
  }

  return {
    toColorPart:    toColorPart,
    succ:           succ,
    times:          times,
    toPaddedString: toPaddedString,
    toJSON:         toJSON,
    abs:            abs,
    round:          round,
    ceil:           ceil,
    floor:          floor
  };
})());

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

var ObjectRange = Class.create(Enumerable, (function() {
  function initialize(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  }

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

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

  return {
    initialize: initialize,
    _each:      _each,
    include:    include
  };
})());



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

  activeRequestCount: 0
};

Ajax.Responders = {
  responders: [],

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

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

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

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

Object.extend(Ajax.Responders, Enumerable);

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

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

    if (Object.isString(this.options.parameters))
      this.options.parameters = this.options.parameters.toQueryParams();
    else if (Object.isHash(this.options.parameters))
      this.options.parameters = this.options.parameters.toObject();
  }
});
Ajax.Request = Class.create(Ajax.Base, {
  _complete: false,

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

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

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

    this.parameters = params;

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

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

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

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

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

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

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

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

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

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

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

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

    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

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

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

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

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

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

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

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

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

    if (state == 'Complete') {
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

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

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

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

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

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








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

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

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

  status:      0,

  statusText: '',

  getStatus: Ajax.Request.prototype.getStatus,

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

  getHeader: Ajax.Request.prototype.getHeader,

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

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

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

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

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

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

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

    $super(url, options);
  },

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

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

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

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

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

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

    this.start();
  },

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

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

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

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

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});



function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element)){
    element = document.getElementById(element);
  }
  return Element.extend(element);
}

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

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

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

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


(function(global) {

  var SETATTRIBUTE_IGNORES_NAME = (function(){
    var elForm = document.createElement("form");
    var elInput = document.createElement("input");
    var root = document.documentElement;
    elInput.setAttribute("name", "test");
    elForm.appendChild(elInput);
    root.appendChild(elForm);
    var isBuggy = elForm.elements
      ? (typeof elForm.elements.test == "undefined")
      : null;
    root.removeChild(elForm);
    elForm = elInput = null;
    return isBuggy;
  })();

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

Element.cache = { };
Element.idCounter = 1;

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

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


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

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

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

  update: (function(){

    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
      var el = document.createElement("select"),
          isBuggy = true;
      el.innerHTML = "<option value=\"test\">test</option>";
      if (el.options && el.options[0]) {
        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
      }
      el = null;
      return isBuggy;
    })();

    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
      try {
        var el = document.createElement("table");
        if (el && el.tBodies) {
          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
          var isBuggy = typeof el.tBodies[0] == "undefined";
          el = null;
          return isBuggy;
        }
      } catch (e) {
        return true;
      }
    })();

    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
      var s = document.createElement("script"),
          isBuggy = false;
      try {
        s.appendChild(document.createTextNode(""));
        isBuggy = !s.firstChild ||
          s.firstChild && s.firstChild.nodeType !== 3;
      } catch (e) {
        isBuggy = true;
      }
      s = null;
      return isBuggy;
    })();

    function update(element, content) {
      element = $(element);

      if (content && content.toElement)
        content = content.toElement();

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

      content = Object.toHTML(content);

      var tagName = element.tagName.toUpperCase();

      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
        element.text = content;
        return element;
      }

      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
        if (tagName in Element._insertionTranslations.tags) {
          while (element.firstChild) {
            element.removeChild(element.firstChild);
          }
          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
            .each(function(node) {
              element.appendChild(node)
            });
        }
        else {
          element.innerHTML = content.stripScripts();
        }
      }
      else {
        element.innerHTML = content.stripScripts();
      }

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

    return update;
  })(),

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

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

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

    var content, insert, tagName, childNodes;

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

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

      content = Object.toHTML(content);

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

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

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

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

    return element;
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


  select: function(element) {
    var args = Array.prototype.slice.call(arguments, 1);
    return Selector.findChildElements(element, args);
  },

  adjacent: function(element) {
    var args = Array.prototype.slice.call(arguments, 1);
    return Selector.findChildElements(element.parentNode, args).without(element);
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return false;
  },

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

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

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

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

    return element;
  },

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

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

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
      els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      if (Prototype.Browser.Opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

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

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

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

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0, deltaY = 0;
 	deltaY =  window.pageYOffset
           || document.documentElement.scrollTop
           || document.body.scrollTop
           || 0;
           
	do {
		if(Element.getStyle(element, 'position') == 'fixed') { 
			valueT += element.offsetTop + deltaY;
			valueL += element.offsetLeft || 0;
			element = element.offsetParent;
		}
		else {
			valueT += element.offsetTop  || 0;
			valueL += element.offsetLeft || 0;
			element = element.offsetParent;
		}
    } while (element);
    
    return Element._returnOffset(valueL, valueT);
  },
  
  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (element.tagName.toUpperCase() == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p !== 'static') break;
      }
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  absolutize: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'position') == 'absolute') return element;

    var offsets = Element.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';
    return element;
  },

  relativize: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'position') == 'relative') return element;

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

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

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

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

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

    return $(document.body);
  },

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

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

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

    } while (element = element.offsetParent);

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

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

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

    source = $(source);
    var p = Element.viewportOffset(source);

    element = $(element);
    var delta = [0, 0];
    var parent = null;
    if (Element.getStyle(element, 'position') == 'absolute') {
      parent = Element.getOffsetParent(element);
      delta = Element.viewportOffset(parent);
    }

    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

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

Object.extend(Element.Methods, {
  getElementsBySelector: Element.Methods.select,

  childElements: Element.Methods.immediateDescendants
});

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

if (Prototype.Browser.Opera) {
  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
    function(proceed, element, style) {
      switch (style) {
        case 'left': case 'top': case 'right': case 'bottom':
          if (proceed(element, 'position') === 'static') return null;
        case 'height': case 'width':
          if (!Element.visible(element)) return null;

          var dim = parseInt(proceed(element, style), 10);

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

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

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

else if (Prototype.Browser.IE) {
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    function(proceed, element) {
      element = $(element);
      try { element.offsetParent }
      catch(e) { return $(document.body) }
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);
      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    }
  );

  $w('positionedOffset viewportOffset').each(function(method) {
    Element.Methods[method] = Element.Methods[method].wrap(
      function(proceed, element) {
        element = $(element);
        try { element.offsetParent }
        catch(e) { return Element._returnOffset(0,0) }
        var position = element.getStyle('position');
        if (position !== 'static') return proceed(element);
        var offsetParent = element.getOffsetParent();
        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
          offsetParent.setStyle({ zoom: 1 });
        element.setStyle({ position: 'relative' });
        var value = proceed(element);
        element.setStyle({ position: position });
        return value;
      }
    );
  });

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

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

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

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

    
    return value;
  };

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

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

  Element._attributeTranslations = (function(){

    var classProp = 'className';
    var forProp = 'for';

    var el = document.createElement('div');

    el.setAttribute(classProp, 'x');

    if (el.className !== 'x') {
      el.setAttribute('class', 'x');
      if (el.className === 'x') {
        classProp = 'class';
      }
    }
    el = null;

    el = document.createElement('label');
    el.setAttribute(forProp, 'x');
    if (el.htmlFor !== 'x') {
      el.setAttribute('htmlFor', 'x');
      if (el.htmlFor === 'x') {
        forProp = 'htmlFor';
      }
    }
    el = null;

    return {
      read: {
        names: {
          'class':      classProp,
          'className':  classProp,
          'for':        forProp,
          'htmlFor':    forProp
        },
        values: {
          _getAttr: function(element, attribute) {
            return element.getAttribute(attribute);
          },
          _getAttr2: function(element, attribute) {
            return element.getAttribute(attribute, 2);
          },
          _getAttrNode: function(element, attribute) {
            var node = element.getAttributeNode(attribute);
            return node ? node.value : "";
          },
          _getEv: (function(){

            var el = document.createElement('div');
            el.onclick = Prototype.emptyFunction;
            var value = el.getAttribute('onclick');
            var f;

            if (String(value).indexOf('{') > -1) {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                attribute = attribute.toString();
                attribute = attribute.split('{')[1];
                attribute = attribute.split('}')[0];
                return attribute.strip();
              };
            }
            else if (value === '') {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                return attribute.strip();
              };
            }
            el = null;
            return f;
          })(),
          _flag: function(element, attribute) {
            return $(element).hasAttribute(attribute) ? attribute : null;
          },
          style: function(element) {
            return element.style.cssText.toLowerCase();
          },
          title: function(element) {
            return element.title;
          }
        }
      }
    }
  })();

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

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

  Element._attributeTranslations.has = {};

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

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

  if (Prototype.BrowserFeatures.ElementExtensions) {
    (function() {
      function _descendants(element) {
        var nodes = element.getElementsByTagName('*'), results = [];
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName !== "!") // Filter out comment nodes.
            results.push(node);
        return results;
      }

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

}

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

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

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

    return element;
  };

  Element.Methods.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;

 	deltaY =  window.pageYOffset
           || document.documentElement.scrollTop
           || document.body.scrollTop
           || 0;
        
   // if (Element.getStyle(element, 'position') == 'fixed') {
        valueT += deltaY;
   // }

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

console.warn(valueT);


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

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

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

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

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

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

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

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

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

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

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

Element.Methods.ByTag = { };

Object.extend(Element, Element.Methods);

(function(div) {

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

  div = null;

})(document.createElement('div'))

Element.extend = (function() {

  function checkDeficiency(tagName) {
    if (typeof window.Element != 'undefined') {
      var proto = window.Element.prototype;
      if (proto) {
        var id = '_' + (Math.random()+'').slice(2);
        var el = document.createElement(tagName);
        proto[id] = 'x';
        var isBuggy = (el[id] !== 'x');
        delete proto[id];
        el = null;
        return isBuggy;
      }
    }
    return false;
  }

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

  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');

  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
      return function(element) {
        if (element && typeof element._extendedByPrototype == 'undefined') {
          var t = element.tagName;
          if (t && (/^(?:object|applet|embed)$/i.test(t))) {
            extendElementWith(element, Element.Methods);
            extendElementWith(element, Element.Methods.Simulated);
            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
          }
        }
        return element;
      }
    }
    return Prototype.K;
  }

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

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

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

    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

    extendElementWith(element, methods);

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

  }, {
    refresh: function() {
      if (!Prototype.BrowserFeatures.ElementExtensions) {
        Object.extend(Methods, Element.Methods);
        Object.extend(Methods, Element.Methods.Simulated);
      }
    }
  });

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

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

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

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

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

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

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

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

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

    var element = document.createElement(tagName);
    var proto = element['__proto__'] || element.constructor.prototype;
    element = null;
    return proto;
  }

  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
   Element.prototype;

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

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

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

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


document.viewport = {

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

  getScrollOffsets: function() {
    return Element._returnOffset(
      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
  }
};

(function(viewport) {
  var B = Prototype.Browser, doc = document, element, property = {};

  function getRootElement() {
    if (B.WebKit && !doc.evaluate)
      return document;

    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
      return document.body;

    return document.documentElement;
  }

  function define(D) {
    if (!element) element = getRootElement();

    property[D] = 'client' + D;

    viewport['get' + D] = function() { return element[property[D]] };
    return viewport['get' + D]();
  }

  viewport.getWidth  = define.curry('Width');

  viewport.getHeight = define.curry('Height');
})(document.viewport);


Element.Storage = {
  UID: 1
};

Element.addMethods({
  getStorage: function(element) {
    if (!(element = $(element))) return;

    var uid;
    if (element === window) {
      uid = 0;
    } else {
      if (typeof element._prototypeUID === "undefined")
        element._prototypeUID = [Element.Storage.UID++];
      uid = element._prototypeUID[0];
    }

    if (!Element.Storage[uid])
      Element.Storage[uid] = $H();

    return Element.Storage[uid];
  },

  store: function(element, key, value) {
    if (!(element = $(element))) return;

    if (arguments.length === 2) {
      Element.getStorage(element).update(key);
    } else {
      Element.getStorage(element).set(key, value);
    }

    return element;
  },

  retrieve: function(element, key, defaultValue) {
    if (!(element = $(element))) return;
    var hash = Element.getStorage(element), value = hash.get(key);

    if (Object.isUndefined(value)) {
      hash.set(key, defaultValue);
      value = defaultValue;
    }

    return value;
  },

  clone: function(element, deep) {
    if (!(element = $(element))) return;
    var clone = element.cloneNode(deep);
    clone._prototypeUID = void 0;
    if (deep) {
      var descendants = Element.select(clone, '*'),
          i = descendants.length;
      while (i--) {
        descendants[i]._prototypeUID = void 0;
      }
    }
    return Element.extend(clone);
  }
});
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license.  Please see http://www.yui-ext.com/ for more information. */

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

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

  },

  shouldUseXPath: (function() {

    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
      var isBuggy = false;
      if (document.evaluate && window.XPathResult) {
        var el = document.createElement('div');
        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';

        var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
          "//*[local-name()='li' or local-name()='LI']";

        var result = document.evaluate(xpath, el, null,
          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

        isBuggy = (result.snapshotLength !== 2);
        el = null;
      }
      return isBuggy;
    })();

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

      var e = this.expression;

      if (Prototype.Browser.WebKit &&
       (e.include("-of-type") || e.include(":empty")))
        return false;

      if ((/(\[[\w-]*?:|:checked)/).test(e))
        return false;

      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;

      return true;
    }

  })(),

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

    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;

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

    try {
      Selector._div.querySelector(this.expression);
    } catch(e) {
      return false;
    }

    return true;
  },

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

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

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

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

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

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

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

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

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

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

    switch (this.mode) {
      case 'selectorsAPI':
        if (root !== document) {
          var oldId = root.id, id = $(root).identify();
          id = id.replace(/([\.:])/g, "\\$1");
          e = "#" + id + " " + e;
        }

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

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

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

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

    while (e && le !== e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        p = ps[i].re;
        name = ps[i].name;
        if (m = e.match(p)) {
          if (as[name]) {
            this.tokens.push([name, Object.clone(m)]);
            e = e.replace(m[0], '');
          } else {
            return this.findElements(document).include(element);
          }
        }
      }
    }

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

    return match;
  },

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

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

if (Prototype.BrowserFeatures.SelectorsAPI &&
 document.compatMode === 'BackCompat') {
  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
    var div = document.createElement('div'),
     span = document.createElement('span');

    div.id = "prototype_test_id";
    span.className = 'Test';
    div.appendChild(span);
    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
    div = span = null;
    return isIgnored;
  })();
}

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

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

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

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

  patterns: [
    { name: 'laterSibling', re: /^\s*~\s*/ },
    { name: 'child',        re: /^\s*>\s*/ },
    { name: 'adjacent',     re: /^\s*\+\s*/ },
    { name: 'descendant',   re: /^\s/ },

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

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

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

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

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

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

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

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

    unmark: (function(){

      var PROPERTIES_ATTRIBUTES_MAP = (function(){
        var el = document.createElement('div'),
            isBuggy = false,
            propName = '_countedByPrototype',
            value = 'x'
        el[propName] = value;
        isBuggy = (el.getAttribute(propName) === value);
        el = null;
        return isBuggy;
      })();

      return PROPERTIES_ATTRIBUTES_MAP ?
        function(nodes) {
          for (var i = 0, node; node = nodes[i]; i++)
            node.removeAttribute('_countedByPrototype');
          return nodes;
        } :
        function(nodes) {
          for (var i = 0, node; node = nodes[i]; i++)
            node._countedByPrototype = void 0;
          return nodes;
        }
    })(),

    index: function(parentNode, reverse, ofType) {
      parentNode._countedByPrototype = Prototype.emptyFunction;
      if (reverse) {
        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
          var node = nodes[i];
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
      }
    },

    unique: function(nodes) {
      if (nodes.length == 0) return nodes;
      var results = [], n;
      for (var i = 0, l = nodes.length; i < l; i++)
        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
          n._countedByPrototype = Prototype.emptyFunction;
          results.push(Element.extend(n));
        }
      return Selector.handlers.unmark(results);
    },

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

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

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

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

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

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

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

    id: function(nodes, root, id, combinator) {
      var targetNode = $(id), h = Selector.handlers;

      if (root == document) {
        if (!targetNode) return [];
        if (!nodes) return [targetNode];
      } else {
        if (!root.sourceIndex || root.sourceIndex < 1) {
          var nodes = root.getElementsByTagName('*');
          for (var j = 0, node; node = nodes[j]; j++) {
            if (node.id === id) return [node];
          }
        }
      }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

if (Prototype.Browser.IE) {
  Object.extend(Selector.handlers, {
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        if (node.tagName !== "!") a.push(node);
      return a;
    }
  });
}

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}

var Form = {
  reset: function(form) {
    form = $(form);
    form.reset();
    return form;
  },

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

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

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

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

  getElements: function(form) {
    var elements = $(form).getElementsByTagName('*'),
        element,
        arr = [ ],
        serializers = Form.Element.Serializers;
    for (var i = 0; element = elements[i]; i++) {
      arr.push(element);
    }
    return arr.inject([], function(elements, child) {
      if (serializers[child.tagName.toLowerCase()])
        elements.push(Element.extend(child));
      return elements;
    })
  },

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

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

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

    return matchingInputs;
  },

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

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

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

    return firstByIndex ? firstByIndex : elements.find(function(element) {
      return /^(?:input|select|textarea)$/i.test(element.tagName);
    });
  },

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

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

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

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

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

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

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


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

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

Form.Element.Methods = {

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

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

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

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

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

  activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
          !(/^(?:button|reset|submit)$/i.test(element.type))))
        element.select();
    } catch (e) { }
    return element;
  },

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

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

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

var Field = Form.Element;

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

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

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

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

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

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

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

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

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

  optionValue: function(opt) {
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
};

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


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

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

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

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

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

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

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

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

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

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

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

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

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

    cache: {}
  };

  var docEl = document.documentElement;
  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
    && 'onmouseleave' in docEl;

  var _isButton;
  if (Prototype.Browser.IE) {
    var buttonMap = { 0: 1, 1: 4, 2: 2 };
    _isButton = function(event, code) {
      return event.button === buttonMap[code];
    };
  } else if (Prototype.Browser.WebKit) {
    _isButton = function(event, code) {
      switch (code) {
        case 0: return event.which == 1 && !event.metaKey;
        case 1: return event.which == 1 && event.metaKey;
        default: return false;
      }
    };
  } else {
    _isButton = function(event, code) {
      return event.which ? (event.which === code + 1) : (event.button === code);
    };
  }

  function isLeftClick(event)   { return _isButton(event, 0) }

  function isMiddleClick(event) { return _isButton(event, 1) }

  function isRightClick(event)  { return _isButton(event, 2) }

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

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

    if (currentTarget && currentTarget.tagName) {
      if (type === 'load' || type === 'error' ||
        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
          && currentTarget.type === 'radio'))
            node = currentTarget;
    }

    if (node.nodeType == Node.TEXT_NODE)
      node = node.parentNode;

    return Element.extend(node);
  }

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

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

  function pointerX(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollLeft: 0 };

    return event.pageX || (event.clientX +
      (docElement.scrollLeft || body.scrollLeft) -
      (docElement.clientLeft || 0));
  }

  function pointerY(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollTop: 0 };

    return  event.pageY || (event.clientY +
       (docElement.scrollTop || body.scrollTop) -
       (docElement.clientTop || 0));
  }


  function stop(event) {
    Event.extend(event);
    event.preventDefault();
    event.stopPropagation();

    event.stopped = true;
  }

  Event.Methods = {
    isLeftClick: isLeftClick,
    isMiddleClick: isMiddleClick,
    isRightClick: isRightClick,

    element: element,
    findElement: findElement,

    pointer: pointer,
    pointerX: pointerX,
    pointerY: pointerY,

    stop: stop
  };


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

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

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

    Event.extend = function(event, element) {
      if (!event) return false;
      if (event._extendedByPrototype) return event;

      event._extendedByPrototype = Prototype.emptyFunction;
      var pointer = Event.pointer(event);

      Object.extend(event, {
        target: event.srcElement || element,
        relatedTarget: _relatedTarget(event),
        pageX:  pointer.x,
        pageY:  pointer.y
      });

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

  function _createResponder(element, eventName, handler) {
    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) {
      CACHE.push(element);
      registry = Element.retrieve(element, 'prototype_event_registry', $H());
    }

    var respondersForEvent = registry.get(eventName);
    if (Object.isUndefined(respondersForEvent)) {
      respondersForEvent = [];
      registry.set(eventName, respondersForEvent);
    }

    if (respondersForEvent.pluck('handler').include(handler)) return false;

    var responder;
    if (eventName.include(":")) {
      responder = function(event) {
        if (Object.isUndefined(event.eventName))
          return false;

        if (event.eventName !== eventName)
          return false;

        Event.extend(event, element);
        handler.call(element, event);
      };
    } else {
      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
       (eventName === "mouseenter" || eventName === "mouseleave")) {
        if (eventName === "mouseenter" || eventName === "mouseleave") {
          responder = function(event) {
            Event.extend(event, element);

            var parent = event.relatedTarget;
            while (parent && parent !== element) {
              try { parent = parent.parentNode; }
              catch(e) { parent = element; }
            }

            if (parent === element) return;

            handler.call(element, event);
          };
        }
      } else {
        responder = function(event) {
          Event.extend(event, element);
          handler.call(element, event);
        };
      }
    }

    responder.handler = handler;
    respondersForEvent.push(responder);
    return responder;
  }

  function _destroyCache() {
    for (var i = 0, length = CACHE.length; i < length; i++) {
      Event.stopObserving(CACHE[i]);
      CACHE[i] = null;
    }
  }

  var CACHE = [];

  if (Prototype.Browser.IE)
    window.attachEvent('onunload', _destroyCache);

  if (Prototype.Browser.WebKit)
    window.addEventListener('unload', Prototype.emptyFunction, false);


  var _getDOMEventName = Prototype.K;

  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
    _getDOMEventName = function(eventName) {
      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
      return eventName in translations ? translations[eventName] : eventName;
    };
  }

  function observe(element, eventName, handler) {
    element = $(element);

    var responder = _createResponder(element, eventName, handler);

    if (!responder) return element;

    if (eventName.include(':')) {
      if (element.addEventListener)
        element.addEventListener("dataavailable", responder, false);
      else {
        element.attachEvent("ondataavailable", responder);
        element.attachEvent("onfilterchange", responder);
      }
    } else {
      var actualEventName = _getDOMEventName(eventName);

      if (element.addEventListener)
        element.addEventListener(actualEventName, responder, false);
      else
        element.attachEvent("on" + actualEventName, responder);
    }

    return element;
  }

  function stopObserving(element, eventName, handler) {
    element = $(element);

    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) return element;

    if (eventName && !handler) {
      var responders = registry.get(eventName);

      if (Object.isUndefined(responders)) return element;

      responders.each( function(r) {
        Element.stopObserving(element, eventName, r.handler);
      });
      return element;
    } else if (!eventName) {
      registry.each( function(pair) {
        var eventName = pair.key, responders = pair.value;

        responders.each( function(r) {
          Element.stopObserving(element, eventName, r.handler);
        });
      });
      return element;
    }

    var responders = registry.get(eventName);

    if (!responders) return;

    var responder = responders.find( function(r) { return r.handler === handler; });
    if (!responder) return element;

    var actualEventName = _getDOMEventName(eventName);

    if (eventName.include(':')) {
      if (element.removeEventListener)
        element.removeEventListener("dataavailable", responder, false);
      else {
        element.detachEvent("ondataavailable", responder);
        element.detachEvent("onfilterchange",  responder);
      }
    } else {
      if (element.removeEventListener)
        element.removeEventListener(actualEventName, responder, false);
      else
        element.detachEvent('on' + actualEventName, responder);
    }

    registry.set(eventName, responders.without(responder));

    return element;
  }

  function fire(element, eventName, memo, bubble) {
    element = $(element);

    if (Object.isUndefined(bubble))
      bubble = true;

    if (element == document && document.createEvent && !element.dispatchEvent)
      element = document.documentElement;

    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('dataavailable', true, true);
    } else {
      event = document.createEventObject();
      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
    }

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

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

    return Event.extend(event);
  }


  Object.extend(Event, Event.Methods);

  Object.extend(Event, {
    fire:          fire,
    observe:       observe,
    stopObserving: stopObserving
  });

  Element.addMethods({
    fire:          fire,

    observe:       observe,

    stopObserving: stopObserving
  });

  Object.extend(document, {
    fire:          fire.methodize(),

    observe:       observe.methodize(),

    stopObserving: stopObserving.methodize(),

    loaded:        false
  });

  if (window.Event) Object.extend(window.Event, Event);
  else window.Event = Event;
})();

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

  var timer;

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

  function checkReadyState() {
    if (document.readyState === 'complete') {
      document.stopObserving('readystatechange', checkReadyState);
      fireContentLoadedEvent();
    }
  }

  function pollDoScroll() {
    try { document.documentElement.doScroll('left'); }
    catch(e) {
      timer = pollDoScroll.defer();
      return;
    }
    fireContentLoadedEvent();
  }

  if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
  } else {
    document.observe('readystatechange', checkReadyState);
    if (window == top)
      timer = pollDoScroll.defer();
  }

  Event.observe(window, 'load', fireContentLoadedEvent);
})();

Element.addMethods();

/*------------------------------- DEPRECATED -------------------------------*/

Hash.toQueryString = Object.toQueryString;

var Toggle = { display: Element.toggle };

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

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

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

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

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

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

var Position = {
  includeScrollOffsets: false,

  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = Element.cumulativeOffset(element);

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

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

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

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

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


  cumulativeOffset: Element.Methods.cumulativeOffset,

  positionedOffset: Element.Methods.positionedOffset,

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

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

  realOffset: Element.Methods.cumulativeScrollOffset,

  offsetParent: Element.Methods.getOffsetParent,

  page: Element.Methods.viewportOffset,

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

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

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

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

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

    return elements;
  };

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

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

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

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

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

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

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

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

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

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



// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return styleRules;
};

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

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

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

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

Element.addMethods(Effect.Methods);

Effect.BlindLeft = function(element) {
  element = $(element);
  element.makeClipping();
  return new Effect.Scale(element, 0,
    Object.extend({ scaleContent: false,
      scaleY: false,
      scaleMode: 'box',
      scaleContent: false,
      restoreAfterFinish: true,
      afterSetup: function(effect) {
        effect.element.makeClipping().setStyle({
          height: effect.dims[0] + 'px'
        }).show();
      },
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping();
      }
    }, arguments[1] || { })
  );
};
var elementDimensions;

Effect.BlindRight = function(element) {
  element = $(element);
  try{
  if(elementDimensions){
  }else{
  elementDimensions = element.getDimensions();
  }
  }catch(e){
  elementDimensions = element.getDimensions();
  }
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleY: false,
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({
        height: effect.dims[0] + 'px'
      }).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  }, arguments[1] || { }));
};


Effect.BlindToggle = function(element) {
try{
	elementobj = $(element);
	if(elementobj.style.display=='none'){		
		$('tabimage').src="images/open-tab.png";
		$('tabimage').title="Hide View Options";
		elementobj.style.display = 'block';
	}else {
		$('tabimage').src="images/closed-tab.png";
		$('tabimage').title="Show View Options"
		elementobj.style.display = 'none';
	}
}catch(e){}
}



// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
//           (c) 2005-2009 Jon Tirsen (http://www.tirsen.com)
// Contributors:
//  Richard Livsey
//  Rahul Bhargava
//  Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// 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.

if(typeof Effect == 'undefined')
  throw("controls.js requires including script.aculo.us' effects.js library");

var Autocompleter = { };
Autocompleter.Base = Class.create({
  baseInitialize: function(element, update, options) {
    element          = $(element);
    this.element     = element;
    this.update      = $(update);
    this.hasFocus    = false;
    this.changed     = false;
    this.active      = false;
    this.index       = 0;
    this.entryCount  = 0;
    this.oldElementValue = this.element.value;

    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);
    // Force carriage returns as token delimiters anyway
    if (!this.options.tokens.include('\n'))
      this.options.tokens.push('\n');

    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, 'keydown', this.onKeyPress.bindAsEventListener(this));
  },

  show: function() {
    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
    if(!this.iefix &&
      (Prototype.Browser.IE) &&
      (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, {setTop:(!this.update.style.height)});
    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();
         Event.stop(event);
         return;
       case Event.KEY_DOWN:
         this.markNext();
         this.render();
         Event.stop(event);
         return;
      }
     else
       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
         (Prototype.Browser.WebKit > 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;
    this.getEntry(this.index).scrollIntoView(true);
  },

  markNext: function() {
    if(this.index < this.entryCount-1) this.index++;
      else this.index = 0;
    this.getEntry(this.index).scrollIntoView(false);
  },

  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 = $(selectedElement).select('.' + this.options.select) || [];
      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
    } else
      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');

    var bounds = this.getTokenBounds();
    if (bounds[0] != -1) {
      var newValue = this.element.value.substr(0, bounds[0]);
      var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
      if (whitespace)
        newValue += whitespace[0];
      this.element.value = newValue + value + this.element.value.substr(bounds[1]);
    } else {
      this.element.value = value;
    }
    this.oldElementValue = this.element.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.down());

      if(this.update.firstChild && this.update.down().childNodes) {
        this.entryCount =
          this.update.down().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;

      if(this.entryCount==1 && this.options.autoSelect) {
        this.selectEntry();
        this.hide();
      } else {
        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;
    this.tokenBounds = null;
    if(this.getToken().length>=this.options.minChars) {
      this.getUpdatedChoices();
    } else {
      this.active = false;
      this.hide();
    }
    this.oldElementValue = this.element.value;
  },

  getToken: function() {
    var bounds = this.getTokenBounds();
    return this.element.value.substring(bounds[0], bounds[1]).strip();
  },

  getTokenBounds: function() {
    if (null != this.tokenBounds) return this.tokenBounds;
    var value = this.element.value;
    if (value.strip().empty()) return [-1, 0];
    var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
    var offset = (diff == this.oldElementValue.length ? 1 : 0);
    var prevTokenPos = -1, nextTokenPos = value.length;
    var tp;
    for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
      tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
      if (tp > prevTokenPos) prevTokenPos = tp;
      tp = value.indexOf(this.options.tokens[index], diff + offset);
      if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
    }
    return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
  }
});

Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
  var boundary = Math.min(newS.length, oldS.length);
  for (var index = 0; index < boundary; ++index)
    if (newS[index] != oldS[index])
      return index;
  return boundary;
};

Ajax.Autocompleter = Class.create(Autocompleter.Base, {
  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() {
    this.startIndicator();

    var 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.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 and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).

// 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({
  initialize: function(element, url, options) {
    this.url = url;
    this.element = element = $(element);
    this.prepareOptions();
    this._controls = { };
    arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
    Object.extend(this.options, options || { });
    if (!this.options.formId && this.element.id) {
      this.options.formId = this.element.id + '-inplaceeditor';
      if ($(this.options.formId))
        this.options.formId = '';
    }
    if (this.options.externalControl)
      this.options.externalControl = $(this.options.externalControl);
    if (!this.options.externalControl)
      this.options.externalControlOnly = false;
    this._originalBackground = this.element.getStyle('background-color') || 'transparent';
    this.element.title = this.options.clickToEditText;
    this._boundCancelHandler = this.handleFormCancellation.bind(this);
    this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
    this._boundFailureHandler = this.handleAJAXFailure.bind(this);
    this._boundSubmitHandler = this.handleFormSubmission.bind(this);
    this._boundWrapperHandler = this.wrapUp.bind(this);
    this.registerListeners();
  },
  checkForEscapeOrReturn: function(e) {
    if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
    if (Event.KEY_ESC == e.keyCode)
      this.handleFormCancellation(e);
    else if (Event.KEY_RETURN == e.keyCode)
      this.handleFormSubmission(e);
  },
  createControl: function(mode, handler, extraClasses) {
    var control = this.options[mode + 'Control'];
    var text = this.options[mode + 'Text'];
    if ('button' == control) {
      var btn = document.createElement('input');
      btn.type = 'submit';
      btn.value = text;
      btn.className = 'editor_' + mode + '_button';
      if ('cancel' == mode)
        btn.onclick = this._boundCancelHandler;
      this._form.appendChild(btn);
      this._controls[mode] = btn;
    } else if ('link' == control) {
      var link = document.createElement('a');
      link.href = '#';
      link.appendChild(document.createTextNode(text));
      link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
      link.className = 'editor_' + mode + '_link';
      if (extraClasses)
        link.className += ' ' + extraClasses;
      this._form.appendChild(link);
      this._controls[mode] = link;
    }
  },
  createEditField: function() {
    var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
    var fld;
    if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
      fld = document.createElement('input');
      fld.type = 'text';
      var size = this.options.size || this.options.cols || 0;
      if (0 < size) fld.size = size;
    } else {
      fld = document.createElement('textarea');
      fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
      fld.cols = this.options.cols || 40;
    }
    fld.name = this.options.paramName;
    fld.value = text; // No HTML breaks conversion anymore
    fld.className = 'editor_field';
    if (this.options.submitOnBlur)
      fld.onblur = this._boundSubmitHandler;
    this._controls.editor = fld;
    if (this.options.loadTextURL)
      this.loadExternalText();
    this._form.appendChild(this._controls.editor);
  },
  createForm: function() {
    var ipe = this;
    function addText(mode, condition) {
      var text = ipe.options['text' + mode + 'Controls'];
      if (!text || condition === false) return;
      ipe._form.appendChild(document.createTextNode(text));
    };
    this._form = $(document.createElement('form'));
    this._form.id = this.options.formId;
    this._form.addClassName(this.options.formClassName);
    this._form.onsubmit = this._boundSubmitHandler;
    this.createEditField();
    if ('textarea' == this._controls.editor.tagName.toLowerCase())
      this._form.appendChild(document.createElement('br'));
    if (this.options.onFormCustomization)
      this.options.onFormCustomization(this, this._form);
    addText('Before', this.options.okControl || this.options.cancelControl);
    this.createControl('ok', this._boundSubmitHandler);
    addText('Between', this.options.okControl && this.options.cancelControl);
    this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
    addText('After', this.options.okControl || this.options.cancelControl);
  },
  destroy: function() {
    if (this._oldInnerHTML)
      this.element.innerHTML = this._oldInnerHTML;
    this.leaveEditMode();
    this.unregisterListeners();
  },
  enterEditMode: function(e) {
    if (this._saving || this._editing) return;
    this._editing = true;
    this.triggerCallback('onEnterEditMode');
    if (this.options.externalControl)
      this.options.externalControl.hide();
    this.element.hide();
    this.createForm();
    this.element.parentNode.insertBefore(this._form, this.element);
    if (!this.options.loadTextURL)
      this.postProcessEditField();
    if (e) Event.stop(e);
  },
  enterHover: function(e) {
    if (this.options.hoverClassName)
      this.element.addClassName(this.options.hoverClassName);
    if (this._saving) return;
    this.triggerCallback('onEnterHover');
  },
  getText: function() {
    return this.element.innerHTML.unescapeHTML();
  },
  handleAJAXFailure: function(transport) {
    this.triggerCallback('onFailure', transport);
    if (this._oldInnerHTML) {
      this.element.innerHTML = this._oldInnerHTML;
      this._oldInnerHTML = null;
    }
  },
  handleFormCancellation: function(e) {
    this.wrapUp();
    if (e) Event.stop(e);
  },
  handleFormSubmission: function(e) {
    var form = this._form;
    var value = $F(this._controls.editor);
    this.prepareSubmission();
    var params = this.options.callback(form, value) || '';
    if (Object.isString(params))
      params = params.toQueryParams();
    params.editorId = this.element.id;
    if (this.options.htmlResponse) {
      var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
      Object.extend(options, {
        parameters: params,
        onComplete: this._boundWrapperHandler,
        onFailure: this._boundFailureHandler
      });
      new Ajax.Updater({ success: this.element }, this.url, options);
    } else {
      var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
      Object.extend(options, {
        parameters: params,
        onComplete: this._boundWrapperHandler,
        onFailure: this._boundFailureHandler
      });
      new Ajax.Request(this.url, options);
    }
    if (e) Event.stop(e);
  },
  leaveEditMode: function() {
    this.element.removeClassName(this.options.savingClassName);
    this.removeForm();
    this.leaveHover();
    this.element.style.backgroundColor = this._originalBackground;
    this.element.show();
    if (this.options.externalControl)
      this.options.externalControl.show();
    this._saving = false;
    this._editing = false;
    this._oldInnerHTML = null;
    this.triggerCallback('onLeaveEditMode');
  },
  leaveHover: function(e) {
    if (this.options.hoverClassName)
      this.element.removeClassName(this.options.hoverClassName);
    if (this._saving) return;
    this.triggerCallback('onLeaveHover');
  },
  loadExternalText: function() {
    this._form.addClassName(this.options.loadingClassName);
    this._controls.editor.disabled = true;
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        this._form.removeClassName(this.options.loadingClassName);
        var text = transport.responseText;
        if (this.options.stripLoadedTextTags)
          text = text.stripTags();
        this._controls.editor.value = text;
        this._controls.editor.disabled = false;
        this.postProcessEditField();
      }.bind(this),
      onFailure: this._boundFailureHandler
    });
    new Ajax.Request(this.options.loadTextURL, options);
  },
  postProcessEditField: function() {
    var fpc = this.options.fieldPostCreation;
    if (fpc)
      $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
  },
  prepareOptions: function() {
    this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
    Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
    [this._extraDefaultOptions].flatten().compact().each(function(defs) {
      Object.extend(this.options, defs);
    }.bind(this));
  },
  prepareSubmission: function() {
    this._saving = true;
    this.removeForm();
    this.leaveHover();
    this.showSaving();
  },
  registerListeners: function() {
    this._listeners = { };
    var listener;
    $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
      listener = this[pair.value].bind(this);
      this._listeners[pair.key] = listener;
      if (!this.options.externalControlOnly)
        this.element.observe(pair.key, listener);
      if (this.options.externalControl)
        this.options.externalControl.observe(pair.key, listener);
    }.bind(this));
  },
  removeForm: function() {
    if (!this._form) return;
    this._form.remove();
    this._form = null;
    this._controls = { };
  },
  showSaving: function() {
    this._oldInnerHTML = this.element.innerHTML;
    this.element.innerHTML = this.options.savingText;
    this.element.addClassName(this.options.savingClassName);
    this.element.style.backgroundColor = this._originalBackground;
    this.element.show();
  },
  triggerCallback: function(cbName, arg) {
    if ('function' == typeof this.options[cbName]) {
      this.options[cbName](this, arg);
    }
  },
  unregisterListeners: function() {
    $H(this._listeners).each(function(pair) {
      if (!this.options.externalControlOnly)
        this.element.stopObserving(pair.key, pair.value);
      if (this.options.externalControl)
        this.options.externalControl.stopObserving(pair.key, pair.value);
    }.bind(this));
  },
  wrapUp: function(transport) {
    this.leaveEditMode();
    // Can't use triggerCallback due to backward compatibility: requires
    // binding + direct element
    this._boundComplete(transport, this.element);
  }
});

Object.extend(Ajax.InPlaceEditor.prototype, {
  dispose: Ajax.InPlaceEditor.prototype.destroy
});

Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
  initialize: function($super, element, url, options) {
    this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
    $super(element, url, options);
  },

  createEditField: function() {
    var list = document.createElement('select');
    list.name = this.options.paramName;
    list.size = 1;
    this._controls.editor = list;
    this._collection = this.options.collection || [];
    if (this.options.loadCollectionURL)
      this.loadCollection();
    else
      this.checkForExternalText();
    this._form.appendChild(this._controls.editor);
  },

  loadCollection: function() {
    this._form.addClassName(this.options.loadingClassName);
    this.showLoadingText(this.options.loadingCollectionText);
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        var js = transport.responseText.strip();
        if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
          throw('Server returned an invalid collection representation.');
        this._collection = eval(js);
        this.checkForExternalText();
      }.bind(this),
      onFailure: this.onFailure
    });
    new Ajax.Request(this.options.loadCollectionURL, options);
  },

  showLoadingText: function(text) {
    this._controls.editor.disabled = true;
    var tempOption = this._controls.editor.firstChild;
    if (!tempOption) {
      tempOption = document.createElement('option');
      tempOption.value = '';
      this._controls.editor.appendChild(tempOption);
      tempOption.selected = true;
    }
    tempOption.update((text || '').stripScripts().stripTags());
  },

  checkForExternalText: function() {
    this._text = this.getText();
    if (this.options.loadTextURL)
      this.loadExternalText();
    else
      this.buildOptionList();
  },

  loadExternalText: function() {
    this.showLoadingText(this.options.loadingText);
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        this._text = transport.responseText.strip();
        this.buildOptionList();
      }.bind(this),
      onFailure: this.onFailure
    });
    new Ajax.Request(this.options.loadTextURL, options);
  },

  buildOptionList: function() {
    this._form.removeClassName(this.options.loadingClassName);
    this._collection = this._collection.map(function(entry) {
      return 2 === entry.length ? entry : [entry, entry].flatten();
    });
    var marker = ('value' in this.options) ? this.options.value : this._text;
    var textFound = this._collection.any(function(entry) {
      return entry[0] == marker;
    }.bind(this));
    this._controls.editor.update('');
    var option;
    this._collection.each(function(entry, index) {
      option = document.createElement('option');
      option.value = entry[0];
      option.selected = textFound ? entry[0] == marker : 0 == index;
      option.appendChild(document.createTextNode(entry[1]));
      this._controls.editor.appendChild(option);
    }.bind(this));
    this._controls.editor.disabled = false;
    Field.scrollFreeActivate(this._controls.editor);
  }
});

//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only  exists for a while,  in order to  let ****
//**** users adapt to  the new API.  Read up on the new ****
//**** API and convert your code to it ASAP!            ****

Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
  if (!options) return;
  function fallback(name, expr) {
    if (name in options || expr === undefined) return;
    options[name] = expr;
  };
  fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
    options.cancelLink == options.cancelButton == false ? false : undefined)));
  fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
    options.okLink == options.okButton == false ? false : undefined)));
  fallback('highlightColor', options.highlightcolor);
  fallback('highlightEndColor', options.highlightendcolor);
};

Object.extend(Ajax.InPlaceEditor, {
  DefaultOptions: {
    ajaxOptions: { },
    autoRows: 3,                                // Use when multi-line w/ rows == 1
    cancelControl: 'link',                      // 'link'|'button'|false
    cancelText: 'cancel',
    clickToEditText: 'Click to edit',
    externalControl: null,                      // id|elt
    externalControlOnly: false,
    fieldPostCreation: 'activate',              // 'activate'|'focus'|false
    formClassName: 'inplaceeditor-form',
    formId: null,                               // id|elt
    highlightColor: '#ffff99',
    highlightEndColor: '#ffffff',
    hoverClassName: '',
    htmlResponse: true,
    loadingClassName: 'inplaceeditor-loading',
    loadingText: 'Loading...',
    okControl: 'button',                        // 'link'|'button'|false
    okText: 'ok',
    paramName: 'value',
    rows: 1,                                    // If 1 and multi-line, uses autoRows
    savingClassName: 'inplaceeditor-saving',
    savingText: 'Saving...',
    size: 0,
    stripLoadedTextTags: false,
    submitOnBlur: false,
    textAfterControls: '',
    textBeforeControls: '',
    textBetweenControls: ''
  },
  DefaultCallbacks: {
    callback: function(form) {
      return Form.serialize(form);
    },
    onComplete: function(transport, element) {
      // For backward compatibility, this one is bound to the IPE, and passes
      // the element directly.  It was too often customized, so we don't break it.
      new Effect.Highlight(element, {
        startcolor: this.options.highlightColor, keepBackgroundImage: true });
    },
    onEnterEditMode: null,
    onEnterHover: function(ipe) {
      ipe.element.style.backgroundColor = ipe.options.highlightColor;
      if (ipe._effect)
        ipe._effect.cancel();
    },
    onFailure: function(transport, ipe) {
      alert('Error communication with the server: ' + transport.responseText.stripTags());
    },
    onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
    onLeaveEditMode: null,
    onLeaveHover: function(ipe) {
      ipe._effect = new Effect.Highlight(ipe.element, {
        startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
        restorecolor: ipe._originalBackground, keepBackgroundImage: true
      });
    }
  },
  Listeners: {
    click: 'enterEditMode',
    keydown: 'checkForEscapeOrReturn',
    mouseover: 'enterHover',
    mouseout: 'leaveHover'
  }
});

Ajax.InPlaceCollectionEditor.DefaultOptions = {
  loadingCollectionText: 'Loading options...'
};

// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields

Form.Element.DelayedObserver = Class.create({
  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));
  }
});



// script.aculo.us slider.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

if (!Control) var Control = { };

// options:
//  axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider = Class.create({
  initialize: function(handle, track, options) {
    var slider = this;

    if (Object.isArray(handle)) {
      this.handles = handle.collect( function(e) { return $(e) });
    } else {
      this.handles = [$(handle)];
    }

    this.track   = $(track);
    this.options = options || { };

    this.axis      = this.options.axis || 'horizontal';
    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.range     = this.options.range || $R(0,1);

    this.value     = 0; // assure backwards compat
    this.values    = this.handles.map( function() { return 0 });
    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
    this.options.startSpan = $(this.options.startSpan || null);
    this.options.endSpan   = $(this.options.endSpan || null);

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

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

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

    this.trackLength = this.maximumOffset() - this.minimumOffset();

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

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

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

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

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

    // Initialize handles in reverse (make sure first handle is active)
    this.handles.each( function(h,i) {
      i = slider.handles.length-1-i;
      slider.setValue(parseFloat(
        (Object.isArray(slider.options.sliderValue) ?
          slider.options.sliderValue[i] : slider.options.sliderValue) ||
         slider.range.start), i);
      h.makePositioned().observe("mousedown", slider.eventMouseDown);
    });

    this.track.observe("mousedown", this.eventMouseDown);
    document.observe("mouseup", this.eventMouseUp);
    document.observe("mousemove", this.eventMouseMove);

    this.initialized = true;
  },
  dispose: function() {
    var slider = this;
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },
  getNearestValue: function(value){
    if (this.allowedValues){
      if (value >= this.allowedValues.max()) return(this.allowedValues.max());
      if (value <= this.allowedValues.min()) return(this.allowedValues.min());

      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if (currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        }
      });
      return newValue;
    }
    if (value > this.range.end) return this.range.end;
    if (value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if (!this.active) {
      this.activeHandleIdx = handleIdx || 0;
      this.activeHandle    = this.handles[this.activeHandleIdx];
      this.updateStyles();
    }
    handleIdx = handleIdx || this.activeHandleIdx || 0;
    if (this.initialized && this.restricted) {
      if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
        sliderValue = this.values[handleIdx-1];
      if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1];
    }
    sliderValue = this.getNearestValue(sliderValue);
    this.values[handleIdx] = sliderValue;
    this.value = this.values[0]; // assure backwards compat

    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
      this.translateToPx(sliderValue);

    this.drawSpans();
    if (!this.dragging || !this.event) this.updateFinished();
  },
  setValueBy: function(delta, handleIdx) {
    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
      handleIdx || this.activeHandleIdx || 0);
  },
  translateToPx: function(value) {
    return Math.round(
      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
      (value - this.range.start)) + "px";
  },
  translateToValue: function(offset) {
    return ((offset/(this.trackLength-this.handleLength) *
      (this.range.end-this.range.start)) + this.range.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K);
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffset: function(){
    return(this.isVertical() ? this.alignY : this.alignX);
  },
  maximumOffset: function(){
    return(this.isVertical() ?
      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
        this.track.style.height.replace(/px$/,"")) - this.alignY :
      (this.track.offsetWidth != 0 ? this.track.offsetWidth :
        this.track.style.width.replace(/px$/,"")) - this.alignX);
  },
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if (this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if (this.options.startSpan)
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if (this.options.endSpan)
      this.setSpan(this.options.endSpan,
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if (this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if (Event.isLeftClick(event)) {
      if (!this.disabled){
        this.active = true;

        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if (track==this.track) {
          var offsets  = this.track.cumulativeOffset();
          this.event = event;
          this.setValue(this.translateToValue(
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = this.activeHandle.cumulativeOffset();
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode)
            handle = handle.parentNode;

          if (this.handles.indexOf(handle)!=-1) {
            this.activeHandle    = handle;
            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
            this.updateStyles();

            var offsets  = this.activeHandle.cumulativeOffset();
            this.offsetX = (pointer[0] - offsets[0]);
            this.offsetY = (pointer[1] - offsets[1]);
          }
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if (this.active) {
      if (!this.dragging) this.dragging = true;
      this.draw(event);
      if (Prototype.Browser.WebKit) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = this.track.cumulativeOffset();
    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;
  }
});



// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

if(Object.isUndefined(Effect))
  throw("dragdrop.js requires including script.aculo.us' effects.js library");

var Droppables = {
  drops: [],

  remove: function(element) {
    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
  },

  add: function(element) {
    element = $(element);
    var options = Object.extend({
      greedy:     true,
      hoverclass: null,
      tree:       false
    }, arguments[1] || { });

    // cache containers
    if(options.containment) {
      options._containers = [];
      var containment = options.containment;
      if(Object.isArray(containment)) {
        containment.each( function(c) { options._containers.push($(c)) });
      } else {
        options._containers.push($(containment));
      }
    }

    if(options.accept) options.accept = [options.accept].flatten();

    Element.makePositioned(element); // fix IE
    options.element = element;

    this.drops.push(options);
  },

  findDeepestChild: function(drops) {
    deepest = drops[0];

    for (i = 1; i < drops.length; ++i)
      if (Element.isParent(drops[i].element, deepest.element))
        deepest = drops[i];

    return deepest;
  },

  isContained: function(element, drop) {
    var containmentNode;
    if(drop.tree) {
      containmentNode = element.treeNode;
    } else {
      containmentNode = element.parentNode;
    }
    return drop._containers.detect(function(c) { return containmentNode == c });
  },

  isAffected: function(point, element, drop) {
   return (
      (drop.element!=element) &&
      ((!drop._containers) ||
        this.isContained(element, drop)) &&
      ((!drop.accept) ||
        (Element.classNames(element).detect(
          function(v) { return drop.accept.include(v) } ) )) &&
      Position.within(drop.element, point[0], point[1]) );
  },

  deactivate: function(drop) {
    if(drop.hoverclass)
      Element.removeClassName(drop.element, drop.hoverclass);
    this.last_active = null;
  },

  activate: function(drop) {
    if(drop.hoverclass)
      Element.addClassName(drop.element, drop.hoverclass);
    this.last_active = drop;
  },

  show: function(point, element) {
    if(!this.drops.length) return;
    var drop, affected = [];

    this.drops.each( function(drop) {
      if(Droppables.isAffected(point, element, drop))
        affected.push(drop);
    });

    if(affected.length>0)
      drop = Droppables.findDeepestChild(affected);

    if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
    if (drop) {
      Position.within(drop.element, point[0], point[1]);
      if(drop.onHover)
        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));

      if (drop != this.last_active) Droppables.activate(drop);
    }
  },

  fire: function(event, element) {
    if(!this.last_active) return;
    Position.prepare();

    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
      if (this.last_active.onDrop) {
        this.last_active.onDrop(element, this.last_active.element, event);
        return true;
      }
  },

  reset: function() {
    if(this.last_active)
      this.deactivate(this.last_active);
  }
};

var Draggables = {
  drags: [],
  observers: [],

  register: function(draggable) {
    if(this.drags.length == 0) {
      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
      this.eventKeypress  = this.keyPress.bindAsEventListener(this);

      Event.observe(document, "mouseup", this.eventMouseUp);
      Event.observe(document, "mousemove", this.eventMouseMove);
      Event.observe(document, "keypress", this.eventKeypress);
    }
    this.drags.push(draggable);
  },

  unregister: function(draggable) {
    this.drags = this.drags.reject(function(d) { return d==draggable });
    if(this.drags.length == 0) {
      Event.stopObserving(document, "mouseup", this.eventMouseUp);
      Event.stopObserving(document, "mousemove", this.eventMouseMove);
      Event.stopObserving(document, "keypress", this.eventKeypress);
    }
  },

  activate: function(draggable) {
    if(draggable.options.delay) {
      this._timeout = setTimeout(function() {
        Draggables._timeout = null;
        window.focus();
        Draggables.activeDraggable = draggable;
      }.bind(this), draggable.options.delay);
    } else {
      window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
      this.activeDraggable = draggable;
    }
  },

  deactivate: function() {
    this.activeDraggable = null;
  },

  updateDrag: function(event) {
    if(!this.activeDraggable) return;
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    
    // added by Chris - compensate for non-static positioned element
    pointer[1] = pointer[1] + this.activeDraggable.element.getOffsetParent().scrollTop;
    // end
    
    // Mozilla-based browsers fire successive mousemove events with
    // the same coordinates, prevent needless redrawing (moz bug?)
    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
    this._lastPointer = pointer;

    this.activeDraggable.updateDrag(event, pointer);
  },

  endDrag: function(event) {
    if(this._timeout) {
      clearTimeout(this._timeout);
      this._timeout = null;
    }
    if(!this.activeDraggable) return;
    this._lastPointer = null;
    this.activeDraggable.endDrag(event);
    this.activeDraggable = null;
  },

  keyPress: function(event) {
    if(this.activeDraggable)
      this.activeDraggable.keyPress(event);
  },

  addObserver: function(observer) {
    this.observers.push(observer);
    this._cacheObserverCallbacks();
  },

  removeObserver: function(element) {  // element instead of observer fixes mem leaks
    this.observers = this.observers.reject( function(o) { return o.element==element });
    this._cacheObserverCallbacks();
  },

  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
    if(this[eventName+'Count'] > 0)
      this.observers.each( function(o) {
        if(o[eventName]) o[eventName](eventName, draggable, event);
      });
    if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
  },

  _cacheObserverCallbacks: function() {
    ['onStart','onEnd','onDrag'].each( function(eventName) {
      Draggables[eventName+'Count'] = Draggables.observers.select(
        function(o) { return o[eventName]; }
      ).length;
    });
  }
};

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

var Draggable = Class.create({
  initialize: function(element) {
    var defaults = {
      handle: false,
      reverteffect: function(element, top_offset, left_offset) {
        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
        
        new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, 
          queue: {scope:'_draggable', position:'end'}
        });
      },
      endeffect: function(element) {
        var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
          queue: {scope:'_draggable', position:'end'},
          afterFinish: function(){
            Draggable._dragging[element] = false;
          }
        });
      },
      zindex: 1000,
      revert: false,
      quiet: false,
      scroll: false,
      scrollSensitivity: 20,
      scrollSpeed: 15,
      snap: false,  // false, or xy or [x,y] or function(x,y){ return [x,y] }
      delay: 0,
      ghostOpactiy:1
    };

    if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
      Object.extend(defaults, {
        starteffect: function(element) {
          element._opacity = Element.getOpacity(element);
          Draggable._dragging[element] = true;
          new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
        }
      });

    var options = Object.extend(defaults, arguments[1] || { });

    this.element = $(element);

    if(options.handle && Object.isString(options.handle))
      this.handle = this.element.down('.'+options.handle, 0);

    if(!this.handle) this.handle = $(options.handle);
    if(!this.handle) this.handle = this.element;

    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
      options.scroll = $(options.scroll);
      this._isScrollChild = Element.childOf(this.element, options.scroll);
    }

    Element.makePositioned(this.element); // fix IE

    this.options  = options;
    this.dragging = false;

    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
    Event.observe(this.handle, "mousedown", this.eventMouseDown);

    Draggables.register(this);
  },

  destroy: function() {
    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
    Draggables.unregister(this);
  },

  currentDelta: function() {
  	var containerHeight = parseInt(this.element.parentNode.parentNode.style.height);
    
    // Chris's bug fix for Safari. 
    // this.element.height returns NaN instead of 0, which makes everything else NaN.
    
    var elementHeight = this.element.height;
    if(isNaN(parseInt(elementHeight))) elementHeight =0;    
  	var startHeight = containerHeight - parseInt(elementHeight) - 6;
    
    // end fix
    
   return([
      parseInt(Element.getStyle(this.element,'left') || '0'),
      parseInt(Element.getStyle(this.element,'top') || startHeight)]);
  },

  initDrag: function(event) {
    if(!Object.isUndefined(Draggable._dragging[this.element]) &&
      Draggable._dragging[this.element]) return;
    if(Event.isLeftClick(event)) {
      // abort on form elements, fixes a Firefox issue
      var src = Event.element(event);
      if((tag_name = src.tagName.toUpperCase()) && (
        tag_name=='INPUT' ||
        tag_name=='SELECT' ||
        tag_name=='OPTION' ||
        tag_name=='BUTTON' ||
        tag_name=='TEXTAREA')) return;

      var pointer = [Event.pointerX(event), Event.pointerY(event)];
      var pos     = this.element.cumulativeOffset();
      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });

      Draggables.activate(this);
      Event.stop(event);
    }
  },

  startDrag: function(event) {
    this.dragging = true;
    if(!this.delta)
      this.delta = this.currentDelta();


	this.element.style.position='fixed';

    if(this.options.zindex) {
      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
      this.element.style.zIndex = this.options.zindex;
    }

    if(this.options.ghosting) {
      this._clone = this.element.cloneNode(true);
      this._clone.setOpacity(this.options.ghostOpacity);    // added by Chris; can now set opacity of ghost
      this._clone.addClassName("dragGhost");                // added by Chris; can now style the ghost element
      this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
      if (!this._originallyAbsolute)
        Position.absolutize(this.element);
      this.element.parentNode.insertBefore(this._clone, this.element);
    }

    if(this.options.scroll) {
      if (this.options.scroll == window) {
        var where = this._getWindowScroll(this.options.scroll);
        this.originalScrollLeft = where.left;
        this.originalScrollTop = where.top;
      } else {
        this.originalScrollLeft = this.options.scroll.scrollLeft;
        this.originalScrollTop = this.options.scroll.scrollTop;
      }
    }

    Draggables.notify('onStart', this, event);

    if(this.options.starteffect) this.options.starteffect(this.element);
  },

  updateDrag: function(event, pointer) {
    if(!this.dragging) this.startDrag(event);

    if(!this.options.quiet){
      Position.prepare();
      Droppables.show(pointer, this.element);
    }

    Draggables.notify('onDrag', this, event);

    this.draw(pointer);
    if(this.options.change) this.options.change(this);

    if(this.options.scroll) {
      this.stopScrolling();

      var p;
      if (this.options.scroll == window) {
        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
      } else {
        p = Position.page(this.options.scroll);
        p[0] += this.options.scroll.scrollLeft + Position.deltaX;
        p[1] += this.options.scroll.scrollTop + Position.deltaY;
        p.push(p[0]+this.options.scroll.offsetWidth);
        p.push(p[1]+this.options.scroll.offsetHeight);
      }
      var speed = [0,0];
      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
      this.startScrolling(speed);
    }

    // fix AppleWebKit rendering
    if(Prototype.Browser.WebKit) window.scrollBy(0,0);

    Event.stop(event);
  },

  finishDrag: function(event, success) {
    this.dragging = false;

    if(this.options.quiet){
      Position.prepare();
      var pointer = [Event.pointerX(event), Event.pointerY(event)];
      Droppables.show(pointer, this.element);
    }

    if(this.options.ghosting) {
      if (!this._originallyAbsolute)
        Position.relativize(this.element);
      delete this._originallyAbsolute;
      Element.remove(this._clone);
      this._clone = null;
    }

    var dropped = false;
    if(success) {
      dropped = Droppables.fire(event, this.element);
      if (!dropped) dropped = false;
    }
    if(dropped && this.options.onDropped) this.options.onDropped(this.element);
    Draggables.notify('onEnd', this, event);

    var revert = this.options.revert;
    if(revert && Object.isFunction(revert)) revert = revert(this.element);

    var d = this.currentDelta();
    if(revert && this.options.reverteffect) {
      if (dropped == 0 || revert != 'failure')
        this.options.reverteffect(this.element,
          d[1]-this.delta[1], d[0]-this.delta[0]);
    } else {
      this.delta = d;
    }

	this.element.style.position='';

    if(this.options.zindex)
      this.element.style.zIndex = this.originalZ;

    if(this.options.endeffect)
      this.options.endeffect(this.element);

    Draggables.deactivate(this);
    Droppables.reset();
  },

  keyPress: function(event) {
    if(event.keyCode!=Event.KEY_ESC) return;
    this.finishDrag(event, false);
    Event.stop(event);
  },

  endDrag: function(event) {
    if(!this.dragging) return;
    this.stopScrolling();
    this.finishDrag(event, true);
    Event.stop(event);
  },

  draw: function(point) {
    var pos = this.element.cumulativeOffset();

    if(this.options.ghosting) {
      var r   = Position.realOffset(this.element);
      pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
    }

    var d = this.currentDelta();
    pos[0] -= d[0]; pos[1] -= d[1];

    if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
    }

    var p = [0,1].map(function(i){
      return (point[i]-pos[i]-this.offset[i])
    }.bind(this));
    
    if(this.options.snap) {
      if(Object.isFunction(this.options.snap)) {
        p = this.options.snap(p[0],p[1],this);
      } else {
      if(Object.isArray(this.options.snap)) {
        p = p.map( function(v, i) {
          return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
      } else {
        p = p.map( function(v) {
          return (v/this.options.snap).round()*this.options.snap }.bind(this));
      }
    }}
    
    var style = this.element.style;
    
    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
      style.left = p[0] + "px";
    if((!this.options.constraint) || (this.options.constraint=='vertical'))
      style.top  = p[1] + "px";

    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
  },

  stopScrolling: function() {
    if(this.scrollInterval) {
      clearInterval(this.scrollInterval);
      this.scrollInterval = null;
      Draggables._lastScrollPointer = null;
    }
  },

  startScrolling: function(speed) {
    if(!(speed[0] || speed[1])) return;
    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
    this.lastScrolled = new Date();
    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
  },

  scroll: function() {
    var current = new Date();
    var delta = current - this.lastScrolled;
    this.lastScrolled = current;
    if(this.options.scroll == window) {
      with (this._getWindowScroll(this.options.scroll)) {
        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
          var d = delta / 1000;
          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
        }
      }
    } else {
      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
    }

    Position.prepare();
    Droppables.show(Draggables._lastPointer, this.element);
    Draggables.notify('onDrag', this);
    if (this._isScrollChild) {
      Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
      Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
      Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
      if (Draggables._lastScrollPointer[0] < 0)
        Draggables._lastScrollPointer[0] = 0;
      if (Draggables._lastScrollPointer[1] < 0)
        Draggables._lastScrollPointer[1] = 0;
      this.draw(Draggables._lastScrollPointer);
    }

    if(this.options.change) this.options.change(this);
  },

  _getWindowScroll: function(w) {
    var T, L, W, H;
    with (w.document) {
      if (w.document.documentElement && documentElement.scrollTop) {
        T = documentElement.scrollTop;
        L = documentElement.scrollLeft;
      } else if (w.document.body) {
        T = body.scrollTop;
        L = body.scrollLeft;
      }
      if (w.innerWidth) {
        W = w.innerWidth;
        H = w.innerHeight;
      } else if (w.document.documentElement && documentElement.clientWidth) {
        W = documentElement.clientWidth;
        H = documentElement.clientHeight;
      } else {
        W = body.offsetWidth;
        H = body.offsetHeight;
      }
    }
    return { top: T, left: L, width: W, height: H };
  }
});

Draggable._dragging = { };

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

var SortableObserver = Class.create({
  initialize: function(element, observer) {
    this.element   = $(element);
    this.observer  = observer;
    this.lastValue = Sortable.serialize(this.element);
  },

  onStart: function() {
    this.lastValue = Sortable.serialize(this.element);
  },

  onEnd: function() {
    Sortable.unmark();
    if(this.lastValue != Sortable.serialize(this.element))
      this.observer(this.element)
  }
});

var Sortable = {
  SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,

  sortables: { },

  _findRootElement: function(element) {
    while (element.tagName.toUpperCase() != "BODY") {
      if(element.id && Sortable.sortables[element.id]) return element;
      element = element.parentNode;
    }
  },

  options: function(element) {
    element = Sortable._findRootElement($(element));
    if(!element) return;
    return Sortable.sortables[element.id];
  },

  destroy: function(element){
    element = $(element);
    var s = Sortable.sortables[element.id];

    if(s) {
      Draggables.removeObserver(s.element);
      s.droppables.each(function(d){ Droppables.remove(d) });
      s.draggables.invoke('destroy');

      delete Sortable.sortables[s.element.id];
    }
  },

  create: function(element) {
    element = $(element);
    var options = Object.extend({
      element:     element,
      tag:         'li',       // assumes li children, override with tag: 'tagname'
      dropOnEmpty: false,
      tree:        false,
      treeTag:     'ul',
      overlap:     'vertical', // one of 'vertical', 'horizontal'
      constraint:  'vertical', // one of 'vertical', 'horizontal', false
      containment: element,    // also takes array of elements (or id's); or false
      handle:      false,      // or a CSS class
      only:        false,
      delay:       0,
      hoverclass:  null,
      ghosting:    false,
      ghostOpacity: 1,  // added by Chris: set ghosting opacity 0-1
      quiet:       false,
      scroll:      false,
      scrollSensitivity: 20,
      scrollSpeed: 15,
      format:      this.SERIALIZE_RULE,

      // these take arrays of elements or ids and can be
      // used for better initialization performance
      elements:    false,
      handles:     false,

      onChange:    Prototype.emptyFunction,
      onUpdate:    Prototype.emptyFunction,
      onDrop:      Prototype.emptyFunction  // added by Chris - add an extra callback which fires after drop
    }, arguments[1] || { });
    // clear any old sortable with same element
    this.destroy(element);

    // build options for the draggables
    var options_for_draggable = {
      revert:      true,
      quiet:       options.quiet,
      scroll:      options.scroll,
      scrollSpeed: options.scrollSpeed,
      scrollSensitivity: options.scrollSensitivity,
      delay:       options.delay,
      ghosting:    options.ghosting,
      ghostOpacity: options.ghostOpacity,
      constraint:  options.constraint,
      handle:      options.handle,
      onEnd:      options.onDrop,
      onStart:    options.onStart };

    if(options.starteffect)
      options_for_draggable.starteffect = options.starteffect;

    if(options.reverteffect)
      options_for_draggable.reverteffect = options.reverteffect;
    else
      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
        element.style.top  = 0;
        element.style.left = 0;
      };

    if(options.endeffect)
      options_for_draggable.endeffect = options.endeffect;

    if(options.zindex)
      options_for_draggable.zindex = options.zindex;

    // build options for the droppables
    var options_for_droppable = {
      overlap:     options.overlap,
      containment: options.containment,
      tree:        options.tree,
      hoverclass:  options.hoverclass,
      onHover:     Sortable.onHover,
      onDrop:      options.onDrop   // added by Chris - send onDrop option to the droppable
    };

    var options_for_tree = {
      onHover:      Sortable.onEmptyHover,
      overlap:      options.overlap,
      containment:  options.containment,
      hoverclass:   options.hoverclass,
      onDrop:      options.onDrop   // added by Chris - send onDrop option to the droppable
    };

    // fix for gecko engine
    Element.cleanWhitespace(element);

    options.draggables = [];
    options.droppables = [];

    // drop on empty handling
    if(options.dropOnEmpty || options.tree) {
      Droppables.add(element, options_for_tree);
      options.droppables.push(element);
    }

    (options.elements || this.findElements(element, options) || []).each( function(e,i) {
      var handle = options.handles ? $(options.handles[i]) :
        (options.handle ? $(e).select('.' + options.handle)[0] : e);
      options.draggables.push(
        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
      Droppables.add(e, options_for_droppable);
      if(options.tree) e.treeNode = element;
      options.droppables.push(e);
    });

    if(options.tree) {
      (Sortable.findTreeElements(element, options) || []).each( function(e) {
        Droppables.add(e, options_for_tree);
        e.treeNode = element;
        options.droppables.push(e);
      });
    }

    // keep reference
    this.sortables[element.identify()] = options;

    // for onupdate
    Draggables.addObserver(new SortableObserver(element, options.onUpdate));

  },

  // return all suitable-for-sortable elements in a guaranteed order
  findElements: function(element, options) {
    return Element.findChildren(
      element, options.only, options.tree ? true : false, options.tag);
  },

  findTreeElements: function(element, options) {
    return Element.findChildren(
      element, options.only, options.tree ? true : false, options.treeTag);
  },

  onHover: function(element, dropon, overlap) {
    if(Element.isParent(dropon, element)) return;

    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
      return;
    } else if(overlap>0.5) {
      Sortable.mark(dropon, 'before');
      if(dropon.previousSibling != element) {
        var oldParentNode = element.parentNode;
        element.style.visibility = "hidden"; // fix gecko rendering
        dropon.parentNode.insertBefore(element, dropon);
        if(dropon.parentNode!=oldParentNode)
          Sortable.options(oldParentNode).onChange(element);
        Sortable.options(dropon.parentNode).onChange(element);
      }
    } else {
      Sortable.mark(dropon, 'after');
      var nextElement = dropon.nextSibling || null;
      if(nextElement != element) {
        var oldParentNode = element.parentNode;
        element.style.visibility = "hidden"; // fix gecko rendering
        dropon.parentNode.insertBefore(element, nextElement);
        if(dropon.parentNode!=oldParentNode)
          Sortable.options(oldParentNode).onChange(element);
        Sortable.options(dropon.parentNode).onChange(element);
      }
    }
  },

  onEmptyHover: function(element, dropon, overlap) {
    var oldParentNode = element.parentNode;
    var droponOptions = Sortable.options(dropon);

    if(!Element.isParent(dropon, element)) {
      var index;

      var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
      var child = null;

      if(children) {
        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);

        for (index = 0; index < children.length; index += 1) {
          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
            offset -= Element.offsetSize (children[index], droponOptions.overlap);
          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
            child = index + 1 < children.length ? children[index + 1] : null;
            break;
          } else {
            child = children[index];
            break;
          }
        }
      }

      dropon.insertBefore(element, child);

      Sortable.options(oldParentNode).onChange(element);
      droponOptions.onChange(element);
    }
  },

  unmark: function() {
    if(Sortable._marker) Sortable._marker.hide();
  },

  mark: function(dropon, position) {
    // mark on ghosting only
    var sortable = Sortable.options(dropon.parentNode);
    if(sortable && !sortable.ghosting) return;

    if(!Sortable._marker) {
      Sortable._marker =
        ($('dropmarker') || Element.extend(document.createElement('DIV'))).
          hide().addClassName('dropmarker').setStyle({position:'absolute'});
      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
    }
    var offsets = dropon.cumulativeOffset();
    Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});

    if(position=='after')
      if(sortable.overlap == 'horizontal')
        Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
      else
        Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});

    Sortable._marker.show();
  },

  _tree: function(element, options, parent) {
    var children = Sortable.findElements(element, options) || [];

    for (var i = 0; i < children.length; ++i) {
      var match = children[i].id.match(options.format);

      if (!match) continue;

      var child = {
        id: encodeURIComponent(match ? match[1] : null),
        element: element,
        parent: parent,
        children: [],
        position: parent.children.length,
        container: $(children[i]).down(options.treeTag)
      };

      /* Get the element containing the children and recurse over it */
      if (child.container)
        this._tree(child.container, options, child);

      parent.children.push (child);
    }

    return parent;
  },

  tree: function(element) {
    element = $(element);
    var sortableOptions = this.options(element);
    var options = Object.extend({
      tag: sortableOptions.tag,
      treeTag: sortableOptions.treeTag,
      only: sortableOptions.only,
      name: element.id,
      format: sortableOptions.format
    }, arguments[1] || { });

    var root = {
      id: null,
      parent: null,
      children: [],
      container: element,
      position: 0
    };

    return Sortable._tree(element, options, root);
  },

  /* Construct a [i] index for a particular node */
  _constructIndex: function(node) {
    var index = '';
    do {
      if (node.id) index = '[' + node.position + ']' + index;
    } while ((node = node.parent) != null);
    return index;
  },

  sequence: function(element) {
    element = $(element);
    var options = Object.extend(this.options(element), arguments[1] || { });

    return $(this.findElements(element, options) || []).map( function(item) {
      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
    });
  },

  setSequence: function(element, new_sequence) {
    element = $(element);
    var options = Object.extend(this.options(element), arguments[2] || { });

    var nodeMap = { };
    this.findElements(element, options).each( function(n) {
        if (n.id.match(options.format))
            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
        n.parentNode.removeChild(n);
    });

    new_sequence.each(function(ident) {
      var n = nodeMap[ident];
      if (n) {
        n[1].appendChild(n[0]);
        delete nodeMap[ident];
      }
    });
  },

  serialize: function(element) {
    element = $(element);
    var options = Object.extend(Sortable.options(element), arguments[1] || { });
    var name = encodeURIComponent(
      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);

    if (options.tree) {
      return Sortable.tree(element, arguments[1]).children.map( function (item) {
        return [name + Sortable._constructIndex(item) + "[id]=" +
                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
      }).flatten().join('&');
    } else {
      return Sortable.sequence(element, arguments[1]).map( function(item) {
        return name + "[]=" + encodeURIComponent(item);
      }).join('&');
    }
  }
};

// Returns true if child is contained within element
Element.isParent = function(child, element) {
  if (!child.parentNode || child == element) return false;
  if (child.parentNode == element) return true;
  return Element.isParent(child.parentNode, element);
};

Element.findChildren = function(element, only, recursive, tagName) {
  if(!element.hasChildNodes()) return null;
  tagName = tagName.toUpperCase();
  if(only) only = [only].flatten();
  var elements = [];
  $A(element.childNodes).each( function(e) {
    if(e.tagName && e.tagName.toUpperCase()==tagName &&
      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
        elements.push(e);
    if(recursive) {
      var grandchildren = Element.findChildren(e, only, recursive, tagName);
      if(grandchildren) elements.push(grandchildren);
    }
  });

  return (elements.length>0 ? elements.flatten() : []);
};

Element.offsetSize = function (element, type) {
  return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
};



// script.aculo.us scriptaculous.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/

var Scriptaculous = {
  Version: '1.8.3',
  require: function(libraryName) {
    try{
      // inserting via DOM fails in Safari 2.0, so brute force approach
      document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
    } catch(e) {
      // for xhtml+xml served content, fall back to DOM methods
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = libraryName;
      document.getElementsByTagName('head')[0].appendChild(script);
    }
  },
  REQUIRED_PROTOTYPE: '1.6.0.3',
  load: function() {
    function convertVersionString(versionString) {
      var v = versionString.replace(/_.*|\./g, '');
      v = parseInt(v + '0'.times(4-v.length));
      return versionString.indexOf('_') > -1 ? v-1 : v;
    }

    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       (convertVersionString(Prototype.Version) <
        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
        Scriptaculous.REQUIRED_PROTOTYPE);

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

Scriptaculous.load();


var tempA = '';

function ge()
{
	var ea;

	for( var i = 0; i < arguments.length; i++)
	{
    	var e = arguments[i];
	}

	if (typeof e == 'string')
	{
		e = document.getElementById(e);
	}

	if(arguments.length == 1)
	{
		return e;
	}

	if(!ea)
	{
		ea = new Array();
		ea[ea.length] = e;
	}

	return ea;
}

function show()
{
	for( var i = 0; i < arguments.length; i++ )
	{
		var element = ge(arguments[i]);

		if (element && element.style)
		{
			element.style.display = '';
		}
  	}

  	return false;
}








function hide(window_name)
{
	document.getElementById(window_name).style.display="none";
	for( var i = 0; i < arguments.length; i++ )
	{
		var element = ge(arguments[i]);
		if (element && element.style) element.style.display = 'none';
	}
	return false;
}

var windowState = (function(){
var readScroll = {scrollLeft:0,scrollTop:0};
var readSize = {clientWidth:0,clientHeight:0};
var readScrollX = 'scrollLeft';
var readScrollY = 'scrollTop';
var readWidth = 'clientWidth';
var readHeight = 'clientHeight';
function otherWindowTest(obj){
if((document.compatMode)&&
(document.compatMode == 'CSS1Compat')&&
(document.documentElement)){
return document.documentElement;
}else if(document.body){
return document.body;
}else{
return obj;
}
};
if((typeof this.innerHeight == 'number')&&
(typeof this.innerWidth == 'number')){
readSize = this;
readWidth = 'innerWidth';
readHeight = 'innerHeight';
}else{
readSize = otherWindowTest(readSize);
}
if((typeof this.pageYOffset == 'number')&&
(typeof this.pageXOffset == 'number')){
readScroll = this;
readScrollY = 'pageYOffset';
readScrollX = 'pageXOffset';
}else{
readScroll = otherWindowTest(readScroll);
}
return {
getScrollX:function(){
return (readScroll[readScrollX]||0);
},
getScrollY:function(){
return (readScroll[readScrollY]||0);
},
getWidth:function(){
return (readSize[readWidth]||0);
},
getHeight:function(){
return (readSize[readHeight]||0);
}
};
})();

function getStyleObj(id){
var obj = null;
if(document.getElementById){
obj = document.getElementById(id);
}else if(document.all){
obj = document.all[id];
}else if(document.layers){
obj = document.layers[id];
}
return (obj && obj.style) || obj;
}




function showBox(window_name, button1_func, button2_func, button3_func, auto_position) {

if(!auto_position) {
    if(document.getElementById('blackout')){
        document.getElementById('blackout').style.display = 'block'; 
    } else {
        var newdiv = document.createElement('div');
        newdiv.setAttribute('id', 'blackout');
        document.body.appendChild(newdiv);
    
        document.getElementById('blackout').style.display = 'block';     
    }
}
	buttonFunc = [null, null, null];
	buttonFunc[0] = button1_func;
	buttonFunc[1] = button2_func;
	buttonFunc[2] = button3_func;

	show(window_name);

    var divWidth = 0;
    var divHeight = 0;

    var viewPortWidth = 0;
    var viewPortHeight = 0;
    var horizontalScroll = 0;
    var verticalScroll = 0;

    var hPos = 0;
    var vPos = 0;

    var divStyleRef = "";
    var positionMod = "";

    viewPortWidth = windowState.getWidth();
    viewPortHeight = windowState.getHeight();
    horizontalScroll = windowState.getScrollX();
    verticalScroll = windowState.getScrollY();

	if($(window_name).hasClassName('msgPopupNew')){
    	divWidth = $(window_name + 'Inside').offsetWidth;
    	divHeight = $(window_name + 'Inside').offsetHeight;
	} else {
	    divWidth = $(window_name).offsetWidth;
	    divHeight = $(window_name).offsetHeight;
	}

    hPos = Math.round((viewPortWidth-divWidth)/2);
    vPos = Math.round((viewPortHeight-divHeight)/2);

	if($(window_name).hasClassName('msgPopupNew')){
		$(window_name + 'Inside').setStyle({'marginTop':vPos + 'px'});
	} else {
	    divStyleRef = getStyleObj(window_name);
	    positionMod = (typeof divStyleRef.top == 'string')?"px":0;
	    divStyleRef.top = vPos + positionMod;
    	divStyleRef.left = hPos + positionMod;
	}
    
    
    
    
    
    
    
    
    
}



function showBoxNew(window_name, button1_func, button2_func, button3_func, auto_position)
{
	buttonFunc = [null, null, null];

	buttonFunc[0] = button1_func;
	buttonFunc[1] = button2_func;
	buttonFunc[2] = button3_func;
    
    var divWidth = 0;
    var divHeight = 0;

    var viewPortWidth = 0;
    var viewPortHeight = 0;
    var horizontalScroll = 0;
    var verticalScroll = 0;

    var hPos = 0;
    var vPos = 0;

    var divStyleRef = "";
    var positionMod = "";

    viewPortWidth = windowState.getWidth();
    viewPortHeight = windowState.getHeight();
    horizontalScroll = windowState.getScrollX();
    verticalScroll = windowState.getScrollY();

    divWidth = $(window_name).offsetWidth;
    divHeight = $(window_name).offsetHeight;

    hPos = Math.round((viewPortWidth-divWidth)/2);
    vPos = Math.round((viewPortHeight-divHeight)/2);

    divStyleRef = getStyleObj(window_name);
    positionMod = (typeof divStyleRef.top == 'string')?"px":0;

//	temp4 = getImageTop(document.getElementById('grid-item_A_' + tempA));
//	temp5 = (verticalScroll / 2);
//	temp6 = temp4 + temp5;


 //   divStyleRef.top =  temp6 + 'px';
 //   temp = getImageLeft(document.getElementById('grid-item_A_' + tempA)); 
//	temp2 = document.getElementById('grid-item_A_' + tempA).width;
//	temp3 = temp + temp2;
   // divStyleRef.left = temp3 + 'px';
    
    divStyleRef.top = hPos;
    divStyleRef.left = vPos;
    
    show(window_name);
}
function getElementLeft(elem) {
		xPos = elem.offsetLeft;
		tempEl = elem.offsetParent;
  		while (tempEl != null) {
  			xPos += tempEl.offsetLeft;
	  		tempEl = tempEl.offsetParent;
  		}
		return xPos;

}


function getElementTop(elem) {
		yPos = elem.offsetTop;
		tempEl = elem.offsetParent;
		while (tempEl != null) {
  			yPos += tempEl.offsetTop;
	  		tempEl = tempEl.offsetParent;
  		}
		return yPos;
}

function getImageTop(myImage) {
	var y, obj;
	if (document.layers) {
		var img = getImage(myImage);
		if (img.container != null)
			return img.container.pageY + img.y;
		else
			return img.y;
	} else {
		return getElementTop(myImage);
	}
	return -1;
}


function getImageLeft(myImage) {
	var x, obj;
	if (document.layers) {
		var img = getImage(myImage);
    	if (img.container != null)
			return img.container.pageX + img.x;
		else
			return img.x;
  	} else {
		return getElementLeft(myImage);
	}
	return -1;
}

function hideBox(window_name)
{
try{
    document.getElementById('blackout').style.display = 'none';
    }catch(e){} 
	hide(window_name);
	// ... fade
}

function callBoxFunc(func)
{
	if (func == null)
	{
		return hideBox();
	}
	else
	{
		return func();
	}
};

function openGallery(setId)
	{
   	    try {
   	    url = '?service=gallery&action=show_slideshow_page&language=en&gallery=1&set=' + setId;
   	    var slideshow_width = 850;
		var slideshow_height = 687;
		var slideshow_scroll = 1;
		var slideshow_resizeable = 1;
		var win_left = (screen.width - slideshow_width) / 2;
		var win_top = (screen.height - slideshow_height) / 2;
		var winprops = 'address=no,menubar=no,toolbar=no,height='+slideshow_height+',width='+slideshow_width+',top='+win_top+',left='+win_left+',scrollbars='+slideshow_scroll+',resizable='+slideshow_resizeable;
		
				 
   	    //commented working..
   	    browser=navigator.appName;
   		browserindex = browser.search(/Netscape/);
		if(browserindex >= '0')
		{
		
   	    	//window.open(url, 'viewSlideShow','width=550, height=480');
   	    	win = window.open(url, 'viewSlideShow',winprops);
   	    	if (parseInt(navigator.appVersion) >= 4) 
			{ 
				win.window.focus(); 
			}
   	    	
   	    }
   	    else
   	    {
   	    	window.open(url, 'viewSlideShow', winprops);
   	    	//win = window.open(url, 'viewSlideShow', winprops);
   	    	//if (parseInt(navigator.appVersion) >= 4) 
			//{ 
				//win.window.focus(); 
			//}
   	    	
   	    }
        }catch(e){
        }
        return false;
   	   
  	}

function GotoPage(url,frame){
    document.location.href=url;    
}



/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();



function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&id.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; x.oSrc=x.src; x.src=a[i+2];}
}

    
    
// Dragable layers   
    
function Browser() {

  var ua, s, i;

  this.isIE    = false;
  this.isNS    = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}

var browser = new Browser();

// Global object to hold drag information.

var dragObj = new Object();
dragObj.zIndex = 1000;

function dragStart(event, id) {

  var el;
  var x, y;

  // If an element id was given, find it. Otherwise use the element being
  // clicked on.

  if (id)
    dragObj.elNode = document.getElementById(id);
  else {
    if (browser.isIE)
      dragObj.elNode = window.event.srcElement;
    if (browser.isNS)
      dragObj.elNode = event.target;

    // If this is a text node, use its parent element.

    if (dragObj.elNode.nodeType == 3)
      dragObj.elNode = dragObj.elNode.parentNode;
  }

  // Get cursor position with respect to the page.

  if (browser.isIE) {
    x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    y = window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (browser.isNS) {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }

  // Save starting positions of cursor and element.

  dragObj.cursorStartX = x;
  dragObj.cursorStartY = y;
  dragObj.elStartLeft  = parseInt(dragObj.elNode.style.left, 10);
  dragObj.elStartTop   = parseInt(dragObj.elNode.style.top,  10);

  if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
  if (isNaN(dragObj.elStartTop))  dragObj.elStartTop  = 0;

  // Update element's z-index.

  dragObj.elNode.style.zIndex = ++dragObj.zIndex;

  // Capture mousemove and mouseup events on the page.

  if (browser.isIE) {
    document.attachEvent("onmousemove", dragGo);
    document.attachEvent("onmouseup",   dragStop);
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  if (browser.isNS) {
    document.addEventListener("mousemove", dragGo,   true);
    document.addEventListener("mouseup",   dragStop, true);
    event.preventDefault();
  }
}

function dragGo(event) {

  var x, y;

  // Get cursor position with respect to the page.

  if (browser.isIE) {
    x = window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    y = window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (browser.isNS) {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }

  // Move drag element by the same amount the cursor has moved.

  dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
  dragObj.elNode.style.top  = (dragObj.elStartTop  + y - dragObj.cursorStartY) + "px";

  if (browser.isIE) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  if (browser.isNS)
    event.preventDefault();
}

function dragStop(event) {

  // Stop capturing mousemove and mouseup events.

  if (browser.isIE) {
    document.detachEvent("onmousemove", dragGo);
    document.detachEvent("onmouseup",   dragStop);
  }
  if (browser.isNS) {
    document.removeEventListener("mousemove", dragGo,   true);
    document.removeEventListener("mouseup",   dragStop, true);
  }
}            
			var Popup = {
			  open: function(options)
			  {
			    this.options = {
			      url: '#',
			      width: 600,
			      height: 500,
			      name:"_blank",
			      location:"no",
			      menubar:"no",
			      toolbar:"no",
			      status:"yes",
			      scrollbars:"yes",
			      resizable:"yes",
			      left:"",
			      top:"",
			      normal:false
			    }
			    Object.extend(this.options, options || {});
			
			    if (this.options.normal){
			        this.options.menubar = "yes";
			        this.options.status = "yes";
			        this.options.toolbar = "yes";
			        this.options.location = "yes";
			    }
			
			    this.options.width = this.options.width < screen.availWidth?this.options.width:screen.availWidth;
			    this.options.height=this.options.height < screen.availHeight?this.options.height:screen.availHeight;
			    var openoptions = 'width='+this.options.width+',height='+this.options.height+',location='+this.options.location+',menubar='+this.options.menubar+',toolbar='+this.options.toolbar+',scrollbars='+this.options.scrollbars+',resizable='+this.options.resizable+',status='+this.options.status
			    if (this.options.top!="")openoptions+=",top="+this.options.top;
			    if (this.options.left!="")openoptions+=",left="+this.options.left;
			    window.open(this.options.url, this.options.name,openoptions );
			    return false;
			  }
			}


function Asset()
{
	var autozoom_enabled = false;
	var Running = new Array();
	var HideMe = new Array();
    
    // Set to true when the first autozoom image has been shown
    // Means that actions can be added on autozoom rather than on load
    var hasShownFirstAutoZoom = false;  

	this.showZoomKeywordsWindow = function(asset, asset_location)
	{
		url = '?service=asset&action=show_zoom_keywords_window&language=en&asset=' + asset + '&location=' + asset_location;
		new Ajax.Updater('assetZoomWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function() 
			{
				showBox('assetZoomWindow');
			}
		});
	}

	this.showDownloadLowResWindow = function(asset, asset_location)
	{
		url = '?service=asset&action=show_download_low_res_window&language=en&asset=' + asset + '&location=' + asset_location;
		new Ajax.Updater('assetZoomWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('assetZoomWindow');
			}
		});
	}

	this.zoomPopup = function(asset, asset_location, assetel, asset_list, basket_item_id)
		{
   	    $('assetAutoZoomWindow').style.display = 'none';
   	   
   	    if(Element.hasClassName($(assetel), 'clicked')) {
					$$('.clicked').each(function(el,index){
										el.removeClassName('clicked');
										el.removeClassName('clicked2');
										window.open('?service=asset&action=show_zoom_window_popup&language=en&asset=' + Lightbox.getObjectId(el) + '&location=' + asset_location + '&asset_list=' + asset_list + '&basket_item_id=' + basket_item_id, '', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=860,height=700,top=' + cascadeWinTop + ',left=' + cascadeWinLeft);
										cascadeWinTop += 20;
										cascadeWinLeft += 20;
										if(screen.availHeight < (cascadeWinTop + 700 - 20)) { cascadeWinTop = 0;} 
										if(screen.availWidth < (cascadeWinLeft + 860 - 20)) { cascadeWinLeft = 0;}
		
									});		

		} else {
		
		window.open('en/asset/show_zoom_window_popup.html?asset=' + asset + '&location=' + asset_location + '&asset_list=' + asset_list + '&basket_item_id=' + basket_item_id, '', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=860,height=700,top=' + cascadeWinTop + ',left=' + cascadeWinLeft);
		cascadeWinTop += 20;
		cascadeWinLeft += 20;
		if(screen.availHeight < (cascadeWinTop + 700 - 20)) { cascadeWinTop = 0;} 
		if(screen.availWidth < (cascadeWinLeft + 860 - 20)) { cascadeWinLeft = 0;}

	}		
		
		
	}

	this.closeZoomWindow = function()
	{
		hideBox('assetZoomWindow');
		
	}

	this.enableAutoZoom = function()
	{
	
		this.autozoom_enabled = true;
	}

	this.disableAutoZoom = function()
	{
		this.autozoom_enabled = false;
	}
	
	this.showAutoZoomWindow = function(asset, element)
	{
        // Shows the autozoom for a particular item
        
        hasShownFirstAutoZoom = true;   // will only do the above IE things once
        
		try{
		aId=element.id;
		}catch(e){}
		if (this.autozoom_enabled) {
		if(Running[aId.replace('assetLink_A_','')] != true) {
		for ( var i in HideMe ) {
			clearTimeout(HideMe[i]);
		}
		for ( var i in Running ) {
			Running[i] = false;
		}		
			Running = new Array();
			Running[aId.replace('assetLink_A_','')] = true;
			$A($$('.autozoom')).each(function(el){el.setStyle({display:'none'});});
			$A($$('.autoZoomText')).each(function(el){el.setStyle({display:'none'});});
			$A($$('.icos')).each(function(el){el.setStyle({display:'none'});});
			$A($$('.previewrel')).each(function(el){el.src='x.gif';});
			imgId=element.id.replace('assetLink','grid-item');
			$(aId + 'div').setStyle({ position:'absolute',backgroundColor:'#fff', display:'none', zIndex:'999'});
			$(aId.replace('assetLink_A_','')).setStyle({width:'100%'});

			if($(aId.replace('assetLink_A_','')).src != $(aId.replace('assetLink_A_','')).alt) {
				$(aId.replace('assetLink_A_','')).src = $(aId.replace('assetLink_A_','')).alt;		
			
			}else{
			// Already Loaded
			
			}
			
			
			$(aId.replace('assetLink_A_','')).observe('load', function(){
		
				/* VARS */
				vPadding = 5;
				
				/* View Port Information */
				viewWidth = document.viewport.getWidth();
				viewHeight = document.viewport.getHeight();					
				viewScroll = document.viewport.getScrollOffsets();
				viewScrollLeft = viewScroll[0];
				viewScrollTop = viewScroll[1];
				
				/* Thumbnail Information */
				thumbWidth = $(imgId).getWidth();
				thumbHeight = $(imgId).getHeight();  
				thumbOffset = $(imgId).cumulativeOffset();
				thumbLeft = thumbOffset[0];
				thumbTop = thumbOffset[1];
				thumbRight = thumbWidth + thumbLeft;
				thumbBottom = thumbHeight + thumbTop;
				
				realThumbLeft = thumbLeft - viewScrollLeft;
				realThumbTop = thumbTop - viewScrollTop;
				realThumbRight = thumbWidth + realThumbLeft;
				realThumbBottom = (thumbHeight + realThumbTop);

				/*Preview Image Info*/
				$(aId + 'div').setStyle({width:'5000px', position:'absolute', left:'-50000px'});
				$(aId + 'div').setStyle({display:'block'});
					$(aId.replace('assetLink_A_','')).setStyle({width:'auto'});
					imgWidth = $(aId.replace('assetLink_A_','')).getWidth();
					imgHeight = $(aId.replace('assetLink_A_','')).getHeight();
					$(aId.replace('assetLink_A_','')).setStyle({margin:'0px', border:'0px',maxWidth: imgWidth + 'px',width:'100%', position:'static'});
					$(aId + 'div').setStyle({width: imgWidth + 'px'});
					boxHeight = $(aId + 'div').getHeight();
					
				try{
				ww = aId + 'div';
				$(ww).setStyle({'display':'none'});
				$A($$('.autoZoomText')).each(function(el){el.setStyle({'display':'none'});});
				$A($$('.icos')).each(function(el){el.setStyle({'display':'none'});});
				}catch(e){}
						
				/* Div Information */
				tempLeft = Math.floor(thumbWidth/2);
				tempBottom = Math.floor(thumbHeight/2);
				$(aId + 'div').setStyle({height: 'auto', width:'1px', display:'none', left: tempLeft + 'px', bottom: tempBottom + 'px'});
						
						
				tempLeft =  ((( imgWidth + (vPadding * 2) ) /2)*-1) + (thumbWidth/2);
				tempBottom = ((( imgHeight + (vPadding * 2) ) /2)*-1) + (thumbHeight/2); 

				lightboxHeight=0;
				basketHeight=0
				similarHeight=0;

				try{lightboxHeight = $('lightbox-container').getHeight();}catch(e){}
				try{basketHeight = $('basket-container').getHeight();}catch(e){}
				try{similarHeight = $('similars-container').getHeight();}catch(e){}
				panelHeight = lightboxHeight + basketHeight + similarHeight;
				
				
				//Left Protection
				if( (tempLeft - 10) < (realThumbLeft * -1)) {
					tempLeft = ((realThumbLeft * -1) + 10);
				}
				
				//Bottom Protection
				if ((tempBottom *-1) + realThumbBottom + 30 > (viewHeight - panelHeight)){
					tempBottom = tempBottom - ((viewHeight - panelHeight) - ((tempBottom *-1) + realThumbBottom + 30));
				}

				//Right Protection
				if((tempLeft + imgWidth + 20 + thumbLeft) > (viewWidth + viewScrollLeft)) {
					tt1 = tempLeft + imgWidth + 20 + thumbLeft;
					tt2 = viewWidth + viewScrollLeft;
					tt3 = tt1-tt2;
					tempLeft=tempLeft - tt3;					
				}
				
				
				
				//Top Protection
				if($('topContainer') && $('topContainer').getStyle('position') == 'fixed'){
					tt9 = $('topContainer').getHeight();				
					realThumbTop -= tt9;
					
					
				}					
				
				if( boxHeight + 60 > (((tempBottom) *-1 ) + thumbHeight + realThumbTop)){
					tt1 = boxHeight + 60 - (((tempBottom) *-1 ) + thumbHeight + realThumbTop);
					tempBottom = tempBottom - tt1;				
				}	
					
							
				if($('topContainer') && $('topContainer').getStyle('position') == 'fixed'){
					tt9 = $('mainContent').cumulativeScrollOffset();				
					tempBottom -= (tt9[1] - (40));
					
				}	
				if(Prototype.Browser.WebKit){
					tt9 = $('mainContent').cumulativeScrollOffset();				
					tempBottom -= (tt9[1] - (40));				}

				
				
				
				
				
				divEndStyle = 'height:' + (boxHeight+50) + 'px;zIndex:99999999;z-Index:9999999999;bottom:' + tempBottom +'px;left:' + tempLeft + 'px; padding:'+vPadding+'px;width:' + ( imgWidth ) + 'px;';
				
				
				$A($$('.autoZoomText')).each(function(el){el.setStyle({display:'none'});});
				$(aId + 'div').setStyle({display:'block'});
				new Effect.Morph(aId + 'div', {style: divEndStyle, duration: 0.0, afterFinish:function(){
					$A($$('.autoZoomText')).each(function(el){el.setStyle({display:'block'});});
					$A($$('.icos')).each(function(el){el.setStyle({display:'block'});});
					/*if(Prototype.Browser.IE){
						$A($$('.mainThumbImage')).each(function(el){el.setStyle({position:'static'});});
						$A($$('.pictureBox_img')).each(function(el){el.setStyle({position:'static'});});
					}*/
				}});

			});

			$(aId + 'div').observe('mouseout', function(){
				clearTimeout(HideMe[aId.replace('assetLink_A_','')]);
				HideMe[aId.replace('assetLink_A_','')] = setTimeout(

					function(){
					/*if(Prototype.Browser.IE){
						$A($$('.mainThumbImage')).each(function(el){el.setStyle({position:'absolute'});});
						$A($$('.pictureBox_img')).each(function(el){el.setStyle({position:'relative'});});
					}*/
						$(aId + 'div').setStyle({display:'none'});
						$(aId.replace('assetLink_A_','')).src = 'x.gif';
						setTimeout(function(){Running[aId.replace('assetLink_A_','')] = false;},500);
					}, 500
				);
				
			});

			$(aId + 'div').observe('mouseover', function(){
				clearTimeout(HideMe[aId.replace('assetLink_A_','')]);
			});			
			}else{
			
			}
		}
	}

	this.showSimilarsWindow = function(asset, asset_location) {
		url = '?service=asset&action=show_similar_images&language=en&asset=' + asset + '&location=' + asset_location;
		new Ajax.Updater('assetZoomWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function() {
				showBox('assetZoomWindow');
			}
		});
	}

	this.closeAutoZoom = function() {
		$A($$('.autozoom')).each(function(el){el.setStyle({display:'none'});});		
	}

	this.downloadCompImage = function(asset, size) {
 
				var acknowlaged = true;
 
		if (acknowlaged) {
			url = '?service=asset&action=download_comp_image&asset=' + asset + '&size=' + size;
			document.location = url;
		}
	}

	this.showFeaturesWindow = function(asset, asset_location)
	{
		url = '?service=asset&action=show_features_window&asset=' + asset + '&language=en&location=' + asset_location;
		new Ajax.Updater('assetZoomWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function() 
			{ 
				showBox('assetZoomWindow');
			}
		});
	}
	
	this.searchAssetKeywords = function(language, keywords)
	{
		params = keywords.join(',');
		
		url = '?service=search&action=do_quick_search&language=' + language + '&mode=keywords&q=' + escape(params);
		
		document.location = url;
	}

	this.checkSubscriptionDownload = function(asset, on_success_action, on_failure_action)
	{
		url = '?service=asset&action=do_check_scr_download&asset=' + asset;
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
				
				if (response_code == "true")
				{
					on_success_action();
				}
				else
				{
					on_failure_action();
				}
			}
		});	
	}
	
	this.showAssetSubscriptionDownloadNAWindow = function(language, on_OK_button_action)
	{
		url = '?service=asset&action=show_scr_download_na_window&language=' + language;
		new Ajax.Updater('assetSubscriptionDownloadNAWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('assetSubscriptionDownloadNAWindow', on_OK_button_action);
			}
		});
	}
	
	this.closeAssetSubscriptionDownloadNAWindow = function()
	{
		hideBox('assetSubscriptionDownloadNAWindow');
	}
	
	this.loadPlainTextPreview = function(asset)
	{
		url = '?service=asset&action=show_preview&asset=' + asset;
		new Ajax.Updater('textPreview', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				$('textPreview').innerHTML = $('textPreview').innerHTML;
			}
		});
	}
	
	this.email = function(asset, email, subject, description, on_success_action, on_failure_action)
	{
		params = 'email=' + email + '&subject=' +  subject.replace('?','%3F') + '&description=' + description.replace('?','%3F');
		url = '?service=asset&action=do_email&asset=' + asset;
		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params, 
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
		
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}
				else
				{
					document.location = '?service=error&action=show_db_error_page';
				}
				
				return result;
			}
		});
	}
	
	this.showEmailWindow = function(asset, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=asset&action=show_email_window&language=' + this.language + '&asset=' + asset;
		
		new Ajax.Updater('messageWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('messageWarningWindow', on_OK_button_action, on_CANCEL_button_action); 
			}
		});
	}

	this.showEmailFormErrors = function(language)
	{
		url = '?service=asset&action=show_email_form_errors&language=' + language;
		new Ajax.Updater('assetEmailFormErrors', url, {method: 'get', asynchronous:true, evalScripts:true});
	}
	
	this.closeEmailWindow = function()
	{
		hideBox('messageWarningWindow');
	}

}

var Asset = new Asset();

function Similars() {
	
	var object = this;
	
	this.initPreviewPanel = function(asset, on_complete_action) {
		
	this.showPreviewPanel(asset, function() 
	{
				$('similars-preview-panel-basket-selector').onclick = 
					function()
					{
						setCookie('simPan','0','31');
						Basket.initPreviewPanel(Basket.getBasketId(),
							function()
							{
								try{
    	                            Basket.show();
                                }catch(e){}
                                try{
									object.hide();
                                }catch(e){}
                                try{
									Basket.enableSlider();
									if($('similars-maximize').style.display == 'none') {
										Basket.maximize();
									}
										else {
										Basket.minimize();
									}
                                }catch(e){}

							}
						);

						return false;
					};
					
					$('similars-preview-panel-lightbox-selector').onclick = 
						function()
						{
							setCookie('simPan','0','31');
							Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
								function()
								{
									Lightbox.show();
									object.hide();
									Lightbox.enableSlider();
									if($('similars-maximize').style.display == 'none') {
										Lightbox.maximize();
									}
										else {
										Lightbox.minimize();
									}
								}
									
							);
							return false;
						};
						
					$('similars-minimize').onclick = 
						function()
						{
							object.minimize();
							$('pull-tab').style.display = 'none';
						};
					$('similars-maximize').onclick = 
						function()
						{
							object.maximize();
							$('pull-tab').style.display = 'block';
						};
					Sortable.create('similars-preview-panel-content',
					{
						tag: 'div', overlap: 'horizontal', constraint: false,
						onUpdate: function() 
						{ 
							object.reSortItems(object.getLightboxId());
						}
					});
			}
		);
		
		if (on_complete_action) 
		{
			on_complete_action();
		}
	}
	
	
	this.countSimilars = function()
	{
		var similarsCount = 0;
		$A($('similars-preview-panel').getElementsByTagName('img')).each(
			function(element)
			{
				if (Element.hasClassName(element, 'thumbnail'))
				{
					similarsCount++;
				}
			});
		return similarsCount;
	}
	
	
	this.show = function()
	{
		this.previewSelected = true;

		$('similars-preview-panel').style.display = '';
	}
	this.hide = function()
	{
		this.previewSelected = false;

		$('similars-preview-panel').style.display = 'none';
	}
	this.enableSlider = function(value)
	{
	   var delta=25;
       	var myHeight = 141;
            if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
            }
       
		var myWidth = 600;
		if (parseInt(navigator.appVersion)>3) {
			if (navigator.appName=="Netscape") {
				myWidth = window.innerWidth;
			}
			if (navigator.appName.indexOf("Microsoft")!=-1) {
				myWidth = document.body.offsetWidth;
			}
		}
		myWidth = myWidth-14;
		$('pull-tab').style.width = myWidth + 'px';
             if($('pull-tab').getWidth() != myWidth){
                //$('pull-tab').style.left = ((myWidth-$('pull-tab').getWidth()) / 2) + 'px'; 
              $('pull-tab').style.bottom = '-7px'   
            }
            
            if ($('basket-container')) {
                if($('basket-maximize').style.display=="none")
                {
                    // only adjust basket height if it's not minimized
                 	$('basket-container').style.height = myHeight + delta + 'px';
                	$('basket-preview-panel-content').style.height = 114 + delta + 'px';
                }
            }
			if ($('lightbox-container')) {
                if($('lightbox-maximize').style.display=="none")
                {
                    // only adjust lightbox height if it's not minimized
                    $('lightbox-container').style.height = myHeight + delta + 'px';
                    $('lightbox-preview-panel-content').style.height = 114 + delta + 'px';
                }
			} 
            if ($('similars-container')) {
                if($('similars-maximize').style.display=="none")
                {
                    // only adjust similars height if it's not minimized
                    $('similars-container').style.height = myHeight + delta + 'px';
                    $('similars-preview-panel-content').style.height = 114 + delta + 'px';
                }
			} 
            
		var slider = new Control.Slider('pull-tab', 'pull-track', {
			 axis: 'vertical',
			 range: $R(0, 100),
      		 sliderValue: 100,
			 onSlide: function(value)
			 {
			 	var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");

			 	$('similars-container').style.height = myHeight + delta + 'px';
				$('similars-preview-panel-content').style.height = 114 + delta + 'px';
			},
			onChange:function()
			{
				var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");

				$('similars-container').style.height = myHeight + delta + 'px';
				$('similars-preview-panel-content').style.height = 114 + delta + 'px';
			}
		});

		if (value != null)
		{
			//slider.setValue(value);
		}
        
        $('pull-tab').style.top = (parseInt($('pull-tab').style.top.replace(/px$/,"")) - delta+6) + 'px';  

	}
	this.minimize = function(on_complete_action)
	{
		if($('similars-container')) {
			$('similars-preview-panel-content').style.display = 'none';
			$('similars-container').style.height = '30px';
			$('similars-minimize').style.display = 'none';
			$('similars-maximize').style.display = '';
		}
		$('pull-tab').style.bottom = '-110px';
		$('pull-tab').style.top = '';
		$('pull-tab').style.display = 'none';
		url = '?service=user&action=do_collapse_container';

		new Ajax.Request(url, {method: 'get', asynchronous:false, onComplete: on_complete_action});
	   setCookie('maximized','0','31');
    }
	this.maximize = function(on_complete_action)
	{
	   // old maximize code
		/*if($('similars-container')) {
			$('similars-preview-panel-content').style.display = 'block';
			//$('similars-container').style.height = '140px';
			$('similars-maximize').style.display = 'none';
			$('similars-minimize').style.display = '';
		}
		$('pull-tab').style.bottom = '0px';
		$('pull-tab').style.top = '';
		$('pull-tab').style.display = '';
		$('pull-tab').style.backgroundPosition = 'center center';

		url = '?service=user&action=do_expand_container';

		new Ajax.Request(url, {method: 'get', asynchronous:false, onComplete: on_complete_action});
        Lightbox.enableSlider();
       */ 
       
	   //$('pull-tab').style.display = 'none';
       // set the height to maximize to (based on delta)
	   var delta;
       var myHeight = 122;
	   if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
       } else {
            delta = 140-myHeight; 
       }
       
       // show the similars
		if($('similars-container')) {
			$('similars-preview-panel-content').setStyle({'display':'block'});
			$('similars-container').style.height = myHeight + delta + 'px';
			$('similars-maximize').style.display = 'none';
			$('similars-minimize').style.display = '';
		}
        
        // set slider dimensions
		
		//$('pull-tab').style.top = (parseInt($('pull-tab').style.top.replace(/px$/,"")) - delta + 18) + 'px';  ;
		
		$('pull-tab').style.backgroundPosition = 'center center';

		url = '?service=user&action=do_expand_container';

		new Ajax.Request(url, {method: 'get', asynchronous:false, onComplete: on_complete_action});
	    setCookie('maximized','1','31');
        $('pull-tab').style.display = 'block';
        this.enableSlider();
	}
	this.showPreviewPanel = function(asset, on_complete_action)
	{
	    
		var temp;
		var tempArray;
		temp = '';
		$$('.clicked2').each(function(el,index){
			tempArray = el.id.split('_');
			temp+= '||' + tempArray[2];
		});

		if(asset != '' || !($('similars-preview-panel-content'))) {
			url = '?service=asset&action=show_similars_panel&assets='+asset;
			new Ajax.Updater('similars-preview-panel', url, {method: 'get', asynchronous:false, evalScripts:true, onComplete:on_complete_action});
		}
        Similars.enableSlider();
        
        // update totals in overlay (e.g. "Similars (0)") for other panels
        if(Lightbox) Lightbox.updateTotals();
        if(Basket) Basket.updateTotals();
	}
	
}
var Similars = new Similars();


	function addItemToBasketLink_onClick(item)
	{
        noclear =1;
		Basket.addItem(item,
        	function()
        	{
		        if (Basket.isPreviewSelected())
		        {
					Basket.showPreview(
						function()
	    				{
		    				Basket.showPreviewPanel();
	    				}
					);
		        }
        	}
        );
        noclear=0;
	}

	function removeItemFromBasketLink_onClick(item)
	{
		noclear=1;
		Basket.removeItem(item,
			function()
			{
				Basket.showPreview(
					function()
	    			{
		    			Basket.showPreviewPanel();
	    			}
				);
			}
		);
		noclear=0;
	}

	function removeAssetFromBasketLink_onClick(asset)
	{
		noclear=1;
		Basket.removeAsset(asset,
			function()
			{
				if (Basket.isPreviewSelected())
		        {
			        Basket.showPreviewPanel();
			        Basket.showPreview();
        		}
			}
		);
		noclear=0;	
	}

	function addAssetToLightboxLink_onClick(asset)
	{
      	noclear=1;
		if (Lightbox.getSelectedId() != null)
        {
    		Lightbox.addItem(Lightbox.getSelectedId(), asset,
		   		function()
		   		{
		   			if (Lightbox.isPreviewSelected())
		   			{
			    		Lightbox.showPreview(Lightbox.getSelectedId(),
			    			function()
			    			{
								Lightbox.showPreviewPanel();
			    			}
			    		);
		   			}
		   		}
    		);

		}
		noclear=0;
	}

	function removeAssetFromLightboxLink_onClick(asset)
	{
      	noclear=1;
		if (Lightbox.getSelectedId() != null)
        {
        	Lightbox.removeItem(Lightbox.getSelectedId(), asset,
		   		function()
		   		{
		   			if (Lightbox.isPreviewSelected())
		   			{
			        	Lightbox.showPreview(Lightbox.getSelectedId(),
			    			function()
			    			{
								Lightbox.showPreviewPanel();
			    			}
			        	);
		   			}

		   			if ($('lightbox_name') != null)
					{
						$('lightbox_name').onchange();
					}
		   		}
        	);
		}
		noclear=0;
	}

	function changeBasketIcon_Event(status, item, src, title)
	{
		if (typeof in_basket != 'undefined' && in_basket['grid_item_' + item] != null)
		{
			if ($('basket_icon_' + item) != null)
			{
				$('basket_icon_' + item).src = src;
				$('basket_icon_' + item).title = title;
			}

			in_basket['grid_item_' + item] = status;
		}
	}

	function changeLightboxIcon_Event(status, asset, src, title)
	{
		if (typeof in_lightbox != 'undefined' && in_lightbox['grid_item_' + asset] != null)
		{
			if ($('lb_icon_' + asset) != null)
			{
				$('lb_icon_' + asset).src = src;
				$('lb_icon_' + asset).title = title;
			}

			in_lightbox['grid_item_' + asset] = status;
		}
	}

	function directAssetDownload_onClick(asset)
	{
		noclear=1;
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=asset&action=do_direct_download&asset=' + asset;
			document.location = url;
		}
		noclear=0;
	}

	function subcriptionDownload_onClick(asset)
	{
		noclear=1;
		Asset.checkSubscriptionDownload(asset,
			// on success action
			function()
			{
				url = '?service=asset&action=do_subscription_download&asset=' + asset;
				document.location = url;			
			},
			//
			// on failure action
			function()
			{
				Asset.showAssetSubscriptionDownloadNAWindow('en',
					function()
					{
						Asset.closeAssetSubscriptionDownloadNAWindow();
					}	
				)
			}
			//
		);
		noclear=0;
	}
		
	function searchAssetKeyword_onClick(form, search_button, reset_button)
	{
		for (i = 0; i < $('assetKeywordsForm').length; i++)
		{
			element = $('assetKeywordsForm')[i];

			if (typeof element != 'undefined' && element.checked)
			{
				$('searchButton').disabled = false;
				$('resetButton').disabled = false;

				return true;
			}
		}

		$('searchButton').disabled = true;
		$('resetButton').disabled = true;

		return false;
	}

	function searchAssetKeywords_onClick(language)
	{
		var keywords = new Array();

		for (i = 0; i < $('assetKeywordsForm').length; i++)
		{
			element = $('assetKeywordsForm')[i];

			if (typeof element != 'undefined' && element.checked)
			{
				keywords.push(element.value);
			}
		}

		if (keywords.length > 0)
		{
			Asset.searchAssetKeywords(language, keywords);
		}
	}

	function zoomWindowLoadNavigationPanel(asset)
	{
		for (i = 0; i < item_list.length; i++)
		{
			if (item_list[i] == asset)
			{
				$('imageNumberInput').value = i + 1;

				break;
			}
		}

		$('totalImagesSpan').innerHTML = item_list.length;
	}

	function zoomWindowNavigationInput_onChange()
	{
		if (isNaN($('imageNumberInput').value))
		{
			$('imageNumberInput').value = 1;
		}

		if ($('imageNumberInput').value < 1)
		{
			$('imageNumberInput').value = 1;
		}

		if ($('imageNumberInput').value > item_list.length)
		{
			$('imageNumberInput').value = item_list.length;
		}

		Asset.zoomPopup(item_list[$('imageNumberInput').value - 1], asset_location);
	}

	function zoomWindowNavigationFirst_onClick()
	{
		Asset.zoomPopup(item_list[0], asset_location);
	}

	function zoomWindowNavigationPrev_onClick(asset)
	{
		if (item_list[0] == asset)
		{
			Asset.zoomPopup(item_list[item_list.length - 1], asset_location);
		}
		else
		{
			for (i = 0; i < item_list.length; i++)
			{
				if (item_list[i] == asset)
				{
					Asset.zoomPopup(item_list[i - 1], asset_location);
				}
			}
		}
	}

	function zoomWindowNavigationNext_onClick(asset)
	{
		if (item_list[item_list.length - 1] == asset)
		{
			Asset.zoomPopup(item_list[0], asset_location);
		}
		else
		{
			for (i = 0; i < item_list.length; i++)
			{
				if (item_list[i] == asset)
				{
					Asset.zoomPopup(item_list[i + 1], asset_location);
				}
			}
		}
	}

	function zoomWindowNavigationLast_onClick()
	{
		Asset.zoomPopup(item_list[item_list.length - 1], asset_location);
	}



function User()
{
	// *** VARS ***
	
	this.language = null;
	this.isLoggedIn = false;
	//
	
	// *** METHODS ***
	
	this.setLanguage = function(language)
	{
		this.language = language;
	}
	
	this.enableAutozoom = function()
	{
		url = '?service=user&action=do_enable_autozoom';
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			}
		});
	}
	
	this.disableAutozoom = function()
	{
		url = '?service=user&action=do_disable_autozoom';
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			}
		});
	}
	
	this.collapseContainer = function()
	{
		url = '?service=user&action=do_collapse_container';
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			}		
		});		
	}
	
	this.expandContainer = function()
	{
		url = '?service=user&action=do_expand_container';
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			}		
		});		
	}
	
	this.showPasswordChangedWindow = function(on_OK_button_action)
	{
		url = '?service=user&action=show_password_changed_window&language=' + this.language;
		new Ajax.Updater('passwordChangedWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('passwordChangedWindow', on_OK_button_action);
			}
		});
	}
	
	this.closePasswordChangedWindow = function()
	{
		hideBox('passwordChangedWindow');
	}
	
	this.showMessageList = function(language, page)
	{
		url = '?service=user&action=show_message_list&language=' + language + '&page=' + page;
		new Ajax.Updater('message_list', url, {method: 'get', asynchronous:true, evalScripts:true});
	}
	
	//added invoice list .. sharayu
	
	this.showInvoiceList = function(language, page)
	{
		url = '?service=user&action=show_invoice_list&language=' + language + '&page=' + page;
		new Ajax.Updater('invoice_list', url, {method: 'get', asynchronous:false, evalScripts:true});
	}
	
	//invoice list ended.. sharayu
	

	this.showLogoutWarningWindow = function(on_login_button_action, on_continue_button_action)
	{
		url = '?service=user&action=show_logout_warning_window&app_mode=no_session&language=' + this.language;
		new Ajax.Updater('logoutWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('logoutWarningWindow', on_login_button_action, on_continue_button_action);
			}
		});
	}
	
	this.closeLogoutWarningWindow = function()
	{
		hideBox('logoutWarningWindow');
	}
	
	this.showMessageWarningWindow = function(on_OK_button_action)
	{
		url = '?service=user&action=show_message_warning_window&language=' + this.language;
		new Ajax.Updater('messageWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('messageWarningWindow', on_OK_button_action);
			}
		});
	}
	
	this.closeMessageWarningWindow = function()
	{
		hideBox('messageWarningWindow');
	}
	
	this.checkStatus = function(client_login)
	{
		if (client_login == false)
		{
			return false;
		}

		url = '?service=user&action=do_check_status&app_mode=no_session&client_login=' + client_login;
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (response_code == 'LGT')
				{
					clearInterval(t);
					
					User.showLogoutWarningWindow(
						// on login again
						function()
						{
							document.location = '?service=user&action=show_login_page';
						},
						//
						// on continue
						function()
						{
							User.closeLogoutWarningWindow();
							document.location.reload();
						}
						//
					);
				}
				else if (response_code == 'MSG')
				{
					User.showMessageWarningWindow(
						// OK
						function()
						{
							User.closeMessageWarningWindow();
						}
						//
					);		
				}
			}
		});
	}
	
	this.prepareGBPostCode = function(postcode)
	{
		postcode = postcode.replace(/ /, '');
		
		if (postcode.length >= 5 && postcode.length <= 7)
		{
			postcode = postcode.substr(0, postcode.length - 3) + ' ' + postcode.substr(postcode.length - 3, postcode.length);
		}
		
		postcode = postcode.toUpperCase();
		
		return postcode;
	}	
	//
	
	// *** EVENTS ***
	this.startCheckStatus = function(client_login)
	{
	   this.isLoggedIn = client_login;
    	t = setInterval("User.checkStatus(" + client_login + ");", 10000);
	}
	//
}

// *** OBJECT ***

var User = new User();

//



function autoZoomCheckBox_onClick(checked)
{
	if (checked)
	{
		User.enableAutozoom();
		Asset.enableAutoZoom();
		myArray = $$('.autoZoomCheckbox');
		myArray.each(function(item) {
		item.checked=true;
		});

	}
	else
	{
		$A($$('.autozoom')).each(function(el){el.setStyle({display:'none'});});
		User.disableAutozoom();
		Asset.disableAutoZoom();
		myArray = $$('.autoZoomCheckbox');
		myArray.each(function(item) {
		item.checked=false;
		});
	}
}

function autoZoomEnabled_onLoad()
{
	if ($('autoZoomCheckbox') != null)
	{
		$('autoZoomCheckbox').checked = true;
	myArray = $$('.autoZoomCheckbox');
		myArray.each(function(item) {
		item.checked=true;
		});
	
		Asset.enableAutoZoom();
	}
}

function onPasswordChanged(language)
{
	User.setLanguage(language);
	User.showPasswordChangedWindow(
		function()
		{
			User.closePasswordChangedWindow();
		}
	);
}

function rightClickMessage() {
		var sText ="This photograph is the photographer's property." + "\n"
		sText=sText + "It is protected by USA & international copyright laws." + "\n"
		sText=sText + "Reproduction & copying requires written permission." + "\n"
		sText=sText + "Please contact Science Faction / Jewel Box Images for information" + "\n"
		sText=sText + "about licensing photos for your specific needs:" + "\n"
		sText=sText + "e-mail sales@sciencefaction.com or call +1.206.232.2300"
		alert(sText); 
		return false;
	}
	


function Basket()
{
	// *** VARS ***

	this.language = null;
	this.previewSelected = false;
    this.Timer1 = null;
	//

	/*** INIT ***/

	this.init = function()
	{
		this.id = null;
		this.name = null;
	}

	this.initPreviewPanel = function(basket, on_complete_action)
	{
		var object = this;
        try{
		this.showPreviewPanel(basket,
			function()
			{
				$('basket-preview-panel-selector').onchange =
					function()
					{
						object.initPreviewPanel(this.value);
						$('basket-selected-id').value = this.value;
					};

				$('basket-preview-panel-action-selector').onchange =
					function()
					{
						switch (this.value)
						{
							case 'checkout':
							case 'display':

								object.showBasketPage(basket);

							break;
							case 'notes':
  								object.showNotesWindow(Basket.getBasketId(),function(){Basket.note(Basket.getBasketId(), $('basketRenameWindowInput').value, 											function() {Basket.closeNotesWindow();});},function() {Basket.closeNotesWindow();});                    							
							break;
							case 'create':

								object.showCreateWindow(
									function()
									{
										object.create($('basketCreateWindowInput').value,
											function(basket)
											{
												object.closeCreateWindow();
												object.initPreviewPanel(basket);
											}
										);
									},
									function()
									{
										object.closeCreateWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'rename':

								object.showRenameWindow(Basket.getBasketId(),
									function()
									{
										object.rename(basket, $('basketRenameWindowInput').value,
											function()
											{
												object.closeRenameWindow();
												object.initPreviewPanel(object.getBasketId());
											}
										);
									},
									function()
									{
										object.closeRenameWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'delete':

								object.showDeleteWindow(object.getBasketId(),
									function()
									{
										object._delete(object.getBasketId(),
											function()
											{
												object.closeDeleteWindow();
												object.resetSeletor();
											}
										);
									},
									function()
									{
										object.closeDeleteWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'empty':

								object.showEmptyWindow(object.getBasketId(),
									function()
									{
										object.empty(object.getBasketId(),
											function()
											{
												object.closeEmptyWindow();
												object.initPreviewPanel(object.getBasketId());
											}
										);
									},
									function()
									{
										object.closeEmptyWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'print':
								object.showPrintOptionsWindow(
									function()
									{
                                        object.initPrintOptionsWindow();
									},
									function()
									{
										var parameters = $('layout-selector').value.split('|');

										object.showPrintPage(object.getBasketId(), parameters[0]);
										object.closePrintOptionsWindow();
										object.resetActionSeletor();                                        
									},
									function()
									{
										object.closePrintOptionsWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'duplicate':

								object.showDuplicateWindow(object.getBasketId(),
									function()
									{
										object.duplicate(object.getBasketId(), $('basketDuplicateWindowInput').value,
											function(basket)
											{
												object.closeDuplicateWindow();
												object.initPreviewPanel(basket);
											}
										);
									},
									function()
									{
										object.closeDuplicateWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'd_download':
								object.resetActionSeletor();
								object.direct_download();
								break;

							case 'c_download':

								object.resetActionSeletor();
								object.comp_download();
							break;
						}
					};

					$('basket-preview-panel-lightbox-selector').onclick =
						function()
						{
							Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
								function()
								{
									Lightbox.enableSlider();
									Lightbox.show();
									object.hide();
									if($('basket-maximize').style.display == 'none') {
										Lightbox.maximize();
									}
										else {
										Lightbox.minimize();
									}
								}
							);

							return false;
						};

					if ($('similars-preview-panel-content') && $('basket-similars_count')) {
						$('basket-similars_count').innerHTML = 'Similars ('+Similars.countSimilars()+')';
					}
					$('basket-preview-panel-similars-selector').onclick = 
						function()
						{
						setCookie('simPan','1','31');
							// TODO: similars JS
							if (!$('similars-preview-panel-content')) {
								Similars.initPreviewPanel(0,
									function()
									{
										Similars.enableSlider();
										Similars.show();
										object.hide();
									}
								);
							}
							else {
								Similars.enableSlider();
								Similars.show();
								object.hide();
							}
							return false;
						};

					$('basket-minimize').onclick =
						function()
						{
							object.minimize();
						};

					$('basket-maximize').onclick =
						function()
						{
							object.maximize();
						};
					$('basket-checkout').onclick=
						function(){
							object.showBasketPage(basket);
						};
                    
                    // add actions for sorting basket overlay elements
					Sortable.create('basket-preview-panel-content',
					{
						tag: 'div', 
                        overlap: 'horizontal', 
                        constraint: false, 
                        'ghosting':true, 
                        'ghostOpacity':'0',
                        onUpdate: function(el)
						{
							object.reSortItems(object.getBasketId());
                        },
                        onDrop: function()
                        {
                            // onDrop function added to scriptaculous library by Chris
                            // used to reset styles for currently dragging element
                            // drag functionality alters CSS in an unfavourable way, so put this back again
                             $$('#basket-preview-panel-content div.placeholder').each(function(el){
                                el.setStyle({"top":"0","left":"0"});
                             });
                        },
                        starteffect: function()
                        {
                            // don't want a panel hover, but there could be one already. Override
                            $('basket-preview-panel-content').addClassName("panel_hover_override");
                        },
                        endeffect: function()
                        {
                            // remove panel hover override
                            $('basket-preview-panel-content').removeClassName("panel_hover_override");
                        }
                        
					});

					$('basket-preview-panel-content').onclick = function(e) {
					    var target = e ? e.target : window.event.srcElement;
					    if (target.nodeName.toLowerCase() !== 'a' && target.nodeName.toLowerCase() !== 'img') {
							$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
								function(element)
								{
									if (Element.hasClassName(element, 'thumbnail-selected'))
									{
										Element.removeClassName(element, 'thumbnail-selected');
									}
								}
							);
						}
					}

					$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
						function(element)
						{
							if (Element.hasClassName(element, 'thumbnail'))
							{
								element.onclick = function()
								{
									if (Element.hasClassName(element, 'thumbnail-selected'))
									{
										Element.removeClassName(element, 'thumbnail-selected');
									}
									else
									{
										Element.addClassName(element, 'thumbnail-selected');										
									}
								}
								
								element.ondblclick = function()
								{
									Asset.zoomPopup(object.getObjectId(element), '', '', '', object.getItemId(element));
								}
							}
						}
					);

					$A($('basket-preview-panel-content').getElementsByTagName('a')).each(
						function(element)
						{
							if (element.name == 'basket-preview-panel-content-menu-remove')
							{
								element.onclick = function()
								{
									var assets = [];
									$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
										function(imgEl)
										{
											if (Element.hasClassName(imgEl, 'thumbnail-selected') && object.getItemId(element) != object.getItemId(imgEl))
											{
												assets[assets.length] = object.getItemId(imgEl);
											}
										}
									);
								
									assets[assets.length] = [object.getItemId(element)];

									object.removeAssets(object.getBasketId(), assets,
										function()
										{
											object.initPreviewPanel(object.getBasketId());
											Basket.changeGridIcon(false, object.getItemType(element), object.getObjectId(element), 'images/icons/Cart78.gif');
										}
									);
								}
							}
							if (element.name == 'basket-preview-panel-content-menu-add-basket')
							{
								element.onclick = function()
								{
									var assets = [object.getObjectId(element)];

									object.addAssetToBasket(object.getBasketId(), assets,
										function()
										{
											object.initPreviewPanel(object.getBasketId());
										}
									);
								}
							}
						}
					);

					$A($('mainContent').getElementsByTagName('img')).each(
						function(element)
						{
							if (Element.hasClassName(element, 'imageDraggable-disabled'))
							{
                                // making the images draggable. Some functionality has been implemented
                                // manually, to ensure dragged item can be displayed outside #mainContent.
                                
                                // disable native drag-drop browser functionality in IE
                                element.ondragstart = function(e) {  
                                    return false;  
                                } 
                                
                                // stores the distance from the top left corner of the dragged image to
                                // the mouse coords.
                                
                                var cornerToCursorX = 0;
                                var cornerToCursorY = 0;
                                
                                // make the Draggable object, and override appropriate methods.
                                
                                new Draggable(element.id, {revert:false,
                                onStart: function(d,e){
                                        // Draggable moves the actual image in the DOM.
                                        // This is a problem when inside a scrolling container, as
                                        // the draggable element is not visible outside the scroll.
                                        
                                        // the solution is to overlay a div #drag, which exists in the
                                        // body element, and mirrors the native image.
                                        
                                        // make the new drag image and insert
                                        var dummy = element.clone();
                                        $(dummy).setStyle({'position':'static',top:0,left:0});
                                        $('drag').setStyle({'display':'none'}).insert(dummy);
                                        
                                        // determine distance between mouse coords and top left of image
                                        // This means we can position in future based on mouse coords alone
                                        
                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        var offset = $(element).cumulativeOffset();
                                        cornerToCursorX = Event.pointerX(e) - (offset.left - scrollOffset.left + parseInt(element.getStyle('border-left-width').replace(/px$/,'')));
                                        cornerToCursorY = Event.pointerY(e) - (offset.top - scrollOffset.top + parseInt(element.getStyle('border-top-width').replace(/px$/,'')));     
                                        // position and show for the first time (same as onDrag)
                                        
                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        newTop = Event.pointerY(e) - cornerToCursorY;
                                        newLeft = Event.pointerX(e) - cornerToCursorX;
                                        $('drag').setStyle({'top':newTop+'px'});
                                        $('drag').setStyle({'left':newLeft+'px'});
                                    },
                                    onDrag: function(d,e){
                                        // move the drag image over the native one.
                                        // Can calculate position of image from mouse coords
                                        
                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        newTop = Event.pointerY(e);// - cornerToCursorY;
                                        newLeft = Event.pointerX(e);// - cornerToCursorX;
                                        $('drag').setStyle({'top':newTop+'px'});
                                        $('drag').setStyle({'left':newLeft+'px'});
                                    },
                                 
			                        onEnd: function(){
                                        // put everything back the way it was before the drag
                                        
			                            element.style.display = '';
			                        	element.style.top = "auto";
			                       		element.style.bottom = "auto";  // will be changed to 0px in a moment
			                        	element.style.left = "0px";
                                        
                                        // Due to bug in Safari 4, need to set bottom property once and 
                                        // then again to actually make the change render to the page.
                                        // For this a very short timeout is set, and repeated to take slower
                                        // browsers into account.
                                        it1 = setInterval(function(){element.style.bottom = "0px";},1);
                                        setTimeout(function(){clearInterval(it1);},50);
                                        
                                        // delete the drag image but keep the container
                                        $$('#drag img').each(function(node){node.remove();});
			                        },
                                    
                                    starteffect: function(element){
                                        // hide the native image and show the drag image
                                        // note: display:none doesn't work as need to know offsets etc
                                        
                                        $('drag').setOpacity('0.7').setStyle({'display':'block'});
                                        Draggable._dragging[element] = true;
                                        element.setOpacity('0');
                                    },
                                    
                                    endeffect: function(element){
                                        // hide the drag image and show the native one again
                                        
                                        element.setOpacity('1');
                                        new Effect.Opacity($('drag'), {duration:0.2, from:0.7, to:0,
                                          queue: {scope:'_draggable', position:'end'},
                                          afterFinish: function(){
                                            Draggable._dragging[element] = false
                                          }
                                        });
                                    }
								});
							}						  
							/*if (Element.hasClassName (element, 'imageDraggable'))
							{
								new Draggable(element.id, {revert:false,  
			                        onEnd: function(){
			                        	element.style.top = "auto";
			                       		element.style.bottom = "0px";
			                        	element.style.left = "0px";
			                        	element.style.position = "absolute";
			                        }	                        
								});
							}*/
						}
					);



					var addBack = false;
					if ($('basket-preview-panel-item-sequence-2').checked)
					{
						addBack = true;
					}
					object.updateIcons(addBack);
					
					Droppables.add('basket-preview-panel-content', { hoverclass: 'panel_hover', onDrop:
						function(element)
						{
							if (!Element.hasClassName(element, 'imageDraggable'))
							{
								return false;
							}

							var sequence = Basket.getSequence();

							var type = Basket.getItemType(element);

							if (type == 'F')
							{
								Basket.addFeature(Basket.getBasketId(), Basket.getObjectId(element), sequence,
									function()
									{
										object.initPreviewPanel(object.getBasketId());
									}
								);
							}
							else if (type == 'C')
							{
								Basket.addCd(Basket.getBasketId(), Basket.getObjectId(element), sequence,
									function()
									{
										object.initPreviewPanel(object.getBasketId());
									}
								);
							} else {
								if(element.hasClassName('clicked2')){
									Basket.tsrt='';
									$$('.clicked2').each(function(el,index){
										if(el!=element){
											if(Basket.tsrt == ''){
												Basket.tsrt += Basket.getObjectId(el);
											}else{
												Basket.tsrt +=',' + Basket.getObjectId(el);									
											}	
																		
											el.removeClassName('clicked');
											el.removeClassName('clicked2');	
										}

									});
									Basket.addMultiAsset(Basket.getBasketId(), Basket.tsrt, sequence,function(){
										Basket.initPreviewPanel(object.getBasketId(),
											function() {
												Basket.enableSlider();
												Basket.show();
												Lightbox.hide();
											}
										);
									});

								}else{
									Basket.addAsset(Basket.getBasketId(), Basket.getObjectId(element), sequence,
										function() {
											object.initPreviewPanel(object.getBasketId(),
												function() {
													Basket.enableSlider();
													Basket.show();
													Lightbox.hide();
												}
											);
										}
									);
								}
							}

							Basket.changeGridIcon(true, Basket.getItemType(element), Basket.getObjectId(element), 'images/icons/cartd79.gif');
                            element.style.top = 'auto';
						}
					});

					if (on_complete_action) 
					{
						on_complete_action();
					}
					
			}
		);
        }
                catch(err){}
	}
    
    this.updateTotals = function() {
        // updates the values of the lightbox overlay based on other panels' values e.g. "Similars (0)"
        // grabs values from the panels themselves to avoid ajax call
        
        var numSimilars = null;
        if($('numSimilars')) numSimilars = $('numSimilars');
        if($('basket-similars_count'))
        {
            $('basket-similars_count').innerHTML = 'Similars ('+numSimilars.innerHTML+')';
        }
    }
    
	var tsrt='';
	this.updateIcons = function(addBack)
	{
	   
       // reset lightbox icon state to unselected, and make selected based on lightbox content
		object = this;
		
		var iconUrl = 'images/icons/Cart78.gif';
		var selectedUrl =  'images/icons/cartd79.gif';
        
        // resets all icons to the default, unselected icon
        var type = null;
        var id = null;
        var currentlyInBasket = [];
        
        // reset every icon
        
        $jq("#mainContent a.basketLink img").each(function()
        {
            
            this.src = iconUrl;
        });
        
        // get references of icons in grid that are in lightbox
        $jq('#basket-preview-panel-content img.thumbnail').each(function(){
            // get the id data
            id = this.id.replace(/basket-content-image_[0-9]{0,}/,"");
            
            // can't just get by id as there are duplicate IDs, so do a search
            var basketItems = $jq("#grid-item"+id).parents(".pictureBox").find(".basketLink img");
            basketItems.each(function(){
               this.src=selectedUrl;
            });
            
        });
        /*
	    try{
    		object = this;
    		
    		var iconUrl = 'images/icons/Cart78.gif';
    		
    		$A($('mainContent').getElementsByTagName('a')).each(
    			function(element)
    			{
    				if(Element.hasClassName (element, 'basketLink'))
    				{
    					object.changeGridIcon(false, object.getItemType(element), object.getObjectId(element), iconUrl);
    				}
    			}
    		);
    
    		if ($('basket-preview-panel-content')) {
    			$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
    				function(element)
    				{
    					if (Element.hasClassName (element, 'thumbnail'))
    					{
    						object.changeGridIcon(true, object.getItemType(element), object.getObjectId(element), 'images/icons/cartd79.gif');
    						object.changePreviewIcon(true, object.getItemType(element), object.getObjectId(element), 'images/icons/cartd79.gif');
    					}
    				}
    			);
    		}
        }
        catch(err){}
        */
		
	}
	
	this.initContentPage = function(basket,onCompleteAction)
	{
       try{
		var object = this;
		this.showContentPage(basket,
			function()
			{
			 
				$A(document.getElementsByTagName('a')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'basketRemoveIcon'))
						{
							element.onclick = function()
							{
								object.removeItem(object.getBasketId(), object.getItemId(element),
								function()
									{
										object.initContentPage(object.getBasketId());
									}
								);
							}
						}

						if (Element.hasClassName(element, 'basketApplyUsageToAll'))
						{
						  
							element.onclick = function()
							{
								object.applyUsageToAll(object.getBasketId(), object.getItemId(element),
									function()
									{
										object.initContentPage(object.getBasketId());
									}
								);
							}
						}
  
  						if (Element.hasClassName(element, 'basketApplyUsageToSelected'))
						{
						 
							element.onclick = function()
							{
								object.applyUsageToSelected(object.getBasketId(), object.getItemId(element),
									function()
									{
										object.initContentPage(object.getBasketId());
									}
								);
							}
						}                                             
                        
		              if (Element.hasClassName(element, 'basketZoomIcon'))
						{
							element.onclick = function()
							{
								Asset.zoomPopup(object.getObjectId(element),'basket', '', '', object.getItemId(element));  // now sends "basket" location [CB]
							}
						}
                        
					}
				);



				$A(document.getElementsByTagName('img')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'basketThumbnail'))
						{
							element.ondblclick = function()
							{
								Asset.zoomPopup(object.getObjectId(element),'basket', '', '', object.getItemId(element));  // now sends "basket" location [CB]
							}
						}
					}
				);

				$A(document.getElementsByTagName('select')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'downloadSizeSelector'))
						{
							element.onchange = function()
							{
								object.setDownloadSize(object.getBasketId(), object.getItemId(element), this.value,
									function()
									{
										object.includeItem(object.getBasketId(), object.getItemId(element), '1',
											function()
											{
												object.initContentPage(object.getBasketId());
											}
										);
									}
								);
							}
						}
					}
				);

				$A(document.getElementsByTagName('input')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'includeItem'))
						{
							element.onclick = function()
							{
								var value = (element.checked) ? 1 : 0;
								
								object.includeItem(object.getBasketId(), object.getItemId(element), value,
									function()
									{
										object.initContentPage(object.getBasketId());
									}
								);
							}
						}
					}
				);
				

                

				if($('direct-download-button')) {
					$('direct-download-button').onclick = 
						function()
						{
							object.direct_download();
						}
				}

				$('basket-empty-button-1').onclick =
					function()
					{
						object.showEmptyWindow(object.getBasketId(),
							function()
							{
								object.empty(object.getBasketId(),
									function()
									{
										object.closeEmptyWindow();
										object.initContentPage(object.getBasketId());
									}
								);
							},
							function()
							{
								object.closeEmptyWindow();
							}
						);
					}

				$('basket-empty-button-2').onclick = $('basket-empty-button-1').onclick;
				
				$('basket-proceed-step-1-button-1').onclick =
					function()
					{
						result = object.checkUsage(
							object.getBasketId(),
							function()
							{
								object.initDeliveryMethodPage();
                                $('topContent').scrollTo();
                                
							},
							function()
							{
					        	object.showContentErrorWindow(
					        		function()
					        		{
					        			object.closeContentErrorWindow();
					        		}
					        	);
							}
						);
					}
                    
					$('basket-proceed-step-1-button-2').onclick = $('basket-proceed-step-1-button-1').onclick;
                    if($('include-all-in-checkout-button')) {
					$('include-all-in-checkout-button').onclick = 
						function()
						{
							object.includeAllInCheckout(object.getBasketId(), 1, 
                                function()
                                {
                                    object.initContentPage(object.getBasketId());
                                }
                            );
						}
                    }
                    
                    if($('include-none-in-checkout-button')) {
					$('include-none-in-checkout-button').onclick = 
						function()
						{
							object.includeAllInCheckout(object.getBasketId(), 0, 
                                function()
                                {
                                    object.initContentPage(object.getBasketId());
                                }
                            );
						}
                    }
			},onCompleteAction
		);
        
        }
        catch(err){}
	}
    
    this.includeAllInCheckout = function(basket_id, value, on_complete_action){
        url = '?service=basket&action=include_all_in_checkout&basket='+basket_id+'&value='+value;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
    }
    
    this.disableUpdateButtons = function()
    {
        // disable the "update" and "add to lightbox" buttons
        var updateButton = $('btnUpdate');
        var addToLightboxButton = $('btnLightbox');
        if(updateButton) updateButton.disabled = true;
        if(addToLightboxButton) addToLightboxButton.disabled = true;
    }
    
    this.enableUpdateButtons = function()
    {
        // enable the "update" and "add to lightbox" buttons
        var updateButton = $('btnUpdate');
        var addToLightboxButton = $('btnLightbox');
        if(updateButton) updateButton.disabled = false;
        if(addToLightboxButton) addToLightboxButton.disabled = false;
    }
    
    this.usageDetailsTitleChanged = function(item)
    {
        var object = this;
        var mainWindow = window.top;
	    object.disableUpdateButtons();
        
		object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), mainWindow.Basket.getBasketId(), item,
			function()
			{
				datePickerController.refresh();
                object.enableUpdateButtons();
			}
		);
    }
    
    this.usageDetailsStartDateChanged = function(item)
    {
        var object = this;
        var mainWindow = window.top;
        // change licence end date when start date changes
        
        // disable update buttons
        var alreadyDisabled = false;
        if($('btnUpdate').disabled == true)
        {
            alreadyDisabled = true;
        }
        object.disableUpdateButtons();
        
        // recalculate end date
        if ($('licence_end_' + item) != null) {
        	object.updateLicenceEnd(item,function(){
        	    // enable update buttons, but only if they weren't disabled already
        	    if(!alreadyDisabled) object.enableUpdateButtons();
            });
        }
    }
    
    this.usageDetailsEndDateChanged = function(item)
    {
        var object = this;
        var mainWindow = window.top;
        
        // disable update buttons
        var alreadyDisabled = false;
        if($('btnUpdate').disabled == true)
        {
            alreadyDisabled = true;
        }
        object.disableUpdateButtons();
        
		object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), mainWindow.Basket.getBasketId(), item,
			function()
			{
				datePickerController.refresh();
                if(!alreadyDisabled) object.enableUpdateButtons();
			}
		);
    }

	this.initApplyUsageDetailsForm = function(item,popupWindow)
	{     
        var object = this;
        var mainWindow = window.top;
        if(!popupWindow) popupWindow = window;
        if ($('basket-item-usage-details-validItem_' + item).value == 'true')
        {            
            datePickerController.refresh();      
            /* Project title events */
			if($('project_title_' + item)){
    			$('project_title_' + item).onblur = function()
    			{
                    object.usageDetailsTitleChanged(item);
    			};
			
                $('project_title_' + item).onchange = function()
				{
				    object.usageDetailsTitleChanged(item);
				};          
			}
            
            /* licence start events */
			if($('licence_start_' + item))
            {
    			$('licence_start_' + item).onblur = function()
				{        
					object.usageDetailsStartDateChanged(item);
				};
    		    
    			$('licence_start_' + item).onchange = function()
				{
				   object.usageDetailsStartDateChanged(item);
				};
    		}
            
            /* Licence end events */
            if($('licence_end_' + item))
            {
    			$('licence_end_' + item).onblur = function()
				{
					object.usageDetailsEndDateChanged(item);
				};
					
                $('licence_end_' + item).onchange = function()
				{
                    object.usageDetailsEndDateChanged(item);
				};   
			}			
		}		
		
	    /* Events for the whole container */
		$('basket-item-usage-details-container_' + item).onblur = function()
		{
			/*object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), mainWindow.Basket.getBasketId(), item,
				function()
				{
					datePickerController.refresh();
				}
			);*/
		};
				
  		$('basket-item-usage-details-container_' + item).onchange = function()
		{
            // date picker event can be captured just with the text field's onchange, so this isn't needed
			/*object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), mainWindow.Basket.getBasketId(), item,
				function()
				{
					datePickerController.refresh();
				}
			);*/
		};
           
        /* Usage details button events */   
		if ($('basket-item-usage-details-button_' + item) != null)
		{        
			$('basket-item-usage-details-button_' + item).onclick = function()
			{
				object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), mainWindow.Basket.getBasketId(), item,
					function()
					{
						datePickerController.refresh();
					}
				);
			};
        }
        
        /* Usage details all button events */
		if ($('basket-item-usage-details-all-button_' + item) != null)
		{
			$('basket-item-usage-details-all-button_' + item).onclick = function()
			{
				if (confirm('Are you sure you want to override existing details?')) {
					object.applyUsageDetailsToAll(mainWindow.Basket.getBasketId(), item,
						function()
						{
							object.initContentPage(mainWindow.Basket.getBasketId());
						}
					);
				}
			};
		}
        
        /* Usage details selected button events */			       
		if ($('basket-item-usage-details-selected-button_' + item) != null)
		{
			$('basket-item-usage-details-selected-button_' + item).onclick = function()
			{
				object.applyUsageDetailsToSelected(mainWindow.Basket.getBasketId(), item,
					function()
					{
						object.initContentPage(mainWindow.Basket.getBasketId());
					}
				);
			};
		}
				
	}

	this.updateLicenceEnd = function(item,on_complete_action)
	{
	  
	   var object = this;
		url = '?service=basket&action=get_basket_item_usage_duration&basket=' + Basket.getBasketId() + '&item=' + item;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,onComplete: on_complete_action,
			onSuccess: function(transport)
			{
                var period;
                var duration;
                // can't always get basket item usage details if it's not actually in the basket yet
 
                    // get from select menu instead
                    var durationSelect = $('ctl00_ContentPlaceHolder1_lstDuration');
                    var durationString = durationSelect.options[durationSelect.selectedIndex].text;
                    
                    // determine values
                    period = durationString.match(/(day|week|month|year)/i)[0];
                    duration = durationString.match(/[0-9]{1,}/)[0];
                    if(duration === null || period === null) return;
                    
                    // format
                    period = period.toLowerCase();
                    duration = parseInt(duration);
                
				var currDate = $('licence_start_' + item).value;
				if(currDate==""){
					var dateObj = new Date();
					currDate = dateObj.getDate()+'/'+(dateObj.getMonth()+1)+'/'+dateObj.getFullYear();
				}
				
				var dateSections = currDate.split('/');
				var year = new Number(dateSections[2]);
				var month = new Number(dateSections[1]);
				var day = new Number(dateSections[0]);
				if ($('licence_start_' + currBasketItemId).hasClassName('format-d-m-y')) {
					month = new Number(dateSections[1]);
					day = new Number(dateSections[0]);
				}
				var dt_obj = new Date(year, month-1, day);
				var timeUTC = Date.UTC(year,month-1,day,0,0,0,0);
                
				switch(period) {
					case 'year':
						//year += parseInt(duration);
						timeUTC+=new Number(duration)*60*60*24*1000*365;
						break;
					case 'month':
						//month += parseInt(duration);
						timeUTC+=new Number(duration)*60*60*24*1000*30;
						break;
					case 'week':
						//day += (parseInt(duration) * 7);
						timeUTC+=new Number(duration)*60*60*24*1000*7;
						break;
					case 'day':
                    
						//day += parseInt(duration);
						timeUTC+=new Number(duration)*60*60*24*1000;
                        
						break;
				}
				//var dt_obj = new Date(year, month-1, day);
				var dt_obj = new Date();
				dt_obj.setTime(timeUTC);			
				year = dt_obj.getFullYear();

				month = dt_obj.getMonth() + 1;
				if (month < 10) {month = '0'+month;}

				day = dt_obj.getDate();
				if (day < 10) {day = '0'+day;}
				
				var newDate = day+'/'+ month+'/'+year;
                

				if ($('licence_start_' + currBasketItemId).hasClassName('format-d-m-y')) {
					newDate = day+'/'+month+'/'+year;
				}
                
				$('licence_end_' + item).value = newDate;
				object.applyUsageDetails($('basket-item-usage-details-form_' + item), $('basket-item-usage-details-container_' + item), object.getBasketId(), item,
					function()
					{
						datePickerController.refresh();
					}
				);
			}
		});
	}

	this.initDeliveryMethodPage = function()
	{
		var object = this;

		this.showDeliveryMethodForm(
			function()
			{
				for (i = 0; i < $('delivery-method-form').length; i++)
				{
					var element = $('delivery-method-form').delivery_method[i];

					if (typeof element != 'undefined' && element.type == 'radio')
					{
						if (element.value == $('basket-selected-delivery-method-id').value)
						{
							element.checked = true;
						}
					}
				}

				$('basket-content-page-link').onclick =
					function()
					{
						Basket.initContentPage(null);
					}

				$('basket-back-step-2-button-1').onclick =
					function()
					{
						object.initContentPage(null);
					}

				$('basket-back-step-2-button-2').onclick = $('basket-back-step-2-button-1').onclick;

				$('basket-proceed-step-2-button-1').onclick =
					function()
					{
						var delivery_method = null;

						var method_count = $('delivery-method-form').length;

						if (method_count > 1)
						{
							for (i = 0; i < method_count; i++)
							{
								element = $('delivery-method-form').delivery_method[i];

								if (typeof element != 'undefined' && element.type == 'radio')
								{
									if (element.checked)
									{
										delivery_method = element.value;
									}
								}
							}
						}
						else if (method_count == 1)
						{
							element = $('delivery-method-form').delivery_method;

							if (typeof element != 'undefined' && element.type == 'radio')
							{
								if (element.checked)
								{
									delivery_method = element.value;
								}
							}
						}

						result = Basket.saveDeliveryMethod(delivery_method,
							function()
							{
								Basket.showDeliveryDetailForm(
									function()
									{
										object.initDeliveryDetailPage();
                                        $('topContent').scrollTo();
									}
								);
							},
							function()
							{
					        	Basket.showDeliveryMethodErrorWindow(
					        		function()
					        		{
					        			Basket.closeDeliveryMethodErrorWindow();
					        		}
					        	);
							}
						);
					}

				$('basket-proceed-step-2-button-2').onclick = $('basket-proceed-step-2-button-1').onclick;
			}
		);
	}

	this.initDeliveryDetailPage = function()
	{
		var object = this;

		this.showDeliveryDetailForm(
			function()
			{
				$('basket-content-page-link').onclick =
					function()
					{
						object.initContentPage(null);
					}

				$('basket-delivery-method-page-link').onclick =
					function()
					{
						object.initDeliveryMethodPage();
					}

				$('basket-back-step-3-button-1').onclick =
					function()
					{
						object.initDeliveryMethodPage();
					}

				$('basket-back-step-3-button-2').onclick = $('basket-back-step-3-button-1').onclick;



				$('basket-create-billing-address-link').onclick =
					function()
					{
						object.showAddressCreateWindow(
							function()
							{
								result = Basket.createBillingAddress(
									function()
									{
										object.closeAddressCreateWindow();
										object.showBillingAddress();

										$('basket-billing-address-checkbox').checked = false;
									},
									function()
									{
										object.showAddressErrors();
									}
								);
							},
							function()
							{
								object.closeAddressCreateWindow();
							}
						);
					}

				if ($('basket-create-shipping-address-link') != null)
				{
					$('basket-create-shipping-address-link').onclick =
						function()
						{
							object.showAddressCreateWindow(
								function()
								{
									result = Basket.createShippingAddress(
										function()
										{
											object.closeAddressCreateWindow();
											object.showShippingAddress();

											$('basket-shipping-address-checkbox').checked = false;
										},
										function()
										{
											object.showAddressErrors();
										}
									);
								},
								function()
								{
									object.closeAddressCreateWindow();
								}
							);
						}
				}

				$('basket-proceed-step-3-button-1').onclick =
					function()
					{
						var delivery_name;
						var delivery_notes;

						if ($('delivery_name'))
						{
							delivery_name = $('delivery_name').value;
						}

						if ($('delivery_notes'))
						{
							delivery_notes = $('delivery_notes').value;
						}

						result = object.saveDeliveryDetails(delivery_name, delivery_notes,
							function()
							{
								object.initConfirmationPage();
                                $('topContent').scrollTo();
							},
							function()
							{
	        					object.showDeliveryDetailsErrorWindow(
	        						function()
	        						{
	        							object.closeDeliveryDetailsErrorWindow();
	        						}
	        					);
							}
						);
					}

				$('basket-proceed-step-3-button-2').onclick = $('basket-proceed-step-3-button-1').onclick;
			}
		);
	}

	this.direct_download = function() {
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=basket&action=do_direct_download&basket=' + this.getBasketId();
			document.location = url;
		}
	}
	
	this.comp_download = function() {
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=basket&action=do_comp_download&basket=' + this.getBasketId();
			document.location = url;
		}
	}

	this.initConfirmationPage = function()
	{
		var object = this;

		object.showConfirmDetails(
			function()
			{
				$('basket-content-page-link').onclick =
					function()
					{
						object.initContentPage(null);
					}

				$('basket-delivery-method-page-link').onclick =
					function()
					{
						object.initDeliveryMethodPage();
					}

				$('basket-delivery-detail-page-link').onclick =
					function()
					{
						object.initDeliveryDetailPage();
					}

				$('basket-back-step-4-button-1').onclick =
					function()
					{
						object.initDeliveryDetailPage();
					}

				$A(document.getElementsByTagName('img')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'basketThumbnail'))
						{
							element.ondblclick = function()
							{
								Asset.zoomPopup(object.getObjectId(element));
							}
						}
					}
				);

				$A(document.getElementsByTagName('a')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'basketZoomIcon'))
						{
							element.onclick = function()
							{
								Asset.zoomPopup(object.getObjectId(element));
							}
						}
					}
				);

				$('basket-back-step-4-button-2').onclick = $('basket-back-step-4-button-1').onclick;

				$('basket-quote-button-1').onclick =
					function()
					{
						object.showQuoteConfirmationWindow(
							function()
							{
								object.closeQuoteConfirmationWindow();
								object.doOrderQuote(
									function()
									{
										object.showQuoteCompletedPage();
									}
								);
							},
							function()
							{
								object.closeQuoteConfirmationWindow();
							}
						);
					}

					$('basket-quote-button-2').onclick = $('basket-quote-button-1').onclick;

				$('basket-invoice-button-1').onclick =
					function()
					{
						object.showInvoiceConfirmationWindow(
							function()
							{
								object.closeInvoiceConfirmationWindow();

								result = object.doOrderInvoice(
									function()
									{
										object.showInvoiceCompletedPage();
									},
									function()
									{
										object.showCreditRefusedWarningWindow(
											function()
	        								{
	        									object.closeCreditRefusedWarningWindow();
	        								}
	        							);
									},
									function()
									{
										object.showCreditCheckErrorWindow(
											function()
	        								{
	        									object.closeCreditCheckErrorWindow();
	        								}
	        							);
									}
								);
							},
							function()
							{
								object.closeInvoiceConfirmationWindow();
							}
						);

					}

				$('basket-invoice-button-2').onclick = $('basket-invoice-button-1').onclick;
			}
		)
	}

	this.initPrintOptionsWindow = function()
	{
		$('layout-selector').onchange =
			function()
			{
				var parameters = this.value.split('|');
				$('layout-image').src = parameters[1];
			}
		$('layout-selector').onchange();
	}

	this.initOrderPage = function(page)
	{
		var object = this;
        try{
		Basket.showOrderList(page,
			function()
			{
				$A(document.getElementsByTagName('input')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'orderDownloadButton'))
						{
							element.onclick = function()
							{
								url = '?service=basket&action=do_download&order=' + object.getOrderId(element);

								document.location = url;
							}
						}

						if (Element.hasClassName(element, 'basketFTPUploadButton'))
						{
							element.onclick = function()
							{
								result = object.checkPreviousFTPUploads(
									function()
									{
										object.showFTPUploadWindow(object.getOrderId(element),
											function()
											{
												result = object.doFTPUpload(
													function()
													{
														object.closeFTPUploadWindow();

								                        object.showFTPUploadStatusWindow(object.getOrderId(element),
								                            function()
								                            {
								                                object.closeFTPUploadStatusWindow();
								                            }
								                        );
													},
													function()
													{
														object.showFTPUploadFormErrors();
													}
												);
											},
											function()
											{
												object.closeFTPUploadWindow();
											}
										);
									},
									function()
									{
	        							object.showFTPUploadWarningWindow(
	        								function()
	        								{
	        									object.closeFTPUploadWarningWindow();
	        								}
	        							);
									}
								);
							}
						}
					}
				);

				$A(document.getElementsByTagName('a')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'orderItemsButton'))
						{
							element.onclick = function()
							{
								object.showOrderItemWindow(object.getOrderId(element),
									function()
									{
										object.closeOrderItemWindow();
									}
								);
							}
						}

						if (Element.hasClassName(element, 'basketFTPStatusLink'))
						{
							element.onclick = function()
							{
								object.showFTPUploadStatusWindow(object.getOrderId(element),
        							function()
        							{
        								object.closeFTPUploadStatusWindow();
        							}
        						);
        					}
        				}
					}
				);
			}
		);
        }
                catch(err){}
	}

	this.initQuotePage = function(page)
	{
		var object = this;
        try{
		Basket.showQuoteList(page,
			function()
			{
				$A(document.getElementsByTagName('a')).each(
					function(element)
					{
						if (Element.hasClassName(element, 'quoteItemsButton'))
						{
							element.onclick = function()
							{
								object.showQuoteItemWindow(object.getQuoteId(element),
									function()
									{
										object.closeQuoteItemWindow();
									}
								);
							}
						}
					}
				);
			}
		);
        }
                catch(err){}
	}

	// *** METHODS ***

	this.setLanguage = function(language)
	{
		this.language = language;
	}

	this.resetSeletor = function()
	{
		if($('basket-preview-panel-selector')){
        $('basket-preview-panel-selector').selectedIndex = 0;
		$('basket-preview-panel-selector').onchange();
        }
	}

	this.resetActionSeletor = function()
	{
		$('basket-preview-panel-action-selector').selectedIndex = 0;
	}

	this.getBasketId = function()
	{
		try{
			x = $('basket-selected-id').value;
		}catch(e){
			x =-1;
		}
		return x;
	}

	this.getItemId = function(element)
	{
		var chunks = element.id.split('_');

		return chunks[chunks.length - 3];
	}

	this.getItemType = function(element)
	{
		var chunks = element.id.split('_');

		return chunks[chunks.length - 2];
	}

	this.getObjectId = function(element)
	{
		var objectId = 0;
		if (element.getAttribute('assetid'))
		{
			objectId = element.getAttribute('assetid');
		}
		else
		{
			var chunks = element.id.split('_');
			objectId = chunks[chunks.length - 1];
		}
		return objectId;
	}

	this.getOrderId = function(element)
	{
		var chunks = element.id.split('_');

		return chunks[chunks.length - 1];
	}

	this.getQuoteId = function(element)
	{
		var chunks = element.id.split('_');

		return chunks[chunks.length - 1];
	}

	this.getSequence = function()
	{
		var sequence_element = document.getElementsByName('basket-preview-panel-item-sequence');

		for (var i = 0; i < sequence_element.length; i++)
		{
			if (sequence_element[i].checked)
			{
				return sequence_element[i].value;
			}
		}

		return null;
	}

	this.isPreviewSelected = function()
	{
		return this.previewSelected;
	}

	this.show = function()
	{
		try{Lightbox.hide();}catch(e){}
		
		this.previewSelected = true;

		$('basket-preview-panel').style.display = '';
	}

	this.hide = function()
	{
		this.previewSelected = false;

		if($('basket-preview-panel')) {$('basket-preview-panel').style.display = 'none';}
	}

	this.enableSlider = function(value)
	{
		var myWidth = 600;
		var myHeight = 141;
		if (parseInt(navigator.appVersion)>3) {
			if (navigator.appName=="Netscape") {
				myWidth = window.innerWidth;
			}
			if (navigator.appName.indexOf("Microsoft")!=-1) {
				myWidth = document.body.offsetWidth;
			}
		}
		myWidth=myWidth-14;
		
		$('pull-tab').style.width = (myWidth) + 'px';
            var delta=25;
            if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
            }
            

            if($('pull-tab').getWidth() != myWidth){
                //$('pull-tab').style.left = ((myWidth-$('pull-tab').getWidth()) / 2) + 'px'; 
              $('pull-tab').style.bottom = delta - parseInt(7) + 'px';   
            }
            
            if ($('basket-container')) {
                if($('basket-maximize').style.display=="none")
                {
                    // only adjust basket height if it's not minimized
                 	$('basket-container').style.height = myHeight + delta + 'px';
                	$('basket-preview-panel-content').style.height = 115 + delta + 'px';
                }
            }
			if ($('lightbox-container')) {
                if($('lightbox-maximize').style.display=="none")
                {
                    // only adjust lightbox height if it's not minimized
                    $('lightbox-container').style.height = myHeight + delta + 'px';
                    $('lightbox-preview-panel-content').style.height = 115 + delta + 'px';
                }
			} 
            if ($('similars-container')) {
                if($('similars-maximize').style.display=="none")
                {
                    // only adjust similars height if it's not minimized
                    $('similars-container').style.height = myHeight + delta + 'px';
                    $('similars-preview-panel-content').style.height = 115 + delta + 'px';
                }
			} 
          
		var slider = new Control.Slider('pull-tab', 'pull-track', {
			 axis: 'vertical',
			 range: $R(0, 100),
      		 sliderValue: 100,
			 onSlide: function(value)
			 {
			 	var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
                CookieHandler.setCookie('delta', delta,'31');
              
				if ($('basket-container')) {
				 	$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 114 + delta + 'px';
				}
				if ($('lightbox-container')) {
				 	$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 114 + delta + 'px';
				}
                if($('similars-container')) {
				 	$('similars-container').style.height = myHeight + delta + 'px';
					$('similars-preview-panel-content').style.height = 114 + delta + 'px';
				}
			},
			onChange:function()
			{
				var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
                CookieHandler.setCookie('delta', delta,'31');
				
				if($('lightbox-container')) {
					$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 114 + delta + 'px';
				}
				if($('basket-container')) {
					$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 114 + delta + 'px';
				}
                if($('similars-container')) {
					$('similars-container').style.height = myHeight + delta + 'px';
					$('similars-preview-panel-content').style.height = 114 + delta + 'px';
				}
				
			}
		});

		if (value != null)
		{
			slider.setValue(value);
		}
		
		if($('basket-maximize').style.display == 'none') {
			setTimeout(function(){
				var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
				CookieHandler.setCookie('delta', delta,'31');
				if($('lightbox-container')) {
					$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 111 + delta + 'px';
				}
				if($('basket-container')) {
					$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 111 + delta + 'px';
				}
			},10);		
		}     
        $('pull-tab').style.top = (parseInt($('pull-tab').style.top.replace(/px$/,"")) - delta+6) + 'px';  
        
	}

	this.minimize = function(on_complete_action)
	{
	   setCookie('maximized','1','31');
		$('basket-preview-panel-content').style.display = 'none';
		$('basket-container').style.height = '29px';
		setTimeout(function(){$('basket-container').style.height = '29px';},50);
		
		$('pull-tab').style.bottom = '-110px';
		$('pull-tab').style.top = '';
        $('pull-tab').style.backgroundPosition = 'left';
		$('basket-minimize').style.display = 'none';
		$('basket-maximize').style.display = '';
		$('pull-tab').style.display = 'none';

		url = '?service=user&action=do_collapse_container';

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	   setCookie("maximized",'0','31');
    }

	this.maximize = function(on_complete_action)
	{
       var delta;
       var myHeight = 122;
	   if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
       } else {
            delta = 140-myHeight; 
       }
		$('basket-preview-panel-content').style.display = '';
		$('basket-container').style.height = myHeight + delta + 'px';
		//$('pull-tab').style.bottom = '0px';
		//$('pull-tab').style.top = '';
	
    $('pull-tab').style.backgroundPosition = 'center center';
		$('basket-maximize').style.display = 'none';
		$('basket-minimize').style.display = '';
		$('pull-tab').style.display = 'block';

		url = '?service=user&action=do_expand_container';

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	   setCookie('maximized','1','31');
       this.enableSlider(); 
       }

	this.create = function(name, on_success_action)
	{
		url = '?service=basket&action=do_create&name=' + encodeURIComponent(name);

		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "null")
				{
					alert("Please enter a basket name");
				}
				else
				{
					on_success_action(result);
				}

				return result;
			}
		});
	}

	this.rename = function(basket, name, on_complete_action)
	{
		url = '?service=basket&action=do_rename&basket=' + basket + '&name=' + encodeURIComponent(name);

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.note = function(basket, name, on_complete_action)
	{
		url = '?service=basket&action=do_notes&basket=' + basket + '&note=' + encodeURIComponent(name);

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this._delete = function(basket, on_complete_action)
	{
		url = '?service=basket&action=do_delete&basket=' + basket;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});

        this.resetSeletor();
	}

	this.addAsset = function(basket, asset, sequence, on_complete_action)
	{
		url = '?service=basket&action=do_add_asset&basket=' + basket + '&asset=' + asset + '&sequence=' + sequence;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	}

	this.addMultiAsset = function(basket, asset, sequence, on_complete_action)
	{
		url = '?service=basket&action=do_add_asset&multi=1&basket=' + basket + '&asset=' + asset + '&sequence=' + sequence;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	}
	
	this.addFeature = function(basket, feature, sequence, on_complete_action)
	{
		url = '?service=basket&action=do_add_feature&basket=' + basket + '&feature=' + feature + '&sequence=' + sequence;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	}

	this.addCd = function(basket, cd, sequence, on_complete_action)
	{
		url = '?service=basket&action=do_add_cd&basket=' + basket + '&cd=' + cd + '&sequence=' + sequence;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	}

	this.removeItem = function(basket, item, on_complete_action)
	{
		url = '?service=basket&action=do_remove_item&basket=' + basket + '&item=' + item;

		new Ajax.Request(url, {method: 'get', asynchronous:false, onComplete: on_complete_action});
	}

	this.removeAssets = function(basket, assets, on_complete_action)
	{
		for (var i = 0; i < assets.length; i++)
		{
			object.removeItem(basket, assets[i], false);
		}
		
		if (on_complete_action) 
		{
			on_complete_action();
		}
	}

	this.empty = function(basket, on_complete_action)
	{
		url = '?service=basket&action=do_empty&basket=' + basket;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.reSortItems = function(basket, on_complete_action)
	{
		params = Sortable.serialize('basket-preview-panel-content');

		url = '?service=basket&action=do_resort_items&basket=' + basket;

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.duplicate = function(basket, name, on_success_action)
	{
		url = '?service=basket&action=do_duplicate&basket=' + basket + '&name=' + encodeURIComponent(name);

		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "null")
				{
					alert("Please enter a basket name");
				}
				else
				{
					on_success_action(result);
				}

				return result;
			}
		});
	}

	this.showContentPage = function(basket, on_complete_action)
	{
		if(basket){
            url = '?service=basket&action=show_content&basket=' + basket;
        }else{
            url = '?service=basket&action=show_content';
            
        }
		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}
	
	this.showDirectPaymentPage = function(alias,on_complete_action)
	{
		url = '?service=basket&action=show_direct_payment_page&language=' + this.language + '&alias=' + alias;
		

		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}
	
	this.doDirectPayment = function(alias,on_complete_action)
	{
		url = '?service=basket&action=do_direct_payment_transaction&alias=' + alias;
		data = $('directPaymentForm').serialize(true);
		new Ajax.Updater('mainContent', url, {method: 'post',parameters: data, asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}


	this.applyUsage = function(basket, item, usage_code, ms_menus, pack_code, ps_menus, on_complete_action)
	{
		var basket = basket;
		var item = item;
		var language = this.language;
        url = '?service=basket&action=do_apply_usage&basket=' + basket + '&item=' + item + '&usage_code=' + usage_code + '&ms_menus=' + ms_menus + '&pack_code=' + pack_code + '&ps_menus=' + ps_menus;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
				
			},
			onComplete:on_complete_action
		});
	}
	this.applyUsageSelected = function(basket, item, usage_code, ms_menus, pack_code, ps_menus, on_complete_action)
	{
		url = '?service=basket&action=do_apply_usage_selected&basket=' + basket + '&item=' + item + '&usage_code=' + usage_code + '&ms_menus=' + ms_menus + '&pack_code=' + pack_code + '&ps_menus=' + ps_menus;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}
	this.applyUsageToAll = function(basket, item, on_complete_action,updateBefore)
	{
	   // don't always want to update the usage details. Add flag to preserve existing code
	   if(updateBefore === null) updateBefore = true;
       if(updateBefore) this.applyUsageDetails('basket-item-usage-details-form_'+item,'basket-item-usage-details-container_'+item,basket,item);
		url = '?service=basket&action=do_apply_usage_to_all&basket=' + basket + '&item=' + item;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}
	this.applyUsageToSelected = function(basket, item, on_complete_action,updateBefore)
	{
	   // don't always want to update the usage details. Add flag to preserve existing code
	   if(updateBefore === null) updateBefore = true;
       
	   if(updateBefore) this.applyUsageDetails('basket-item-usage-details-form_'+item,'basket-item-usage-details-container_'+item,basket,item);
		url = '?service=basket&action=do_apply_usage_to_selected&basket=' + basket + '&item=' + item;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}
	this.applyUsageDetails = function(form, container, basket, item, on_complete_action, updateContainer)
	{
	   if(updateContainer != false) updateContainer = true;    // updateContainer defaults to true
       
		params = Form.serialize(form);
		url = '?service=basket&action=do_apply_usage_details&language=' + this.language + '&basket=' + basket + '&item=' + item;
		if(updateContainer == false)
        {
            // don't update the container
            new Ajax.Request(url, {
                method: 'post', 
                asynchronous: true, 
                evalScripts:true, 
                parameters: params, 
                onComplete: on_complete_action
            });
        }
        else
        {
            // update the container with the new values
            new Ajax.Updater(container, url, {
                method: 'post', 
                asynchronous: true, 
                evalScripts:true, 
                parameters: params, 
                onComplete: on_complete_action
            });
        }
    }

	this.applyUsageDetailsToAll = function(basket, item, on_complete_action,updateBefore)
	{
		// don't always want to update the usage details. Add flag to preserve existing code
	   if(updateBefore == null) updateBefore = true;
       
       if(updateBefore) this.applyUsageDetails('basket-item-usage-details-form_'+item,'basket-item-usage-details-container_'+item,basket,item);
        url = '?service=basket&action=do_apply_usage_details_to_all&basket=' + basket + '&item=' + item;
		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}
	this.applyUsageDetailsToSelected = function(basket, item, on_complete_action)
	{
        var temp ='-1';
        $A(document.getElementsByClassName("itemCheck")).each(function(el){
           if(el.checked) {
                temp=temp + ',' +el.value;
           }
        });      
        url = '?service=basket&action=do_apply_usage_details_to_selected&basket=' + basket + '&item=' + item + '&items=' + temp;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}
	this.applyCoupon = function(code, on_success_action, on_failure_action)
	{
		url = '?service=basket&action=do_apply_coupon&code=' + code;

		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.setDownloadSize = function(basket, item, download_size, on_complete_action)
	{
		var basket = basket;
		var item = item;
		var language = this.language;
		
		url = '?service=basket&action=do_set_download_size&basket=' + basket + '&item=' + item + '&download_size=' + download_size;
		new Ajax.Request(url, {method: 'get', asynchronous:true, 
			onSuccess: function(transport)
			{
				
			},
			onComplete:on_complete_action});
	}

	this.includeItem = function(basket, item, value, on_complete_action)
	{
		url = '?service=basket&action=do_include_item&basket=' + basket + '&item=' + item + '&value=' + value;
		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}

	this.checkUsage = function(basket, on_success_action, on_failure_action)
	{
		url = '?service=basket&action=do_check_usage&basket=' + basket;

		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					//on_success_action();
                    on_failure_action();
				}

				return result;
			}
		});
	}

	this.showPreviewPanel = function(basket, on_complete_action)
	{
		url = '?service=basket&action=show_preview_panel&basket=' + basket + '&sequence=' + Basket.getSequence();
		setTimeout(function(){
			$('basket-preview-panel').style.display='';
			try{Lightbox.hide();}catch(e){}
		},100);

		new Ajax.Updater('basket-preview-panel', url, {method: 'get', asynchronous:false, evalScripts:true, onComplete:on_complete_action});
		Basket.enableSlider();
	}

	this.hidePreviewPanel = function()
	{
		$('basket-preview-panel').innerHTML = '';
	}

	this.changeGridIcon = function(status, type, id, src)
	{
		var src=src;
		$$('#basket-icon_' + type + '_' + id).each(
        function(el){
			if (browser.isIE && browser.version == 6) {
				img = new Image();
				img.id = el.id;
				img.src = src;
				img.oSrc = src;
				el.replaceNode(img);
			} else {
                el.src = src;
                el.oSrc = src;
			}
        });
  	}

	this.changePreviewIcon = function(status, type, id, src)
	{
		var src=src;
		$$('#lightbox-preview-panel-content-menu-add-basket-icon' + '_' + id).each(
        function(el){
			if (browser.isIE && browser.version == 6) {
				img = new Image();
				img.id = el.id;
				img.src = src;
				el.replaceNode(img);
			} else {
                el.src = src;
			}
        });
  	}

	this.showCreateWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_create_window&language=' + this.language;

		new Ajax.Updater('basketCreateWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketCreateWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeCreateWindow = function()
	{
        		hideBox('basketCreateWindow');
	}

	this.showRenameWindow = function(basket, on_OK_button_action, on_CANCEL_button_action)
	{
 		url = '?service=basket&action=show_rename_window&language=' + this.language + '&basket=' + basket;

		new Ajax.Updater('basketRenameWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketRenameWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}
	this.showNotesWindow = function(basket, on_OK_button_action, on_CANCEL_button_action)
	{
 		url = '?service=basket&action=show_notes_window&language=' + this.language + '&basket=' + basket;

		new Ajax.Updater('basketRenameWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketRenameWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}
	this.closeRenameWindow = function()
	{
		hideBox('basketRenameWindow');
	}
	this.closeNotesWindow = function()
	{
		hideBox('basketRenameWindow');
	}
	this.showDeleteWindow = function(basket, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_delete_window&language=' + this.language + '&basket=' + basket;

		new Ajax.Updater('basketDeleteWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketDeleteWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeDeleteWindow = function()
	{
	   hideBox('basketDeleteWindow');

	}

	this.showEmptyWindow = function(basket, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_empty_window&language=' + this.language + '&basket=' + basket;

		new Ajax.Updater('basketEmptyWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketEmptyWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeEmptyWindow = function()
	{
	      hideBox('basketEmptyWindow');
	}

	this.showDuplicateWindow = function(basket, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_duplicate_window&language=' + this.language + '&basket=' + basket;

		new Ajax.Updater('basketDuplicateWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketDuplicateWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeDuplicateWindow = function()
	{
	   hideBox('basketDuplicateWindow');

	}

	this.showPrintOptionsWindow = function(on_complete_action, on_PRINT_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_print_options_window&language=' + this.language;

		new Ajax.Updater('basketPrintOptionsWindow', url, {method: 'get', onComplete: function() { on_complete_action(); showBox('basketPrintOptionsWindow', on_PRINT_button_action, on_CANCEL_button_action); }, asynchronous:true, evalScripts:true});
	}

	this.closePrintOptionsWindow = function()
	{
	   	   hideBox('basketPrintOptionsWindow');

	}

	this.showPrintPage = function(basket, print_size)
	{
		window.open('?service=basket&action=show_print_page&basket=' + basket + '&print_size=' + print_size, 'basketPrintWindow', 'status=0, toolbar=0, scrollbars=yes');
	}

	this.showUsageDetailsForm = function(container, basket, item, on_complete_action)
	{
		url = '?service=basket&action=show_item_usage_details_form&language=' + this.language + '&basket=' + basket + '&item=' + item;

		new Ajax.Updater(container, url, {method: 'get', asynchronous:true, evalScripts:true, onComplete: function() {if(on_complete_action){on_complete_action();} datePickerController.create();

	if($('inCheckout' + item).checked == true) {
		//if($('project_title_' + item).value == ''){
		//$('labelproject_title' + item).addClassName('error');
		//}
		//if($('licence_start_' + item).value == ''){
		//	$('labellicence_start' + item).addClassName('error');		
		//}
	}		
        generateLicenseCode();
		
		}});
	}

	this.showBasketItemUsageDetails = function(container, basket, item, on_complete_action)
	{
		url = '?service=basket&action=show_basket_item_usage_details&language=' + this.language + '&basket=' + basket + '&item=' + item;
		new Ajax.Updater(container, url, {method: 'get', asynchronous:true, evalScripts:true, onComplete: on_complete_action});
	}

	this.showContentErrorWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_content_error_window&language=' + this.language;

		new Ajax.Updater('basketSpecifyUsageWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketSpecifyUsageWindow', on_OK_button_action);
			}
		});
	}

	this.closeContentErrorWindow = function()
	{
	   	   	   hideBox('basketSpecifyUsageWindow');

	}

	this.showCouponValidWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_coupon_valid_window&language=' + this.language;

		new Ajax.Updater('basketCouponWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketCouponWarningWindow', on_OK_button_action);
			}
		});
	}

	this.closeCouponValidWindow = function()
	{
	   	   	   	   hideBox('basketCouponWarningWindow');
	}

	this.showCouponInvalidWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_coupon_invalid_window&language=' + this.language;

		new Ajax.Updater('basketCouponWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketCouponWarningWindow', on_OK_button_action);
			}
		});
	}

	this.closeCouponInvalidWindow = function()
	{
	   hideBox('basketCouponWarningWindow');
	}

	/* DELIVERY METHOD */

	this.showDeliveryMethodForm = function(on_complete_action)
	{
		url = '?service=basket&action=show_delivery_method_form&language=' + this.language;

		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.saveDeliveryMethod = function(delivery_method, on_success_action, on_failure_action)
	{
		var params = null;

		if (delivery_method != null)
		{
			params = 'delivery_method=' + delivery_method;
		}

		url = '?service=basket&action=do_save_delivery_method';

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters:params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.showDeliveryMethodErrorWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_delivery_method_error_window&language=' + this.language;

		new Ajax.Updater('basketDeliveryMethodErrorWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketDeliveryMethodErrorWindow', on_OK_button_action);
			}
		});
	}

	this.closeDeliveryMethodErrorWindow = function()
	{
	   hideBox('basketDeliveryMethodErrorWindow');
	}

	/* END: DELIVERY METHOD */

	/* DELIVERY DETAILS */

	this.showDeliveryDetailForm = function(on_complete_action)
	{
		url = '?service=basket&action=show_delivery_detail_form&language=' + this.language;

		new Ajax.Updater('delDetails', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.cloneBillingAddress = function(on_complete_action)
	{
		url = '?service=basket&action=do_clone_billing_address';

		new Ajax.Updater('billingAddress', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.clearBillingAddress = function(on_complete_action)
	{
		url = '?service=basket&action=do_clear_billing_address';

		new Ajax.Updater('billingAddress', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.showBillingAddress = function()
	{
		url = '?service=basket&action=show_billing_address&language=' + this.language;

		new Ajax.Updater('billingAddress', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.showAddressCreateWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_address_create_window&language=' + this.language;

		new Ajax.Updater('basketAddressCreateWindow', url, {method: 'get',  asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketAddressCreateWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeAddressCreateWindow = function()
	{
	   hideBox('basketAddressCreateWindow');

	}

	this.createBillingAddress = function(on_success_action, on_failure_action)
	{
		params = Form.serialize('basketAddressCreateWindowForm');

		url = '?service=basket&action=do_create_billing_address&language=' + this.language;

		new Ajax.Request(url, {method: 'post', asynchronous: true, parameters: params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.showAddressErrors = function()
	{
		url = '?service=basket&action=show_address_errors&language=' + this.language;

		new Ajax.Updater('basketAddressCreateErrors', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.cloneShippingAddress = function(on_complete_action)
	{
		url = '?service=basket&action=do_clone_shipping_address';

		new Ajax.Updater('shippingAddress', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.clearShippingAddress = function(on_complete_action)
	{
		url = '?service=basket&action=do_clear_shipping_address';

		new Ajax.Updater('shippingAddress', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.showShippingAddress = function()
	{
		url = '?service=basket&action=show_shipping_address&language=' + this.language;

		new Ajax.Updater('shippingAddress', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.createShippingAddress = function(on_success_action, on_failure_action)
	{
		params = Form.serialize('basketAddressCreateWindowForm');

		url = '?service=basket&action=do_create_shipping_address&language=' + this.language;

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.saveDeliveryDetails = function(delivery_name, delivery_notes, on_success_action, on_failure_action)
	{
		var params = '';

		if (delivery_name != null)
		{
			params += '&delivery_name=' + encodeURIComponent(delivery_name);
		}

		if (delivery_notes != null)
		{
			params += '&delivery_notes=' + encodeURIComponent(delivery_notes);
		}

		url = '?service=basket&action=do_save_delivery_details';

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.showDeliveryDetailsErrorWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_delivery_details_error_window&language=' + this.language;

		new Ajax.Updater('basketDeliveryDetailsErrorWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketDeliveryDetailsErrorWindow', on_OK_button_action);
			}
		});
	}

	this.closeDeliveryDetailsErrorWindow = function()
	{
	   	   hideBox('basketDeliveryDetailsErrorWindow');
	}

	/* END: DELIVERY DETAILS */

	/* CONFIRM DETAILS */

	this.showConfirmDetails = function(on_complete_action)
	{
		url = '?service=basket&action=show_confirm_details&language=' + this.language;

		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.doOrderQuote = function(on_complete_action)
	{
		url = '?service=basket&action=do_order_quote';

		new Ajax.Request(url, {method: 'post', asynchronous: true, onComplete:on_complete_action});
	}

	this.showQuoteConfirmationWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_quote_confirmation_window&language=' + this.language;

		new Ajax.Updater('basketQuoteConfirmationWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketQuoteConfirmationWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeQuoteConfirmationWindow = function()
	{
	   hideBox('basketQuoteConfirmationWindow');
	}

	this.showQuoteCompletedPage = function()
	{
		url = '?service=basket&action=show_quote_completed_page';

		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.doOrderInvoice = function(on_success_action, on_failure_action, on_error_action)
	{
		url = '?service=basket&action=do_order_invoice';

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}
				else if (result == "cc_error")
				{
					on_error_action();
				}

				return result;
			}
		});
	}

	this.showInvoiceConfirmationWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=basket&action=show_invoice_confirmation_window&language=' + this.language;

		new Ajax.Updater('basketInvoiceConfirmationWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketInvoiceConfirmationWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeInvoiceConfirmationWindow = function()
	{
	   hideBox('basketInvoiceConfirmationWindow');
	}

	this.showCreditRefusedWarningWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_credit_refused_warning_window&language=' + this.language;

		new Ajax.Updater('basketCreditRefusedWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketCreditRefusedWarningWindow', on_OK_button_action);
			}
		});
	}

	this.closeCreditRefusedWarningWindow = function()
	{
	   hideBox('basketCreditRefusedWarningWindow');
	}

	this.showCreditCheckErrorWindow = function(on_OK_button_action)
	{
		url = '?service=basket&action=show_credit_check_error_window&language=' + this.language;

		new Ajax.Updater('basketCreditCheckErrorWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketCreditCheckErrorWindow', on_OK_button_action);
			}
		});
	}

	this.closeCreditCheckErrorWindow = function()
	{
	   hideBox('basketCreditCheckErrorWindow');
	}

	this.showInvoiceCompletedPage = function()
	{
		url = '?service=basket&action=show_invoice_completed_page';

		new Ajax.Updater('mainContent', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	/* END: CONFIRM DETAILS */

	/* ORDERS PAGE */

	this.showOrderList = function(page, on_complete_action)
	{
		url = '?service=basket&action=show_order_list&language=' + this.language + '&page=' + page;

		new Ajax.Updater('order_list', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.showOrderItemWindow = function(order, on_OK_button_action)
	{
        showBox('basketOrderItemWindow');
		url = '?service=basket&action=show_order_item_window&language=' + this.language + '&order=' + order;

		new Ajax.Updater('basketOrderItemWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketOrderItemWindow', on_OK_button_action,null,null,true);
			}
		});
	}
	this.showOrderItemWindow2 = function(order, on_OK_button_action)
	{
		$('basketOrderItemWindow').style.display = '';

		url = '?inv=yes&service=basket&action=show_order_item_window&language=' + this.language + '&order=' + order;

		new Ajax.Updater('basketOrderItemWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketOrderItemWindow', on_OK_button_action);
			}
		});
	}

	this.showOrderItemWindow2Inv = function(order, on_OK_button_action)
	{
		$('basketOrderItemWindow').style.display = '';

		url = '?inv=yes&service=basket&action=show_order_item_window&language=' + this.language + '&invoice=' + order;

		new Ajax.Updater('basketOrderItemWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketOrderItemWindow', on_OK_button_action);
			}
		});
	}
	
	
	
	
	this.closeOrderItemWindow = function()
	{
	      hideBox('basketOrderItemWindow');

	}

	this.showOrderItemUsageDetails = function(container, item, on_complete_action)
	{
		url = '?service=basket&action=show_order_item_usage_details&language=' + this.language + '&item=' + item;

		new Ajax.Updater(container, url, {method: 'get', asynchronous:true, evalScripts:true, onComplete: on_complete_action});
	}

	/* ORDERS PAGE */

	/* QUOTES PAGE */

	this.showQuoteList = function(page, on_complete_action)
	{
		url = '?service=basket&action=show_quote_list&language=' + this.language + '&page=' + page;

		new Ajax.Updater('quote_list', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	this.showQuoteItemWindow = function(quote, on_OK_button_action)
	{
		$('basketQuoteItemWindow').style.display = '';

		url = '?service=basket&action=show_quote_item_window&language=' + this.language + '&quote=' + quote;

		new Ajax.Updater('basketQuoteItemWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketQuoteItemWindow', on_OK_button_action);
			}
		});
	}

	this.closeQuoteItemWindow = function()
	{
	   	      hideBox('basketQuoteItemWindow');
	}

	this.showQuoteItemUsageDetails = function(container, item, on_complete_action)
	{
		url = '?service=basket&action=show_quote_item_usage_details&language=' + this.language + '&item=' + item;

		new Ajax.Updater(container, url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:on_complete_action});
	}

	/* END: QUOTES PAGE */

	/* FTP UPLOAD */

	this.showFTPUploadWindow = function(order, on_OK_button_click, on_CANCEL_button_click)
	{
		url = '?service=basket&action=show_ftp_upload_window&language=' + this.language + '&order=' + order;

		new Ajax.Updater('basketFTPUploadWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketFTPUploadWindow', on_OK_button_click, on_CANCEL_button_click);
			}
		});
	}

	this.closeFTPUploadWindow = function()
	{
	   hideBox('basketFTPUploadWindow');
	}

	this.doFTPUpload = function(on_success_action, on_failure_action)
	{
		params = Form.serialize('basketFTPUploadWindowForm');

		url = '?service=basket&action=do_ftp_upload&language=' + this.language;

		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.showFTPUploadFormErrors = function()
	{
		url = '?service=basket&action=show_ftp_upload_form_errors&language=' + this.language;

		new Ajax.Updater('basketFTPUploadFormErrors', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.showFTPUploadStatusWindow = function(order, on_CLOSE_button_click)
	{
		$('basketFTPUploadStatusWindow').style.display = '';

		url = '?service=basket&action=show_ftp_upload_status_window&language=' + this.language + '&order=' + order;

		new Ajax.Updater('basketFTPUploadStatusWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketFTPUploadStatusWindow', on_CLOSE_button_click);
			}
		});
	}

	this.closeFTPUploadStatusWindow = function()
	{
	   hideBox('basketFTPUploadStatusWindow');
	}

	this.checkPreviousFTPUploads = function(on_success_action, on_failure_action)
	{
		url = '?service=basket&action=do_check_previous_ftp_uploads';

		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}

				return result;
			}
		});
	}

	this.showFTPUploadWarningWindow = function(on_OK_button_click)
	{
		url = '?service=basket&action=show_ftp_upload_warning_window&language=' + this.language;

		new Ajax.Updater('basketFTPUploadWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('basketFTPUploadWarningWindow', on_OK_button_click);
			}
		});
	}

	this.closeFTPUploadWarningWindow = function()
	{
	   hideBox('basketFTPUploadWarningWindow');
	}
	
	this.showBasketPage = function(basket)
    {
    	document.location = '?service=basket&action=show_basket_page&language=' + this.language + '&basket=' + basket; 
    }

	

	/* END: FTP UPLOAD */

}

function ZoomPrice()
{
	this.applyItemUsage = function(item, usage_code, ms_menus, pack_code, ps_menus, on_complete_action) 
	{
		if($('basket_id')) {
			Basket.applyUsage($('basket_id').value, item, usage_code, ms_menus);
		}
		if($('lightbox_id')) {
			Lightbox.applyItemUsage($('lightbox_id').value, item, usage_code, ms_menus);
		}
		$('price_item').value = item;
		$('price_usage_code').value = usage_code;
		$('price_ms_menus').value = ms_menus;
		var url = "?service=asset&action=do_calculate_price&usage_code="+usage_code;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				$('price_message').innerHTML = " ("+result+")";
			},			
			onComplete:on_complete_action
		});
	}
}	

function ItemPrice(addToBasketAlert, addToLightboxAlert)
{
    try{
	this.applyItemUsage = function(item, usage_code, ms_menus, pack_code, ps_menus, on_complete_action) 
	{
		on_complete_action();
		if ($('basket-preview-panel-content') && $('lightbox-preview-panel-content')) {
			var inBasket = false;
            var done = false;
			$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
				function(element)
				{
					if (Element.hasClassName (element, 'thumbnail'))
					{
						if(Basket.getObjectId(element) == item) {
						  if(done==false){
							Basket.applyUsage(Basket.getBasketId(), Basket.getItemId(element), usage_code, ms_menus, pack_code, ps_menus, 
								function()
								{
									Basket.initPreviewPanel(Basket.getBasketId());
								}
							);
							inBasket = true;
                            done=true;
                            }
						}
					}
				}
			);

			var inLightbox = false;
			$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
				function(element)
				{
				    
					if (Element.hasClassName (element, 'thumbnail'))
					{
                        if(Lightbox.getObjectId(element) == item) {
                            
							Lightbox.applyItemUsage(Lightbox.getLightboxId(), item, usage_code, ms_menus, pack_code, ps_menus,
								function()
								{
									Lightbox.initPreviewPanel(Lightbox.getLightboxId());
								}
							);
							inLightbox = true;
						}
					}
				}
			);
		}
		
	}
	this.getBasketItemId = function(item) 
	{
		var itemId = -1;
		if ($('basket-preview-panel-content')) {
			$A($('basket-preview-panel-content').getElementsByTagName('img')).each(
				function(element)
				{
					if (Element.hasClassName (element, 'thumbnail'))
					{
						if(Basket.getObjectId(element) == item) {
							itemId = Basket.getItemId(element);
						}
					}
				}
			);
		}
		return itemId;
    }
    }
    catch(err){}
}	



	//----- PREVIEW SCREEN

	function basketPreview_onSelect()
	{
		if ($('preview_selector'))
		{
			$('preview_selector').disabled = true;
		}
			
		Lightbox.hidePreviewPanel();
		Lightbox.hide();

		Basket.showPreview(
			function()
			{
				Basket.showPreviewPanel();				
			}
		);	
	}
	
	function basketSelectedEvent_onLoad()
	{
	    Basket.showPreview(
	    	function()
	    	{
		    	Basket.showPreviewPanel();
	    	}
	    );
	}
		
	function basketPreviewEmptyLink_onClick(language)
	{
		Basket.showEmptyWindow(language,
			function()
			{
				Basket.empty(
					function()
					{
						Basket.closeEmptyWindow();
						Basket.clearGridIcons();
						Basket.showPreview(
							function()
						    {
							   	Basket.showPreviewPanel();
						    }
						);						
					}
				);
			}
		);
	}

	function addFeatureToBasketLink_onClick(feature)
	{
        Basket.addFeature(feature,
        	function()
        	{
		        if (Basket.isPreviewSelected())
		        {
					Basket.showPreview(
						function()
	    				{
		    				Basket.showPreviewPanel();
	    				}
					);	
		        }        		
        	}	
        );
	}

	function removeFromBasketLink_onClick(item)
	{
		Basket.removeItem(item,
			function()
			{
				Basket.showContent();		
			}
		);
	}


	function emptyBasketButton_onClick()
	{
		Basket.showEmptyWindow('eng',
			function()
			{
				Basket.empty(
					function()
					{
						Basket.closeEmptyWindow();
						Basket.showContent();
					}
				);
			}
		);
	}

	function basketCollapseLink_onClick(label)
	{
		Basket.collapse(label);
		User.collapseContainer();
	}

	function basketExpandLink_onClick()
	{
		Basket.expand();
		User.expandContainer();
	}

	//------

	function saveBasketButton_onClick()
	{
		result = Basket.checkUsage(
			// success
			function()
			{
				Basket.showSaveWindow('eng',
					function()
					{
						Basket.save($('basketSaveWindowNameInput').value, $('basketSaveWindowEmptyCheckbox').checked,
							// success
							function()
							{
								Basket.closeSaveWindow();
								Basket.showSaveCompletedWindow('en',
									// ok
									function()
									{
										Basket.closeSaveCompletedWindow();
										Basket.showContent();
									}
									//
								);
							},
							// failure
							function()
							{
								Basket.showSaveWindowErrors('eng');
							}
						);
					}
				);
			},
			// failure
			function()
			{
		       	Basket.showContentErrorWindow('eng',
		       		function()
		       		{
		       			Basket.closeContentErrorWindow();
		       		}
		       	);				
			}
		);
	}
	
	//----- SPECIFY USAGE SCREEN

	function proceedStep1Button_onClick(element)
	{
		result = Basket.checkUsage(
			// success
			function()
			{
				Basket.showDeliveryMethodForm('eng');	
			},
			// failure
			function()
			{
	        	Basket.showContentErrorWindow('eng',
	        		function()
	        		{
	        			Basket.closeContentErrorWindow();
	        		}
	        	);				
			}
		);
	}

	function specifyUsageMSButton_onClick(item, base_type, sub_type)
	{
		window.open('?service=pricebook&action=show_media_selector_page&item=' + item + '&base_type=' + base_type + "&sub_type=" + sub_type, 'usage', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0')
	}

	function specifyUsagePSButton_onClick(item)
	{
		window.open('?service=pricebook&action=show_pack_selector_page&item=' + item, 'usage', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0')
	}

	function editUsageMSButton_onClick(item, base_type, sub_type, usage_code, ms_menus)
	{
		window.open('?service=pricebook&action=show_media_selector_page&item=' + item + '&base_type=' + base_type + "&sub_type=" + sub_type + '&usage_code=' + usage_code + '&ms_menus=' + ms_menus, 'usage', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0')
	}

	function editUsagePSButton_onClick(item, pack_code, ps_menus)
	{
		window.open('?service=pricebook&action=show_pack_detail_page&item=' + item + '&pack_code=' + pack_code + '&ps_menus=' + ps_menus, 'usage', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0')
	}

	function applyUsageToAllButton_onClick(usage_code)
	{
		Basket.applyUsageToAll(usage_code,
			function()
			{
				Basket.showContent();
			}
		);
	}

	function viewItemUsageButtom_onClick(usage_code)
	{
		window.open('?service=pricebook&action=show_usage_view_page&usage_code=' + usage_code, 'usages', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0')
	}

	function directDownloadButton_onClick()
	{
		alert('here');
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=basket&action=do_direct_download';
			document.location = url;
		}
	}

	function downloadButton_onClick(order)
	{
		url = '?service=basket&action=do_download&order=' + order;
		document.location = url;
	}

	function viewOrderItemsButton_onClick(language, order)
	{
		Basket.showOrderItemWindow(language, order,
			function()
			{
				Basket.closeOrderItemWindow();
			}
		);
	}
	function viewOrderItemsButton2_onClick(language, order)
	{
		Basket.showOrderItemWindow2(language, order,
			function()
			{
				Basket.closeOrderItemWindow();
			}
		);
		return false;
	}
	function viewOrderItemsButton2Inv_onClick(language, order)
	{
		Basket.showOrderItemWindow2Inv(language, order,
			function()
			{
				Basket.closeOrderItemWindow();
			}
		);
		return false;
	}	
	function viewQuoteItemsButton_onClick(language, quote)
	{
		Basket.showQuoteItemWindow(language, quote, 
			function()
			{
				Basket.closeQuoteItemWindow();
			}
		);
	}

	function viewSavedBasketItemsButton_onClick(language, saved_basket)
	{
		Basket.showSavedBasketItemWindow(language, saved_basket,
			function()
			{
				Basket.closeSavedBasketItemWindow();
			}
		);
	}
	
	function activateSavedBasket_onClick(language, saved_basket)
	{
		Basket.showActivateConfirmationWindow(language, saved_basket,
			function()
			{
				Basket.closeActivateConfirmationWindow();
				Basket.activateSavedBasket(saved_basket,
					// on complete
					function()
					{
						// ...
					}
				);	
			}
		);
	}
		
	function deleteSavedBasket_onClick(language, saved_basket, page)
	{
		Basket.showDeleteConfirmationWindow(language, saved_basket,
			function()
			{
				Basket.closeDeleteConfirmationWindow();
				Basket.deleteSavedBasket(saved_basket,
					// on complete
					function()
					{
						Basket.showSavedBasketList(language, page);
					}
				);	
			}
		);
	}
		
	//------

	//----- DELIVERY METHOD SCREEN

	function deliveryForm_onLoad(delivery_method)
	{
		for (i = 0; i < $('delivery_method_form').length; i++)
		{
			element = $('delivery_method_form').delivery_method[i];

			if (typeof element != 'undefined' && element.type == 'radio')
			{
				if (element.value == delivery_method)
				{
					element.checked = true;
				}
			}
		}
	}
    
    /*
    function step2ProceedButton_onClick()
	{
		var delivery_method = null;
        formObj=document.getElementById('delivery_method_form');
        e = formObj.childNodes;
        for(i=0;i<e.length;i++)
        {
            if (typeof e[i] != 'undefined' && e[i].type == 'radio')
			{
				if (e[i].checked)
				{
					delivery_method = e[i].value;
				}
			}
            
        }
    */
	function step2ProceedButton_onClick()
	{
		/*var delivery_method = null;

		var method_count = $('delivery_method_form').length;
		
		if (method_count > 1)
		{
			for (i = 0; i < method_count; i++)
			{
				element = $('delivery_method_form').delivery_method[i];
	
				if (typeof element != 'undefined' && element.type == 'radio')
				{
					if (element.checked)
					{
						delivery_method = element.value;
					}
				}
			}
		}
		else if (method_count == 1)
		{
			element = $('delivery_method_form').delivery_method;
			
			if (typeof element != 'undefined' && element.type == 'radio')
			{
				if (element.checked)
				{
					delivery_method = element.value;
				}
			}
		}*/
        var delivery_method = null;
        formObj=document.getElementById('delivery_method_form');
        e = formObj.childNodes;
        for(i=0;i<e.length;i++)
        {
            if (typeof e[i] != 'undefined' && e[i].type == 'radio')
			{
				if (e[i].checked)
				{
					delivery_method = e[i].value;
				}
			}
            
        }

		result = Basket.saveDeliveryMethod(delivery_method,
			// success
			function()
			{
				Basket.showDeliveryDetailForm('eng');
			},
			// failure
			function()
			{
	        	Basket.showDeliveryMethodErrorWindow('eng',
	        		function()
	        		{
	        			Basket.closeDeliveryMethodErrorWindow();
	        		}
	        	);			
			}
		);
	}

	//------

	//----- DELIVERY ADDRESS SCREEN

	function billingAddressCheckbox_onChange(element)
	{
		if (element.checked)
		{
			Basket.cloneBillingAddress(
				// on complete
				function()
				{
					Basket.showBillingAddress('eng');
				}
			);
		}
		else
		{
			Basket.clearBillingAddress(
				// on complete
				function()
				{
					$('billingAddress').innerHTML = '';
				}
			);
		}
	}

	function shippingAddressCheckbox_onChange(element)
	{
		if (element.checked)
		{
			Basket.cloneShippingAddress(
				// on complete
				function()
				{
					Basket.showShippingAddress('eng');
				}			
			);
		}
		else
		{
			Basket.clearShippingAddress(
				// on complete
				function()
				{
					$('shippingAddress').innerHTML = '';
				}			
			);
		}
	}

	function enterBillingAddress_onClick()
	{
		Basket.showAddressCreateWindow('eng',
			function()
			{
				result = Basket.createBillingAddress('eng',
					// success
					function()
					{
						Basket.closeAddressCreateWindow();
						Basket.showBillingAddress('eng');
						$('billingAddressCheckbox').checked = false;				
					},
					// failure
					function()
					{
						Basket.showAddressErrors('eng');
					}
				);
			}
		);
	}

	function enterShippingAddress_onClick()
	{
		Basket.showAddressCreateWindow('eng',
			function()
			{
				result = Basket.createShippingAddress('eng',
					// success
					function()
					{
						Basket.closeAddressCreateWindow();
						Basket.showShippingAddress('eng');
						$('shippingAddressCheckbox').checked = false;					
					},
					// failure
					function()
					{
						Basket.showAddressErrors('eng');
					}
				);
			}
		);
	}

	//----- DELIVERY DETAILS SCREEN

	function step3ProceedButton_onClick()
	{
		var delivery_name;
		var delivery_notes;
		
		if ($('delivery_name'))
		{
			delivery_name = $('delivery_name').value;
		}
		
		if ($('delivery_notes'))
		{
			delivery_notes = $('delivery_notes').value;
		}

		result = Basket.saveDeliveryDetails(delivery_name, delivery_notes,
			// success
			function()
			{
				Basket.showConfirmDetails('eng');
			},
			// failure
			function()
			{
	        	Basket.showDeliveryDetailsErrorWindow('eng',
	        		function()
	        		{
	        			Basket.closeDeliveryDetailsErrorWindow();
	        		}
	        	);	
			}
		);
	}

	//------

	function quoteButton_onClick()
	{
		/*Basket.showQuoteConfirmationWindow('eng',
			function()
			{
				Basket.closeQuoteConfirmationWindow();
				Basket.doOrderQuote(
					function()
					{
						Basket.showQuoteCompletedPage();
					}
				);
			}
		);*/
		Basket.showQuoteConfirmationWindow(
			function()
			{
				Basket.closeQuoteConfirmationWindow();
				Basket.doOrderQuote(
					function()
					{
						Basket.showQuoteCompletedPage();
					}
				);
			},
			function()
			{
				Basket.closeQuoteConfirmationWindow();
			}
		);
	}

	function invoiceButton_onClick()
	{
		/*Basket.showInvoiceConfirmationWindow('eng',
			function()
			{
				Basket.closeInvoiceConfirmationWindow();

				result = Basket.doOrderInvoice(
					// success
					function()
					{
						Basket.showInvoiceCompletedPage();
					},
					// failure
					function()
					{
						Basket.showCreditRefusedWarningWindow('eng',
							function()
	        				{
	        					Basket.closeCreditRefusedWarningWindow();
	        				}
	        			);
					},
					// error
					function()
					{
						Basket.showCreditCheckErrorWindow('eng',
							function()
	        				{
	        					Basket.closeCreditCheckErrorWindow();
	        				}
	        			);					
					}
				);
			}
		);*/
		
		Basket.showInvoiceConfirmationWindow(
			function()
			{
				Basket.closeInvoiceConfirmationWindow();

				result = Basket.doOrderInvoice(
					function()
					{
						Basket.showInvoiceCompletedPage();
					},
					function()
					{
						Basket.showCreditRefusedWarningWindow(
							function()
							{
								Basket.closeCreditRefusedWarningWindow();
							}
						);
					},
					function()
					{
						Basket.showCreditCheckErrorWindow(
							function()
							{
								Basket.closeCreditCheckErrorWindow();
							}
						);
					}
				);
			},
			function()
			{
				Basket.closeInvoiceConfirmationWindow();
			}
		);

	}

	function FTPUploadButton_onClick(order)
	{
		result = Basket.checkPreviousFTPUploads(
			// success
			function()
			{
				Basket.showFTPUploadWindow('eng', order,
					function()
					{
						result = Basket.doFTPUpload('eng',
							// success
							function()
							{
								$('ftpUploadButton').style.display = 'none';
								$('orderPageLink').style.display = '';
		
								Basket.closeFTPUploadWindow();
							},
							// failure
							function()
							{
								Basket.showFTPUploadFormErrors('eng');
							}
						);
					}
				);			
			},
			// failure
			function()
			{
	        	Basket.showFTPUploadWarningWindow('eng',
	        		function()
	        		{
	        			Basket.closeFTPUploadWarningWindow();
	        		}
	        	);			
			}
		);
	}

	function orderPageFTPUploadButton_onClick(order)
	{
		result = Basket.checkPreviousFTPUploads(
			// success
			function()
			{
				Basket.showFTPUploadWindow('eng', order,
					function()
					{
						result = Basket.doFTPUpload('eng',
							// success
							function()
							{
								Basket.closeFTPUploadWindow();
		                        Basket.showFTPUploadStatusWindow('eng', order,
		                            function()
		                            {
		                                Basket.closeFTPUploadStatusWindow();
		                            }
		                        );
							},
							// failure
							function()
							{
								Basket.showFTPUploadFormErrors('eng');
							}							
						);
					}
				);
			},
			// failure
			function()
			{
	        	Basket.showFTPUploadWarningWindow('eng',
	        		function()
	        		{
	        			Basket.closeFTPUploadWarningWindow();
	        		}
	        	);
			}
		);
	}

	function viewStatusLink_onClick(order)
	{
		Basket.showFTPUploadStatusWindow('eng', order,
        	function()
        	{
        		Basket.closeFTPUploadStatusWindow();
        	}
		);
	}
	
	function showUsageDetailsForm(language, container, item)
	{
		Basket.showUsageDetailsForm(language, container, item, 
			function()
			{
				datePickerController.create();
				datePickerController.refresh();
			}
		);
	}
	
	function showBasketItemUsageDetails_onLoad(language, container, item)
	{
		Basket.showBasketItemUsageDetails(language, container, item);
	}
	
	function showOrderItemUsageDetails_onLoad(language, container, item)
	{
		Basket.showOrderItemUsageDetails(language, container, item);
	}
	
	function showQuoteItemUsageDetails_onLoad(language, container, item)
	{
		Basket.showQuoteItemUsageDetails(language, container, item);
	}
	
	function showSavedBasketItemUsageDetails_onLoad(language, container, item)
	{
		Basket.showSavedBasketItemUsageDetails(language, container, item);
	}
	
	function applyUsageDetailsSave_onClick(language, form, container, item)
	{
		Basket.applyUsageDetails(language, form, container, item,
			function()
			{
				datePickerController.refresh();
			}		
		);
	}
	
	function applyUsageDetailsToAllButton_onClick(item)
	{
		Basket.applyUsageDetailsToAll(item,
			function()
			{
				Basket.showContent();
			}
		);
	}
	
	function basketGridIcon_onClick(asset, feature)
	{
		if (typeof in_basket == 'undefined' || typeof browser == 'undefined')
		{
			return false;
		}
		
		if (feature)
		{
			Basket.addFeature(feature,
				function()
				{
					if (Basket.isPreviewSelected())
					{
						Basket.showPreview(
							function()
							{
								Basket.showPreviewPanel();
							}
						);
					}
			        
					Basket.changeGridIcon(true, item, 'images/icons/cartd79.gif');
				}
			);
		}
		else
		{
			Basket.addAsset(Basket.getBasketId(), asset,
				function()
				{
					if (Basket.isPreviewSelected())
					{
						Basket.showPreview(
							function()
							{
								Basket.showPreviewPanel();
							}
						);
					}
					
					Basket.changeGridIcon(true, asset, 'images/icons/cartd79.gif');
				}
			);
		}
		
		Basket.initPreviewPanel(Basket.getBasketId());
		
		if (browser.isIE && browser.version == 6)
		{
			return false;
		}
	}
	
	function removeItemFromBasketLink_onClick(asset, item)
	{
		Basket.removeItem(item,
			function()
			{
				Basket.showPreview(
					function()
	    			{
		    			Basket.showPreviewPanel();
	    			}
				);
				
				Basket.changeGridIcon(false, asset, 'images/icons/Cart78.gif');
			}
		);
	}
	
	function showDirectPaymentPageButton_onClick(alias)
	{
		Basket.showDirectPaymentPage(alias);
	}
	
	function doDirectPayment_onClick(alias){
		Basket.doDirectPayment(alias);
	}
	


function Lightbox()
{
	// *** VARS ***
	
	this.language = null;
    this.gridItems = [];  // items in the search grid
	
	//


	/*** INIT ***/
	
	this.init = function()
	{
		this.id = null;
		this.name = null;
		this.previewSelected = false;
		this.assetList = '';
	}
	
	this.initPreviewPanel = function(lightbox, on_complete_action)
	{
	   
		var object = this;
        
		this.showPreviewPanel(lightbox,
			function()
			{
			 
				$('lightbox-preview-panel-selector').onchange = 
					function()
					{
						object.initPreviewPanel(this.value);
						$('lightbox-selected-id').value = this.value;
					};	
				$('lightbox-preview-panel-action-selector').onchange = 
					function()
					{
						switch (this.value)
						{
							case 'display':
							
								object.showLightboxPage(lightbox);
							
							break;
							
							case 'create':
							
								object.showCreateWindow(
									function()
									{
										object.create($('lightboxCreateWindowInput').value,
											function(lightbox)
											{
												object.closeCreateWindow();
												object.initPreviewPanel(lightbox);
											}
										);
									},
									function()
									{
										object.closeCreateWindow();
										object.resetActionSeletor();
									}
								);
							
							break;
							
							case 'rename':
							
								object.showRenameWindow(Lightbox.getLightboxId(),
									function()
									{
										object.rename(lightbox, $('lightboxRenameWindowInput').value,
											function()
											{
												object.closeRenameWindow();
												object.initPreviewPanel(object.getLightboxId());
											}
										);
									},
									function()
									{
										object.closeRenameWindow();
										object.resetActionSeletor();
									}
								);								
							
							break;
							
							case 'delete':
								
								object.showDeleteWindow(object.getLightboxId(), 
									function() 
									{
										object._delete(object.getLightboxId(),
											function()
											{					
												object.closeDeleteWindow();
												object.resetSeletor();
											}
										);		
									},
									function()
									{
										object.closeDeleteWindow();
										object.resetActionSeletor();
									}
								);
							
							break;

							case 'empty':
							
								object.showEmptyWindow(object.getLightboxId(),
									function() 
									{
										object.empty(object.getLightboxId(),
											function()
											{
												object.closeEmptyWindow();
												object.initPreviewPanel(object.getLightboxId());
                                                								if ($('lightbox_name') != null)
								{
									$('lightbox_name').onchange();
								}
											}
										);
									},
									function()
									{
										object.closeEmptyWindow();
										object.resetActionSeletor();
									}									
								);
							
							break;

							case 'addToBasket':
							
								if ($('basket-preview-panel')) {
									object.showAddToBasketWindow(this.language, object.getLightboxId(),
										function() 
										{
											object.closeAddToBasketWindow();
											var assets = [];
											$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
												function(imgEl)
												{
													if (Element.hasClassName(imgEl, 'thumbnail'))
													{
														assets[assets.length] = object.getObjectId(imgEl);
													}
												}
											);
										
											object.addAssetToBasket(object.getLightboxId(), assets,
												function()
												{
													Basket.initPreviewPanel(Basket.getBasketId(),
														function()
														{
															Basket.enableSlider();
															Basket.show();
															object.hide();
														}
													);
												}
											);
										},
										function()
										{
											object.resetActionSeletor();
											object.closeAddToBasketWindow();
											
										}									
									);
								}
								else {
									url = this.language+'/user/show_login_page.html';
									document.location = url;
								}
							
							break;

							case 'print':

								object.showPrintOptionsWindow(
									function()
									{		
										object.initPrintOptionsWindow();
									},
									function()
									{
										var parameters = $('layout-selector').value.split('|');
										
										object.showPrintPage(object.getLightboxId(), parameters[0]);
										object.closePrintOptionsWindow();
										object.resetActionSeletor();

									},
									function()
									{
										object.closePrintOptionsWindow();
										object.resetActionSeletor();
									}
								);

							break;

							case 'duplicate':
								
								object.showDuplicateWindow(object.getLightboxId(),
									function()
									{
										object.duplicate(object.getLightboxId(), $('lightboxDuplicateWindowInput').value,
											function(lightbox)
											{
												object.closeDuplicateWindow();
												object.initPreviewPanel(lightbox);
											}
										);
									},
									function()
									{			
										object.closeDuplicateWindow();								
										object.resetActionSeletor();
									}
								);
							
							break;
							
							case 'annotate':
								
								object.showLightboxNotesWindow(object.getLightboxId(),
									function()
									{
										object.saveLightboxNotes(object.getLightboxId(), $('lightboxNotesWindowInput').value,
											function()
											{
												object.closeLightboxNotesWindow();
											}
										);
									},
									function()
									{
										object.closeLightboxNotesWindow();
									}
								);
								
								object.resetActionSeletor();
															
							break;
							
							case 'email':
								object.showEmailWindow(object.getLightboxId(),
									function()
									{
										$('lightboxEmailFormErrors').innerHTML = "<span></span>";
										object.email(object.getLightboxId(), 'email', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
										function () {
											alert('Email successfully sent');
											object.closeEmailWindow();
										}, 
										function () {
											object.showEmailFormErrors(this.language);
										});
									},
									function()
									{
										object.closeEmailWindow();
									}
								);
								object.resetActionSeletor();
							break;

							case 'share':
								object.showShareWindow(object.getLightboxId(),
									function()
									{
										$('lightboxEmailFormErrors').innerHTML = "<span></span>";
										object.email(object.getLightboxId(), 'share', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
										function () {
											alert('Email successfully sent');
											object.closeEmailWindow();
										}, 
										function () {
											object.showEmailFormErrors(this.language);
										});
									},
									function()
									{
										object.closeEmailWindow();
									}
								);
								object.resetActionSeletor();
							break;

							case 'd_download':
								object.resetActionSeletor();
								object.direct_download();
							break;

							case 'arrange':
															
								object.resetActionSeletor();
								url = '?service=lightbox&action=show_lightbox_arranger&lightbox=' + object.getLightboxId();
								document.location = url;
								
							break;
							
							case 'c_download':
								object.resetActionSeletor();
								object.comp_download();
							break;
							
							case 'item_select_all':
								$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
									function(element)
									{
										if (Element.hasClassName(element, 'thumbnail'))
										{
											Element.addClassName(element, 'thumbnail-selected');
										}
									}
								);
								
								object.resetActionSeletor();
							
							break;
							
							case 'item_unselect_all':
								$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
									function(element)
									{
										if (Element.hasClassName(element, 'thumbnail-selected'))
										{
											Element.removeClassName(element, 'thumbnail-selected')
										}
									}
								);
								
								object.resetActionSeletor();
							
							break;
							
							case 'item_copy_selected':
								
								var assets = [];

								$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
									function(element)
									{
										if (Element.hasClassName(element, 'thumbnail-selected'))
										{
											assets[assets.length] = object.getObjectId(element);
										}
									}
								);

								object.showCopyMoveWindow(
									function()
									{
										object.copyAssets(object.getLightboxId(), $('lightboxCopyMoveWindowSelector').value, assets,
											function()
											{					
												object.initPreviewPanel($('lightboxCopyMoveWindowSelector').value);
												object.closeCopyMoveWindow();
											}
										);
									},
									function()
									{
										object.closeCopyMoveWindow();
										object.resetActionSeletor();
									}
								);
							
							break;
							
							case 'item_move_selected':
								
								var assets = [];

								$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
									function(element)
									{
										if (Element.hasClassName(element, 'thumbnail-selected'))
										{
											assets[assets.length] = object.getObjectId(element);
										}
									}
								);

								object.showCopyMoveWindow(
									function()
									{
										object.moveAssets(object.getLightboxId(), $('lightboxCopyMoveWindowSelector').value, assets,
											function()
											{					
												object.initPreviewPanel($('lightboxCopyMoveWindowSelector').value);
												object.closeCopyMoveWindow();
											}
										);
									},
									function()
									{
										object.closeCopyMoveWindow();
										object.resetActionSeletor();
									}
								);

							break;
							
							case 'item_remove_selected':
								
								var assets = [];
								
								$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
									function(element)
									{
										if (Element.hasClassName(element, 'thumbnail-selected'))
										{
											assets[assets.length] = object.getObjectId(element);
										}
									}
								);
								
								object.removeAsset(object.getLightboxId(), assets,
									function()
									{
										object.initPreviewPanel(object.getLightboxId());
                                        								if ($('lightbox_name') != null)
								{
									$('lightbox_name').onchange();
								}
									}
								);

							break;
						}
					};

					$('lightbox-preview-panel-basket-selector').onclick = 
						function()
						{
                            if ($('basket-preview-panel')) {
								Basket.initPreviewPanel(Basket.getBasketId(),
									function()
									{
										Basket.enableSlider();
										Basket.show();
										object.hide();
										if($('lightbox-maximize').style.display == 'none') {
											Basket.maximize();
										}
											else {
											Basket.minimize();
										}
									}
								);
							} else {
							 alert('Please login to use this feature');
                            }
							return false;
						};

					if ($('similars-preview-panel-content')) {
						$('lightbox-similars_count').innerHTML = 'Similars ('+Similars.countSimilars()+')';
					}
					$('lightbox-preview-panel-similars-selector').onclick = 
						function()
						{
						setCookie('simPan','1','31');
							// TODO: similars JS
							if (!$('similars-preview-panel-content')) {
								Similars.initPreviewPanel(0,
									function()
									{
										Similars.enableSlider();
										Similars.show();
										object.hide();
									}
								);
							}
							else {
								Similars.enableSlider();
								Similars.show();
								object.hide();
							}
							return false;
						};


					$('lightbox-minimize').onclick = 
						function()
						{
							object.minimize();
							$('pull-tab').style.display = 'none';
						};

					$('lightbox-maximize').onclick = 
						function()
						{
							object.maximize();
							$('pull-tab').style.display = 'block';
						};
                    
                    
					Sortable.create('lightbox-preview-panel-content',
					{
						tag: 'div', 
                        overlap: 'horizontal', 
                        constraint: false, 
                        'ghosting':true, 
                        'ghostOpacity':'0',
						onUpdate: function() 
						{ 
							object.reSortItems(object.getLightboxId());
						},
                        onDrop: function()
                        {
                            // onDrop function added to scriptaculous library by Chris
                            // used to reset styles for currently dragging element
                            // drag functionality alters CSS in an unfavourable way, so put this back again
                             $$('#basket-preview-panel-content div.placeholder').each(function(el){
                                el.setStyle({"top":"0","left":"0"});
                             });
                        },
                        starteffect: function()
                        {
                            // don't want a panel hover, but there could be one already. Override
                            $('lightbox-preview-panel-content').addClassName("panel_hover_override");
                        },
                        endeffect: function()
                        {
                            // remove panel hover override
                            $('lightbox-preview-panel-content').removeClassName("panel_hover_override");
                        }
					});
					
                    
					$('lightbox-preview-panel-content').onclick = function(e) {
					    var target = e ? e.target : window.event.srcElement;
					    if (target.nodeName.toLowerCase() !== 'a' && target.nodeName.toLowerCase() !== 'img') {
							$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
								function(element)
								{
									if (Element.hasClassName(element, 'thumbnail-selected'))
									{
										Element.removeClassName(element, 'thumbnail-selected');
									}
								}
							);
						}
					}
                    
					object.assetList = '';
					$jq('#lightbox-preview-panel-content img.thumbnail').each(function(index,element){

								if (object.assetList != '') {
									object.assetList += ',';
								}
								object.assetList += object.getObjectId(element);
								
								element.onclick = function()
								{
									if (Element.hasClassName(element, 'thumbnail-selected'))
									{
										Element.removeClassName(element, 'thumbnail-selected');
									}
									else
									{
										Element.addClassName(element, 'thumbnail-selected');										
									}
								}
								
								element.ondblclick = function()
								{
									Asset.zoomPopup(object.getObjectId(element), 'overlay', '', object.assetList, null);
								}
						}
					);
					
					
					
					
					
					
					$jq('#lightbox-preview-panel-content a').each(function(index,element){
 
							if (element.name == 'lightbox-preview-panel-content-menu-remove')
							{
								element.onclick = function()
								{
								    if(Lightbox.isOwner() == false)
                                    {
                                        Lightbox.showNotOwnerError();
                                        return false;   
                                    }
									var assets = [];
									$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
										function(imgEl)
										{
											if (Element.hasClassName(imgEl, 'thumbnail-selected') && object.getObjectId(element) != object.getObjectId(imgEl))
											{
												assets[assets.length] = object.getObjectId(imgEl);
											}
										}
									);
								
									assets[assets.length] = [object.getObjectId(element)];
									object.removeAsset(object.getLightboxId(), assets,
										function()
										{
 											if($('lightbox_name')) {
 												Lightbox.showContent(Lightbox.getLightboxId(), 1, 1);
 											}
                                            Lightbox.initPreviewPanel(Lightbox.getLightboxId());
 											Lightbox.changeGridIcon(false, Lightbox.getItemType(element), Lightbox.getObjectId(element), 'images/icons/Lightbox43.gif');
										}
									);
                                    
                                    
								}
							}

							if (element.name == 'lightbox-preview-panel-content-menu-add-basket')
							{
								element.onclick = function()
								{
									if ($('basket-preview-panel')) {
										var assets = [];
										$A($('lightbox-preview-panel-content').getElementsByTagName('img')).each(
											function(imgEl)
											{
												if (Element.hasClassName(imgEl, 'thumbnail-selected') && object.getObjectId(element) != object.getObjectId(imgEl))
												{
													assets[assets.length] = object.getObjectId(imgEl);
												}
											}
										);
									
										assets[assets.length] = [object.getObjectId(element)];
										
										object.addAssetToBasket(object.getLightboxId(), assets,
											function()
											{
												Basket.initPreviewPanel(Basket.getBasketId(),
													function()
													{
														Basket.enableSlider();
														Basket.show();
														object.hide();
													}
												);
					
												return false;
											}
										);
									}
									else {
										url = this.language+'/user/show_login_page.html';
										document.location = url;
									}
								}
							}
						}
					);
					
					$(document.body).insert('<div id="drag" style="position:absolute;z-index:20000;top:0;left:0;cursor:move;display:none;"></div>');
					

					$jq('#mainContent img.imageDraggableDisabled').each(
						function(index, element){
							element.ondragstart = function(e) {  
								return false;  
                            } 
							
							var cornerToCursorX = 0;
                            var cornerToCursorY = 0;

                                new Draggable(element.id, {revert:false,
                                onStart: function(d,e){
                                        var dummy = element.clone();
                                        $(dummy).setStyle({'position':'static',top:0,left:0});
                                        $('drag').setStyle({'display':'none'}).insert(dummy);

                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        var offset = $(element).cumulativeOffset();
                                        cornerToCursorX = Event.pointerX(e) - (offset.left - scrollOffset.left + parseInt(element.getStyle('border-left-width').replace(/px$/,'')));
                                        cornerToCursorY = Event.pointerY(e) - (offset.top - scrollOffset.top + parseInt(element.getStyle('border-top-width').replace(/px$/,'')));
                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        newTop = Event.pointerY(e) - cornerToCursorY;
                                        newLeft = Event.pointerX(e) - cornerToCursorX;
                                        $('drag').setStyle({'top':newTop+'px'});
                                        $('drag').setStyle({'left':newLeft+'px'});
                                    },
                                    onDrag: function(d,e){
                                        var scrollOffset = $(element).cumulativeScrollOffset();
                                        newTop = Event.pointerY(e);// - cornerToCursorY;
                                        newLeft = Event.pointerX(e);// - cornerToCursorX;
                                        $('drag').setStyle({'top':newTop+'px'});
                                        $('drag').setStyle({'left':newLeft+'px'});
                                    },
                                 
			                        onEnd: function(){
			                            element.style.display = '';
			                        	element.style.top = "auto";
                                        element.style.bottom = "auto";  // this will be reset to 0px in a moment
			                        	element.style.left = "0px";
                                        it1 = setInterval(function(){element.style.bottom = "0px";},1);
                                        setTimeout(function(){clearInterval(it1);},50);
                                        $$('#drag img').each(function(node){node.remove();});
			                        },
                                    
                                    starteffect: function(element){
                                        $('drag').setOpacity('0.7').setStyle({'display':'block'});
                                        Draggable._dragging[element] = true;
                                        element.setOpacity('0');
                                    },
                                    
                                    endeffect: function(element){
                                        element.setOpacity('1');
                                        new Effect.Opacity($('drag'), {duration:0.2, from:0.7, to:0,
                                          queue: {scope:'_draggable', position:'end'},
                                          afterFinish: function(){
                                            Draggable._dragging[element] = false
                                          }
                                        });
                                    }
								});
								
						
						}
					);



					//-------------------- icons [xxx]
					var addBack = false;
					if ($('lightbox-preview-panel-item-sequence-2').checked)
					{
						addBack = true;
					}
					object.updateIcons(addBack);

					//-------------------- [xxx]

					Droppables.add('lightbox-preview-panel-content', { hoverclass: 'panel_hover', onDrop:
						function(element)
						{
							if (!Element.hasClassName(element, 'imageDraggable'))
							{
                                return false;
							}
							var sequence = Lightbox.getSequence();



							if(element.hasClassName('clicked2')){
									Lightbox.tsrt='';
									$$('.clicked2').each(function(el,index){
										if(el!=element){
											if(Lightbox.tsrt == ''){
												Lightbox.tsrt += Lightbox.getObjectId(el);
											}else{
												Lightbox.tsrt +=',' + Lightbox.getObjectId(el);									
											}	
																		
										}
									});
									$$('.clicked').each(function(el,index){
										el.removeClassName('clicked');
									});
									$$('.clicked2').each(function(el,index){
										el.removeClassName('clicked2');	
									});

														
											

									
									Lightbox.addMultiAsset(Lightbox.getLightboxId(), Lightbox.tsrt, sequence,function(){
										Lightbox.initPreviewPanel(object.getLightboxId(),
											function() {
												Lightbox.enableSlider();
												Lightbox.show();
												Basket.hide();
											}
										);
									});

								}else{
									Lightbox.addAsset(Lightbox.getLightboxId(), Lightbox.getObjectId(element), sequence,
										function() {
											object.initPreviewPanel(object.getLightboxId(),
												function() {
													Lightbox.enableSlider();
													Lightbox.show();
													Basket.hide();
												}
											);
										}
									);
								}



							
							
						}
					});
					
					if (Basket) {
						Basket.updateIcons(false);
					}
					
					if (on_complete_action) 
					{
						on_complete_action();
					}
					
 					
			}
		);
	}
    
    
    
	this.tsrt='';
	this.direct_download = function() {
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=lightbox&action=do_direct_download&lightbox=' + this.getLightboxId();
			document.location = url;
		}
	}
	
	this.comp_download = function() {
		
				var acknowlaged = confirm('Images that have not yet been purchased may only be used for mock-up and review purposes. Do you agree not to use this image for any other purpose?');
				
		if (acknowlaged) {
			url = '?service=lightbox&action=do_comp_download&lightbox=' + this.getLightboxId();
			document.location = url;
		}
	}
    
    this.getGridItems = function() {
        // By Chris: returns an array of references to all grid items.
        // You can call this as many times as you like, and it will only calculate grid items once.
        
        if(this.getGridItems.length==0)
        {
            // haven't calculated the grid items yet
            if(grid_item_list)
            {
                // the grid usually has a variable called grid_item_list, set in its template file.
                // this is an array of string values. Just need to turn into references
                newItem = null;
                assetId = null;
                for(i=0;i<grid_item_list.length;i++)
                {
                    // get current assetId
                    assetId = grid_item_list[i];
                    
                    // determine the image
                    letter = 'A';
                    gridItem = $("grid-item_A_"+assetId);
                    if(!gridItem)
                    {
                        gridItem = $("grid-item_F_"+assetId);
                        letter = 'F';
                    }
                    if(!gridItem)
                    {
                        gridItem = $("grid-item_C_"+assetId);
                        letter = 'C';    
                    }
                    
                    // generate the rest
                    // assumes that the letter for all image links is the same as the image itself
                    
                    // there are identical IDs within the grid corresponding to original and autozoom icons.
                    // need to find each one.
                    
                    assetLink = $$('#assetLink_'+letter+'_'+assetId);
                    lightboxLink = $$('#lightbox-link_'+letter+'_'+assetId);
                    basketLink = $$('#basket-link_'+letter+'_'+assetId);
                    downloadLink = $$('#download_icon_link_'+letter+'_'+assetId);
                    
                    //assetLink = $('assetLink_'+letter+'_'+assetId);
                    //lightboxLink = $('lightbox-link_'+letter+'_'+assetId);
                    //basketLink = $('basket-link_'+letter+'_'+assetId);
                    //downloadLink = $('download_icon_link_'+letter+'_'+assetId);
                    
                    newItem = {"gridItem":gridItem,
                                "assetLink":assetLink,
                                "lightboxLink":lightboxLink,
                                "basketLink":basketLink,
                                "downloadLink":downloadLink};
                    this.gridItems.push(newItem);
                }
            }
            else
            {
                // I haven't encountered a place where grid_item_list isn't set, yet.
                // if you do you'll need to generate it manually    
            }
        }
        return this.gridItems;
    }
    
    this.updateTotals = function() {
        // updates the values of the lightbox overlay based on other panels' values e.g. "Similars (0)"
        // grabs values from the panels themselves to avoid ajax call
        
        var numSimilars = null;
        if($('numSimilars')) numSimilars = $('numSimilars');
        $('lightbox-similars_count').innerHTML = 'Similars ('+numSimilars.innerHTML+')';
    }
    
    

	this.updateIcons = function(addBack)
	{
        // reset lightbox icon state to unselected, and make selected based on lightbox content
		object = this;
		
		var iconUrl = 'images/icons/Lightbox43.gif';
		var iconTitle = 'Add to front of lightbox';
		var selectedUrl = 'images/icons/Lightbox43_redX.gif';
		var selectedTitle = 'Move to front of lightbox';
		if (addBack)
		{
			iconUrl = 'images/icons/Lightbox44.gif';
			iconTitle = 'Add to back of lightbox';
			selectedUrl = 'images/icons/Lightbox44_redX.gif';
			selectedTitle = 'Move to back of lightbox';
		}
        
        // resets all icons to the default, unselected icon
        var type = null;
        var id = null;
        var currentlyInPreviewPanel = [];
        
        // reset every icon
        $jq("#mainContent a.lightboxLink img").each(function()
        {
            this.src = iconUrl;
            this.title = iconTitle;
        });
        
        // get references of icons in grid that are in lightbox
        $jq('#lightbox-preview-panel-content img.thumbnail').each(function(){
            // get the id data
            id = this.id.replace("lightbox-preview-panel-content-image","");
            
            // can't just get by id as there are duplicate IDs, so do a search
            $jq("#grid-item"+id).parents(".pictureBox").find(".lightboxLink img").each(function(){
                this.src = selectedUrl;
                this.title = selectedTitle;
            });
        });
        
            
        
        /*$jq("#mainContent a.lightboxLink").each(function()
		{
            type = object.getItemType(this);
            id = object.getObjectId(this);
            
            object.changeGridTitle(type, id, iconTitle);
            object.changeGridIcon(false, type, id, iconUrl);
        });
		
        // sets the ones in the lightbox to the selected ones
		$jq('#lightbox-preview-panel-content img.thumbnail').each(function()
		{
				object.changeGridTitle(object.getItemType(this), object.getObjectId(this), selectedTitle);
				object.changeGridIcon(true, object.getItemType(this), object.getObjectId(this), selectedUrl);
		});*/

	}
	
	//Sharayu .. start init Arranger
	
	this.initArrangerPanel = function(lightbox, on_complete_action)
	{
		var object = this;
		//alert(object.value);
		//alert('in initArrangerPanel');
		this.showArrangerContent(lightbox,
			function()
			{ 
				//not working			
				alert('on complete arranger content');
				
				//not working

				on_complete_action();
			}
		);
	}
	//Sharayu .. end init Arranger
	
	
	this.initPrintOptionsWindow = function()
	{
		$('layout-selector').onchange =
			function()
			{
				var parameters = this.value.split('|');
				$('layout-image').src = parameters[1];
			}

		$('layout-selector').onchange();
	}

	//


	// *** METHODS ***

	this.setLanguage = function(language)
	{
		this.language = language;
	}

	this.resetSeletor = function()
	{	
		$('lightbox-preview-panel-selector').selectedIndex = 0;
		$('lightbox-preview-panel-selector').onchange();
	}

	this.resetActionSeletor = function()
	{	
		$('lightbox-preview-panel-action-selector').selectedIndex = 0;
	}

	this.getLightboxId = function()
	{
		return $('lightbox-selected-id').value;
	}

	this.getItemId = function(element)
	{
		var chunks = element.id.split('_');
		
		return chunks[chunks.length - 3];
	}

	this.getItemType = function(element)
	{
		var chunks = element.id.split('_');

		return chunks[chunks.length - 2];
	}

	this.getObjectId = function(element)
	{
		var objectId = 0;
		if (element.getAttribute('assetid'))
		{
			objectId = element.getAttribute('assetid');
		}
		else
		{
			var chunks = element.id.split('_');
			objectId = chunks[chunks.length - 1];
		}
		return objectId;
	}

	this.getSequence = function()
	{
		var sequence_element = document.getElementsByName('lightboxSequence');

		for (var i = 0; i < sequence_element.length; i++)
		{
			if (sequence_element[i].checked)
			{
				return sequence_element[i].value;
			}
		}

		return null;
	}

	this.isPreviewSelected = function()
	{
		return this.previewSelected;
	}
	
	this.show = function()
	{
		try{Basket.hide();}catch(e){}
		this.previewSelected = true;

		$('lightbox-preview-panel').style.display = '';
	}

	this.hide = function()
	{
		this.previewSelected = false;
 
		$('lightbox-preview-panel').style.display = 'none';
		$('lightbox-preview-panel').style.height = '0px';

	}

	this.enableSlider = function(value)
	{
		var myWidth = 600;
		var myHeight = 141;
		if (parseInt(navigator.appVersion)>3) {
			if (navigator.appName=="Netscape") {
				myWidth = window.innerWidth;
			}
			if (navigator.appName.indexOf("Microsoft")!=-1) {
				myWidth = document.body.offsetWidth;
			}
		}
 		myWidth = myWidth-14;
		  	$('pull-tab').style.width = myWidth + 'px';

            var delta=25;
            if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
            }

            if($('pull-tab').getWidth() != myWidth){
				//$('pull-tab').style.left = ((myWidth-$('pull-tab').getWidth()) / 2) + 'px'; 
				$('pull-tab').style.bottom = delta - parseInt(7) + 'px';   
            }


			if ($('basket-container')) {
                if($('basket-maximize').style.display=="none")
                {
                    // only adjust basket height if it's not minimized
    			 	$('basket-container').style.height = myHeight + delta + 'px';
    				$('basket-preview-panel-content').style.height = 114 + delta + 'px';
                }
			}
			if ($('lightbox-container')) {
                if($('lightbox-maximize').style.display=="none")
                {
                    // only adjust lightbox height if it's not minimized
                    $('lightbox-container').style.height = myHeight + delta + 'px';
                    $('lightbox-preview-panel-content').style.height = 114 + delta + 'px';
                }
			} 
            if ($('similars-container')) {
                if($('similars-maximize').style.display=="none")
                {
                    // only adjust similars height if it's not minimized
                    $('similars-container').style.height = myHeight + delta + 'px';
                    $('similars-preview-panel-content').style.height = 114 + delta + 'px';
                }
			}

			/*if($('lightbox-maximize').style.display == 'none') {
				Lightbox.maximize();
			} else {
				Lightbox.minimize();
			}*/

		var slider = new Control.Slider('pull-tab', 'pull-track', {
			 axis: 'vertical',
			 range: $R(0, 100),
      		 sliderValue: 100,
			 onSlide: function(value)
			 {
			 	var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
                CookieHandler.setCookie('delta', delta,'31');
				if($('lightbox-container')) {
				 	$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 112 + delta + 'px';
			 	}
				if($('basket-container')) {
				 	$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 112 + delta + 'px';
				}				
			},
			onChange:function()
			{
				var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
                CookieHandler.setCookie('delta', delta,'31');
				if($('lightbox-container')) {
					$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 112 + delta + 'px';
				}
				if($('basket-container')) {
					$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 112 + delta + 'px';
				}				
			}
		});
		
		if($('lightbox-maximize').style.display == 'none') {
			setTimeout(function(){
				var delta = $('pull-track').clientHeight - $('pull-tab').style.top.replace(/px$/,"");
				CookieHandler.setCookie('delta', delta,'31');
				if($('lightbox-container')) {
					$('lightbox-container').style.height = myHeight + delta + 'px';
					$('lightbox-preview-panel-content').style.height = 112 + delta + 'px';
				}
				if($('basket-container')) {
					$('basket-container').style.height = myHeight + delta + 'px';
					$('basket-preview-panel-content').style.height = 112 + delta + 'px';
				}
			},50);		
		}
  $('pull-tab').style.top = (parseInt($('pull-tab').style.top.replace(/px$/,"")) - delta+6) + 'px';  
 	}

	this.minimize = function(on_complete_action)
	{
		$('lightbox-preview-panel-content').style.display = 'none';
		$('lightbox-container').style.height = '29px';
		setTimeout(function(){$('lightbox-container').style.height = '29px';},50);
		$('pull-tab').style.bottom = '-110px';
		$('pull-tab').style.top = '';
		$('pull-tab').style.display = 'none';
		$('pull-tab').style.backgroundPosition = 'left';

		$('lightbox-minimize').style.display = 'none';
		$('lightbox-maximize').style.display = '';

		url = '?service=user&action=do_collapse_container';
		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	   setCookie("maximized",'0','31');
    }

	this.maximize = function(on_complete_action)
	{
	   // old maximize code
		/*$('lightbox-preview-panel-content').style.display = '';
		$('lightbox-container').style.height = '140px';
		$('pull-tab').style.bottom = '0px';
		$('pull-tab').style.top = '';
		$('pull-tab').style.display = 'block';
		$('pull-tab').style.backgroundPosition = 'center center';
		$('lightbox-maximize').style.display = 'none';
		$('lightbox-minimize').style.display = '';
		url = '?service=user&action=do_expand_container&lb=1';
		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});*/
        
         var delta;
       var myHeight = 122;
	   if(CookieHandler.getCookie('delta')){
                delta = CookieHandler.getCookie('delta');
                delta = parseInt(delta);
       } else {
            delta = 140-myHeight; 
       }
		$('lightbox-preview-panel-content').style.display = '';
		$('lightbox-container').style.height = myHeight + delta + 'px';
		//$('pull-tab').style.bottom = '0px';
		//$('pull-tab').style.top = (parseInt($('pull-tab').style.top.replace(/px$/,"")) - delta + 18) + 'px';
		
		$('pull-tab').style.backgroundPosition = 'center center';
		$('lightbox-maximize').style.display = 'none';
		$('lightbox-minimize').style.display = '';
        $('pull-tab').style.display = 'block';

		url = '?service=user&action=do_expand_container&lb=2';

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	   setCookie('maximized','1','31');
       Lightbox.enableSlider();
       
	}

	this.create = function(name, on_success_action)
	{
		url = '?service=lightbox&action=do_create&name=' + encodeURIComponent(name);
		
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true, 
			onSuccess: function(transport) 
			{ 
				xml = transport.responseXML.documentElement;
		
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
		
				if (result == "null")
				{
					alert("Please enter a lightbox name");
				}
				else
				{
					on_success_action(result);
				}
				
				return result;
			}
		});
	}

	this.rename = function(lightbox, name, on_complete_action)
	{
		url = '?service=lightbox&action=do_rename&lightbox=' + lightbox + '&name=' + encodeURIComponent(name);
		
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this._delete = function(lightbox, on_complete_action,object)
	{
		url = '?service=lightbox&action=do_delete&lightbox=' + lightbox;
		
		new Ajax.Request(url, {method: 'get', asynchronous:true, 
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},		
			onComplete:on_complete_action
		});
        
        if ($('lightbox-preview-panel-selector')) {
        	this.resetSeletor();
        }
	}

	this.addAsset = function(lightbox, item, sequence, on_complete_action)
	{
		url = '?service=lightbox&action=do_add_asset&lightbox=' + lightbox + '&asset=' + item + '&sequence=' + sequence;
        
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onComplete:on_complete_action
		});
	}

	this.addMultiAsset = function(lightbox, asset, sequence, on_complete_action)
	{
		url = '?service=lightbox&action=do_add_asset&multi=1&lightbox=' + lightbox + '&asset=' + asset + '&sequence=' + sequence;

		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete: on_complete_action});
	}
	
	

	this.removeAsset = function(lightbox, assets, on_complete_action)
	{
		var params = '';

		for (var i = 0; i < assets.length; i++)
		{
			params += '&asset[]=' + assets[i];
		}
		
		url = '?service=lightbox&action=do_remove_asset&lightbox=' + lightbox + '&asset=' + assets;
		
		new Ajax.Request(url, {method: 'get', asynchronous:true, onComplete:on_complete_action});
	}

	this.empty = function(lightbox, on_complete_action)
	{
		url = '?service=lightbox&action=do_empty&lightbox=' + lightbox;
		
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.duplicate = function(lightbox, name, on_success_action)
	{
		url = '?service=lightbox&action=do_duplicate&lightbox=' + lightbox + '&name=' + encodeURIComponent(name);
		
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true, 
			onSuccess: function(transport) 
			{ 
				xml = transport.responseXML.documentElement;
		
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
		
				if (result == "null")
				{
					alert("Please enter a lightbox name");
				}
				else
				{
					on_success_action(result);
				}
				
				return result;
			}
		});
	}

	this.reSortItems = function(lightbox, on_complete_action)
	{
		params = Sortable.serialize('lightbox-preview-panel-content');
		
		url = '?service=lightbox&action=do_resort_items&lightbox=' + lightbox;
		
		new Ajax.Request(url, {method: 'post', asynchronous:true, evalScripts:true, parameters: params,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},		
			onComplete:on_complete_action
		});
	}
/*
	this.email = function()
	{
		document.location.href = 'mailto:?body=' + encodeURIComponent($('lightbox-email-url').value);
	}
*/
	this.email = function(lightbox, type, email, subject, description, on_success_action, on_failure_action)
	{
		params = 'type=' + escape(type) + '&email=' + escape(email) + '&subject=' + escape(subject) + '&description=' + escape(description);
		url = '?service=lightbox&action=do_email&lightbox=' + lightbox;
        new Ajax.Request(url, {method: 'post', parameters: params, asynchronous:true, evalScripts:true,  
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
		
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}
				else
				{
					document.location = '?service=error&action=show_db_error_page';
				}
				
				return result;
			}
		});
	}
	
	this.showEmailFormErrors = function(language)
	{
		url = '?service=lightbox&action=show_email_form_errors&language=' + language;
		new Ajax.Updater('lightboxEmailFormErrors', url, {method: 'get', asynchronous:true, evalScripts:true});
	}
	
	this.share = function()
	{
		document.location.href = 'mailto:?body=' + encodeURIComponent($('lightbox-share-url').value);
	}

	this.setDownloadSize = function(lightbox, asset, download_size, on_complete_action)
	{
		var lightbox = lightbox;
		var item = asset;
		var language = this.language;
		
		url = '?service=lightbox&action=do_set_download_size&lightbox=' + lightbox + '&asset=' + asset + '&download_size=' + download_size;
		new Ajax.Request(url, {method: 'get', asynchronous:true, 
			onSuccess: function(transport)
			{
				
			},
			onComplete:on_complete_action});
	}

	this.applyItemUsage = function(lightbox, item, usage_code, ms_menus, pack_code, ps_menus, on_complete_action)
	{
		var lightbox = lightbox;
		var item = item;
		var language = this.language;
		
		url = '?service=lightbox&action=do_apply_item_usage&lightbox=' + lightbox + '&item=' + item + '&usage_code=' + usage_code + '&ms_menus=' + ms_menus + '&pack_code=' + pack_code + '&ps_menus=' + ps_menus;
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
				
			},			
			onComplete:on_complete_action
		});
	}	
	
	this.copyAssets = function(lightbox_from, lightbox_to, assets, on_complete_action)
	{
		var params = '';

		for (var i = 0; i < assets.length; i++)
		{
			params += '&asset[]=' + assets[i];
		}

		url = '?service=lightbox&action=do_copy&lightbox_from=' + lightbox_from + '&lightbox_to=' + lightbox_to + params;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},			
			onComplete:on_complete_action
		});
	}

	this.moveAssets = function(lightbox_from, lightbox_to, assets, on_complete_action)
	{
		var params = '';

		for (var i = 0; i < assets.length; i++)
		{
			params += '&asset[]=' + assets[i];
		}

		url = '?service=lightbox&action=do_move&lightbox_from=' + lightbox_from + '&lightbox_to=' + lightbox_to + params;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},			
			onComplete:on_complete_action
		});
	}

	this.saveLightboxNotes = function(lightbox, note, on_complete_action)
	{
		url = '?service=lightbox&action=do_save_lightbox_notes&lightbox=' + lightbox + '&notes=' + encodeURIComponent(note);
		
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},			
			onComplete:on_complete_action
		});
	}

	this.saveNote = function(lightbox, note, asset, on_complete_action)
	{
		url = '?service=lightbox&action=do_save_note&lightbox=' + lightbox + '&note=' + encodeURIComponent(note) + '&asset=' + asset;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},			
			onComplete:on_complete_action
		});
	}

	this.changeGridIcon = function(status, type, id, src)
	{
		var src=src;
		$$('#lb-icon_' + type + '_' + id).each(
        function(el){
			if (browser.isIE && browser.version == 6) {
				img = new Image();
				img.id = el.id;
				img.src = src;
				el.replaceNode(img);
			} else {
                el.src = src;
			}
        });
        
	}

	this.changeGridTitle = function(type, id, title)
	{
		var title=title;
		$$('#lb-icon_' + type + '_' + id).each(
        function(el){
                el.title = title;
        });
	}

	this.showPreviewPanel = function(lightbox, on_complete_action)
	{
		setTimeout(function(){
			$('lightbox-preview-panel').style.display='';
			try{Basket.hide();}catch(e){}
		},100);


		url = '?service=lightbox&1=1&action=show_preview_panel&lightbox=' + lightbox  + '&sequence=' + Lightbox.getSequence();

        new Ajax.Updater('lightbox-preview-panel', url, {method: 'get', asynchronous:true, evalScripts:true, onComplete:function(){
          on_complete_action();
          Lightbox.enableSlider();
          }
        });
	}

	this.hidePreviewPanel = function()
	{
		$('lightbox-preview-panel').innerHTML = '';
	}

	this.scrollPreviewTop = function()
	{
		$('lightbox-preview-panel-content').scrollTop = 0;
	}

	this.scrollPreviewBottom = function()
	{
		$('lightbox-preview-panel-content').scrollTop = 9999;
	}

    this.showLightboxPage = function(lightbox)
    {
    	document.location = '?service=lightbox&action=show_lightbox_page&language=' + this.language + '&lightbox=' + lightbox; 
    }

    this.showContent = function(lightbox, page, grid_layout)
    {
		url = '?service=lightbox&action=show_lightbox_page_content&language=' + this.language + '&lightbox=' + lightbox + '&page=' + page + '&grid_layout=' + grid_layout;

		new Ajax.Updater('lightbox_content', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				ajaxAssetImages();
				Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
					function() {
						Lightbox.enableSlider();
						Lightbox.show();
						Basket.hide();
					}
				);

                LP_initSelectItems(); // actions dropdown will have reloaded, so add handlers again
			}
		});
        
    }
    
    //sharayu arrranger
    this.showArrangerContent = function(lightbox, on_complete_action)
    {
    	url = '?service=lightbox&action=show_lightbox_arranger_page_content&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightbox_content', url, {method: 'get', asynchronous:true, evalScripts:true});
		
    }
    
    this.showDivArrangerContent = function(lightbox, divarea)
    {
       	var lightbox_area1  = document.getElementById('lightboxdivArea1').value;
       	var lightbox_area2  = document.getElementById('lightboxdivArea2').value;
              
        if(divarea=='divContentArea1' && lightbox==lightbox_area2) 
        {
        	alert('div 1 ..both div have same lightbox.. please select other');
        	return false;
        }
        
        if(divarea=='divContentArea2' && lightbox==lightbox_area1) 
        {
        	alert('div 2 ..both div have same lightbox.. please select other');
        	return false;
        }
        

        url = '?service=lightbox&action=show_lightbox_arranger_div_content&language=' + this.language + '&lightbox=' + lightbox + '&div_area='+divarea;
    	new Ajax.Updater(divarea, url, {method: 'get', asynchronous:true, evalScripts:true});
    	
    	//working previous
    	//url = '?service=lightbox&action=show_lightbox_arranger_page_content&language=' + this.language + '&lightbox=' + lightbox;
    	//new Ajax.Updater('lightbox_content', url, {method: 'get', asynchronous:true, evalScripts:true}); 
   	}
   	

   	  	
       
    //sharayu arranger

	this.showCreateWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_create_window&language=' + this.language;
		
		new Ajax.Updater('lightboxCreateWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('lightboxCreateWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeCreateWindow = function()
	{
		hideBox('lightboxCreateWindow');
	}

	this.showRenameWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{ 
		url = '?service=lightbox&action=show_rename_window&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxRenameWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('lightboxRenameWindow', on_OK_button_action, on_CANCEL_button_action); 
			}
		});
	}

	this.closeRenameWindow = function()
	{
        hideBox('lightboxRenameWindow');  
	}

	this.showDeleteWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_delete_window&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxDeleteWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function() 
			{
				showBox('lightboxDeleteWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeDeleteWindow = function()
	{
	    hideBox('lightboxDeleteWindow');			
	}

	this.showEmptyWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_empty_window&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxEmptyWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('lightboxEmptyWindow', on_OK_button_action, on_CANCEL_button_action); 
			}
		});
	}

	this.closeEmptyWindow = function()
	{
		hideBox('lightboxEmptyWindow');	
	}

	this.showEmailWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_email_window&language=en&lightbox=' + lightbox;
		
		new Ajax.Updater('messageWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('messageWarningWindow', on_OK_button_action, on_CANCEL_button_action); 
			}
		});
	}

	this.showShareWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_email_window&share=1&language=en&lightbox=' + lightbox;
		
		new Ajax.Updater('messageWarningWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('messageWarningWindow', on_OK_button_action, on_CANCEL_button_action); 
			}
		});
	}


	this.closeEmailWindow = function()
	{
		hideBox('messageWarningWindow');	
	}

	this.showDuplicateWindow = function(lightbox, on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_duplicate_window&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxDuplicateWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{ 
				showBox('lightboxDuplicateWindow', on_OK_button_action, on_CANCEL_button_action);
			}
		});
	}

	this.closeDuplicateWindow = function()
	{
		hideBox('lightboxDuplicateWindow');	
	}

	this.showAddToBasketWindow = function(language, lightbox, action)
	{
		Lightbox.resetActionSeletor();
		url = '?service=lightbox&action=show_add_to_basket_window&language=' + language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxAddToBasketWindow', url, {method: 'get', onComplete: function() {
		showBox('lightboxAddToBasketWindow', action); }, asynchronous:true, evalScripts:true});
	}

	this.closeAddToBasketWindow = function()
	{
		hideBox('lightboxAddToBasketWindow');		
		
	}

	this.showLightboxNotesWindow = function(lightbox, on_SAVE_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_lightbox_notes_window&language=' + this.language + '&lightbox=' + lightbox;
		
		new Ajax.Updater('lightboxNotesWindow', url, {method: 'get', onComplete: function() { showBox('lightboxNotesWindow', on_SAVE_button_action, on_CANCEL_button_action); }, asynchronous:true, evalScripts:true});
	}

	this.closeLightboxNotesWindow = function()
	{  
        hideBox('lightboxNotesWindow');  
	}

	this.showNotesWindow = function(language, lightbox, asset, action)
	{
		url = '?service=lightbox&action=show_notes_window&language=' + language + '&lightbox=' + lightbox + '&asset=' + asset;
		
		new Ajax.Updater('notesWindow', url, {method: 'get', onComplete: function() { showBox('notesWindow', action); }, asynchronous:true, evalScripts:true});
	}

	this.closeNotesWindow = function()
	{
        hideBox('notesWindow');
	}

	this.showCopyMoveWindow = function(on_OK_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_copy_move_window&language=' + this.language;
		
		new Ajax.Updater('lightboxCopyMoveWindow', url, {method: 'get', onComplete: function() { showBox('lightboxCopyMoveWindow', on_OK_button_action, on_CANCEL_button_action); }, asynchronous:true, evalScripts:true});
	}

	this.closeCopyMoveWindow = function()
	{
        hideBox('lightboxCopyMoveWindow');   
	}

	this.showPrintOptionsWindow = function(on_complete_action, on_PRINT_button_action, on_CANCEL_button_action)
	{
		url = '?service=lightbox&action=show_print_options_window&language=' + this.language;
		
		new Ajax.Updater('lightboxPrintOptionsWindow', url, {method: 'get', onComplete: function() { on_complete_action(); showBox('lightboxPrintOptionsWindow', on_PRINT_button_action, on_CANCEL_button_action);  }, asynchronous:true, evalScripts:true});
	}

	this.closePrintOptionsWindow = function()
	{
        hideBox('lightboxPrintOptionsWindow');		
	}

	this.showPrintPage = function(lightbox, print_size)
	{
		window.open('?service=lightbox&action=show_print_page&lightbox=' + lightbox + '&print_size=' + print_size, 'lightboxPrintWindow', 'status=0, toolbar=0, scrollbars=yes');
	}


	//--------------------------------------------------- DELETED
	
	this.addAssetToBasket = function(lightbox, assets, on_complete_action)
	{
		var params = '';

		for (var i = 0; i < assets.length; i++)
		{
			params += '&asset[]=' + assets[i];
		}
		
		url = '?service=lightbox&action=do_add_asset_to_basket&lightbox=' + lightbox + params;
		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{ 
				xml = transport.responseXML.documentElement;
				
				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;
				
				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.showEmailedPage = function(service, action, lightbox, code, page)
	{
		language = this.language;
		document.location = '?service=' + service + '&action=' + action + '&language=' + this.language + '&lightbox=' + lightbox + '&code=' + code + '&page=' + page;
	}
	
	//--------------------------------------------------- END: DELETED
    
    this.isOwner = function()
    {
        // returns the isOwner property.
        // isOwner stores whether the current user can add things to the lightbox. 
        if($('isOwner'))
        {
            if($('isOwner').getValue() == '1')
            {
                return true;   
            }
            else
            {
                return false;   
            }
        }
        return true;
    }
    
    this.showNotOwnerError = function()
    {
        // the error to show when an action can't be performed due to not being the lightbox owner
        // this happens when trying to add to/delete from/price a shared lightbox, etc. 
        // Text is specified as an input in the lightbox preview panel 
        if($('notOwnerErrorText'))
        {
            alert($('notOwnerErrorText').getValue());
        }
        
    }

}

function LP_selectedCount() {
	var selArray = document.selectionList.selectionListItem;
	var selectedCount = 0;
	
	if(typeof selArray == 'object') {
		if(selArray.checked){
			selectedCount++;
		}
	}else{
		for (var i=0;i<selArray.length;i++){
			if (selArray[i].checked) {
				selectedCount++;
			}
		}
	}
	return selectedCount;
}

function LP_selectedItemArray() {

	var selArray = document.selectionList.selectionListItem;
    var checkedArray = [];
	
	if(selArray.checked === true){
        // selArray is actually an element, and it's checked [CB]
        checkedArray.push(selArray.value);
	}
    else if(selArray.checked !== false)
    {
        // if selArray.checked isn't true or false, it's undefined - assume it was an array, not an element [CB]
    	for (var i=0;i<selArray.length;i++){
    		if (selArray[i].checked) {
    			checkedArray.push(selArray[i].value);
    		}
    	}
	}
	
	
	return checkedArray;
}

function LP_updateActionMenu() {
	paras = $$('.selectionListItem');
 	var selCount = 0;
 	paras.each(
 		function(el){
	 		if(el.checked){
			 	selCount++;
 			}
 		}
 	)

//	var selCount = LP_selectedCount();
	if(selCount == 1) {
		document.getElementById('lightbox_actions_optgroup').disabled = false;
	} else {
		document.getElementById('lightbox_actions_optgroup').disabled = true;	
	}
	
	if(selCount > 0) {
		document.getElementById('lightbox_actions_remove_selected').disabled = false;	
	} else {
		document.getElementById('lightbox_actions_remove_selected').disabled = true;	
	}
	
}

function LP_resetActionSelector ()
{	
	$('lightbox_action_selector').selectedIndex = 0;
}

function LP_initSelectItems_old() {
//	var paras = $A(document.getElementsByClassName('selectionListItem'));
//	paras.each($(Element).onclick= function(){LP_updateActionMenu();});

	$('lightbox_action_selector').onchange = 
		function() {
			var checkedArray = LP_selectedItemArray();
			var selectedLightbox;
			if (checkedArray.length == 1) selectedLightbox = checkedArray[0];
			switch (this.value)
			{
				case 'display':
					var checkedArray = LP_selectedItemArray();
					Lightbox.showLightboxPage(selectedLightbox);
					break;
					
				case 'create':
					Lightbox.showCreateWindow(
						function()
						{
							Lightbox.create($('lightboxCreateWindowInput').value,
								function(lightbox)
								{
									Lightbox.closeCreateWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeCreateWindow();
							LP_resetActionSelector();
						}
					);
					break;

				case 'rename':
					Lightbox.showRenameWindow(selectedLightbox,
						function()
						{
							Lightbox.rename(selectedLightbox, $('lightboxRenameWindowInput').value,
								function()
								{
									Lightbox.closeRenameWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeRenameWindow();
							LP_resetActionSelector();
						}
					);								
					break;
					
				case 'delete':
					Lightbox.showDeleteWindow(selectedLightbox, 
						function() 
						{
							Lightbox._delete(selectedLightbox,
								function()
								{	
									Lightbox.closeDeleteWindow();
									window.location = window.location;
								}
							);		
						},
						function()
						{
							Lightbox.closeDeleteWindow();
							LP_resetActionSelector();
						}
					);
					break;
					
				case 'duplicate':
					Lightbox.showDuplicateWindow(selectedLightbox,
						function()
						{
							Lightbox.duplicate(selectedLightbox, $('lightboxDuplicateWindowInput').value,
								function(lightbox)
								{
									Lightbox.closeDuplicateWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{			
							Lightbox.closeDuplicateWindow();								
							LP_resetActionSelector();
						}
					);
					break;
					
				case 'annotate':
					Lightbox.showLightboxNotesWindow(selectedLightbox,
						function()
						{
							Lightbox.saveLightboxNotes(selectedLightbox, $('lightboxNotesWindowInput').value,
								function()
								{
									Lightbox.closeLightboxNotesWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeLightboxNotesWindow();
							LP_resetActionSelector();
						}
					);
					break;
							
				case 'empty':
					Lightbox.showEmptyWindow(selectedLightbox,
						function() 
						{
							Lightbox.empty(selectedLightbox,
								function()
								{
									Lightbox.closeEmptyWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeEmptyWindow();
							LP_resetActionSelector();
						}									
					);
					break;
					
				case 'email':
					Lightbox.showEmailWindow(selectedLightbox,
						function()
						{
							$('lightboxEmailFormErrors').innerHTML = "<span></span>";
							Lightbox.email(selectedLightbox, 'email', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
							function () {
								alert('Email successfully sent');
								Lightbox.closeEmailWindow();
							}, 
							function () {
								Lightbox.showEmailFormErrors(Lightbox.language);
							});
						},
						function()
						{
							Lightbox.closeEmailWindow();
						}
					);
					LP_resetActionSelector();
					break;

				case 'share':
					Lightbox.showEmailWindow(selectedLightbox,
						function()
						{
							$('lightboxEmailFormErrors').innerHTML = "<span></span>";
							Lightbox.email(selectedLightbox, 'share', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
							function () {
								alert('Email successfully sent');
								Lightbox.closeEmailWindow();
							}, 
							function () {
								Lightbox.showEmailFormErrors(Lightbox.language);
							});
						},
						function()
						{
							Lightbox.closeEmailWindow();
						}
					);
					LP_resetActionSelector();
					break;

				case 'print':
					Lightbox.showPrintOptionsWindow(
						function()
						{		
							Lightbox.initPrintOptionsWindow();
						},
						function()
						{
							var parameters = $('layout-selector').value.split('|');
							
							Lightbox.showPrintPage(selectedLightbox, parameters[0]);
							Lightbox.closePrintOptionsWindow();
							LP_resetActionSelector();

						},
						function()
						{
							Lightbox.closePrintOptionsWindow();
							LP_resetActionSelector();
						}
					);
					break;

				case 'select_all':
					LP_selectAll();
					break;

				case 'unselect_all':
					LP_unselectAll();
					break;

				case 'remove_selected':
					Lightbox.showDeleteWindow(0, 
						function() 
						{
							Lightbox.closeDeleteWindow();
							for(var i=0; i<(checkedArray.length-1); i++) {
								Lightbox._delete(checkedArray[i]);	
							}
							Lightbox._delete(checkedArray[i],
								function()
								{	
									Lightbox.closeDeleteWindow();
									window.location = window.location;
								}
							);		
						},
						function()
						{
							Lightbox.closeDeleteWindow();
							LP_resetActionSelector();
						}
					);
					break;
			}
		};
 
}

function LP_initSelectItems() {
    
    // Adds event handlers for the "actions" menu on BOTH the manager and the lightbox list pages.
    // They read slightly different elements (#lightbox_name for the manager and checkboxes for the list)
    // ... deviations are marked
    
    if(document.selectionList)
    {
        // list: add event handlers for checkboxes
        
    	var selArray = document.selectionList.selectionListItem;
        
        // test to see if it's a NodeList; if not, try acting on the object directly
    	if(!selArray.item) {
    		selArray.onclick = function() {
    				LP_updateActionMenu();
    			};
            for (var i=0;i<selArray.length;i++){
    			selArray[i].onclick = function() {
    				LP_updateActionMenu();
    			};
    		}
    	} else{
    		for (var i=0;i<selArray.length;i++){
    			selArray[i].onclick = function() {
    				LP_updateActionMenu();
    			};
    		}
    	}
     }

    // selector onchange actions
	if($('lightbox_action_selector')) $('lightbox_action_selector').onchange = 
		function() {
            var selectedLightbox;
            var checkedArray;
            
            // determine lightbox ID to act upon
            if(document.selectionList)
            {
                // list: determine lightbox ID from checked item
    			checkedArray = LP_selectedItemArray();
    			if (checkedArray.length == 1) selectedLightbox = checkedArray[0];
            }
            else
            {
                // manager: determine lightbox ID from lightbox_name dropdown
                selectedLightbox = $('lightbox_name').value;
            }
            
			switch (this.value)
			{
				case 'display':
					Lightbox.showLightboxPage(selectedLightbox);
					break;
                    
                case 'arrange':									
					object.resetActionSeletor();
					url = '?service=lightbox&action=show_lightbox_arranger&lightbox=' + selectedLightbox + '&lightbox1=' + selectedLightbox;
					document.location = url;
					break;
                    
                case 'addToBasket':
					if ($('basket-preview-panel')) {
						Lightbox.showAddToBasketWindow(this.language, selectedLightbox,
							function()
							{
								Lightbox.closeAddToBasketWindow();
								var assets = [];
								$$("#mainContent .secondaryContent img.mainThumbImage").each(
									function(imgEl)
									{
									   assets[assets.length] = object.getObjectId(imgEl);
									}
								);
							
								Lightbox.addAssetToBasket(selectedLightbox, assets,
									function()
									{
										Basket.initPreviewPanel(Basket.getBasketId(),
											function()
											{
                                                //Lightbox.updateQuantities();
                                                //Similars.updateQuantities();
                                                Basket.show();
                                                Lightbox.hide();
                                                Similars.hide();
											}
										);
									}
								);
							},
							function()
							{
								object.closeAddToBasketWindow();
								object.resetActionSeletor();
							}									
						);
					}
					else {
						url = this.language+'/user/show_login_page.html';
						document.location = url;
					}
                    Lightbox.resetActionSeletor();
				
				break;
                
                case 'd_download':
					Lightbox.resetActionSeletor();
					Lightbox.direct_download(selectedLightbox);
				break;
					
				case 'create':
					Lightbox.showCreateWindow(
						function()
						{
							Lightbox.create($('lightboxCreateWindowInput').value,
								function(lightbox)
								{
									Lightbox.closeCreateWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeCreateWindow();
							LP_resetActionSelector();
						}
					);
					break;

				case 'rename':
					Lightbox.showRenameWindow(selectedLightbox,
						function()
						{
							Lightbox.rename(selectedLightbox, $('lightboxRenameWindowInput').value,
								function()
								{
									Lightbox.closeRenameWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeRenameWindow();
							LP_resetActionSelector();
						}
					);								
					break;
					
				case 'delete':
					Lightbox.showDeleteWindow(selectedLightbox, 
						function() 
						{
							Lightbox._delete(selectedLightbox,
								function()
								{	
									Lightbox.closeDeleteWindow();
									window.location = window.location;
								}
							);		
						},
						function()
						{
							Lightbox.closeDeleteWindow();
							LP_resetActionSelector();
						}
					);
					break;
					
				case 'duplicate':
					Lightbox.showDuplicateWindow(selectedLightbox,
						function()
						{
							Lightbox.duplicate(selectedLightbox, $('lightboxDuplicateWindowInput').value,
								function(lightbox)
								{
									Lightbox.closeDuplicateWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{			
							Lightbox.closeDuplicateWindow();								
							LP_resetActionSelector();
						}
					);
					break;
					
				case 'annotate':
					Lightbox.showLightboxNotesWindow(selectedLightbox,
						function()
						{
							Lightbox.saveLightboxNotes(selectedLightbox, $('lightboxNotesWindowInput').value,
								function()
								{
									Lightbox.closeLightboxNotesWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeLightboxNotesWindow();
							LP_resetActionSelector();
						}
					);
					break;
							
				case 'empty':
					Lightbox.showEmptyWindow(selectedLightbox,
						function() 
						{
							Lightbox.empty(selectedLightbox,
								function()
								{
									Lightbox.closeEmptyWindow();
									window.location = window.location;
								}
							);
						},
						function()
						{
							Lightbox.closeEmptyWindow();
							LP_resetActionSelector();
						}									
					);
					break;
					
				case 'email':
					Lightbox.showEmailWindow(selectedLightbox,
						function()
						{
							$('lightboxEmailFormErrors').innerHTML = "<span></span>";
							Lightbox.email(selectedLightbox, 'email', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
							function () {
								alert('Email successfully sent');
								Lightbox.closeEmailWindow();
							}, 
							function () {
								Lightbox.showEmailFormErrors(Lightbox.language);
							});
						},
						function()
						{
							Lightbox.closeEmailWindow();
						}
					);
					LP_resetActionSelector();
					break;

				case 'share':
					Lightbox.showEmailWindow(selectedLightbox,
						function()
						{
							$('lightboxEmailFormErrors').innerHTML = "<span></span>";
							Lightbox.email(selectedLightbox, 'share', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
							function () {
								alert('Email successfully sent');
								Lightbox.closeEmailWindow();
							}, 
							function () {
								Lightbox.showEmailFormErrors(Lightbox.language);
							});
						},
						function()
						{
							Lightbox.closeEmailWindow();
						}
					);
					LP_resetActionSelector();
					break;

				case 'print':
					Lightbox.showPrintOptionsWindow(
						function()
						{		
							Lightbox.initPrintOptionsWindow();
						},
						function()
						{
							var parameters = $('layout-selector').value.split('|');
							
							Lightbox.showPrintPage(selectedLightbox, parameters[0]);
							Lightbox.closePrintOptionsWindow();
							LP_resetActionSelector();

						},
						function()
						{
							Lightbox.closePrintOptionsWindow();
							LP_resetActionSelector();
						}
					);
					break;

				case 'select_all':
					LP_selectAll();
					break;

				case 'unselect_all':
					LP_unselectAll();
					break;

				case 'remove_selected':
					Lightbox.showDeleteWindow(0, 
						function() 
						{
							Lightbox.closeDeleteWindow();
							for(var i=0; i<(checkedArray.length-1); i++) {
								Lightbox._delete(checkedArray[i]);	
							}
							Lightbox._delete(checkedArray[i],
								function()
								{	
									Lightbox.closeDeleteWindow();
									window.location = window.location;
								}
							);		
						},
						function()
						{
							Lightbox.closeDeleteWindow();
							LP_resetActionSelector();
						}
					);
					break;
			}
		};
        
        
}

function LP_selectAllCheckbox(checked) {
	if (checked) {
		LP_selectAll();
	}
	else {
		LP_unselectAll();
	}
}

function LP_selectAll() {
	var selArray = document.selectionList.selectionListItem;
	for (var i=0;i<selArray.length;i++){
		selArray[i].checked = true;
	}
	document.getElementById('LP_select_all').checked = true;
	document.getElementById('lightbox_actions_optgroup').disabled = true;
	document.getElementById('lightbox_actions_remove_selected').disabled = false;
	LP_resetActionSelector();
}

function LP_unselectAll() {
	var selArray = document.selectionList.selectionListItem;
	for (var i=0;i<selArray.length;i++){
		selArray[i].checked = false;
	}
	document.getElementById('LP_select_all').checked = false;
	document.getElementById('lightbox_actions_optgroup').disabled = true;
	document.getElementById('lightbox_actions_remove_selected').disabled = true;
	LP_resetActionSelector();
}



function CookieHandler()
{
	this.setCookie = function(c_name,value,expiredays)
	{
		var exdate=new Date();
		exdate.setDate(exdate.getDate()+expiredays);
		document.cookie=c_name+ "=" +escape(value) + ";path=/" +
		((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) +
		'; secure';
	}
	
	this.getCookie = function(c_name)
	{
		if (document.cookie.length!=0)
		  {
		  c_start=document.cookie.indexOf(c_name + "=");
		  if (c_start!=-1)
		    {
		    c_start=c_start + c_name.length+1;
		    c_end=document.cookie.indexOf(";",c_start);
		    if (c_end==-1) c_end=document.cookie.length;
		    return unescape(document.cookie.substring(c_start,c_end));
		    }
		  }
		return "";
	}

}	

var CookieHandler = new CookieHandler();

function handlebgcolor() {
	if(CookieHandler.getCookie('bgcolor') !='') {
		for (var i=0; i < document.bgcolorform.bgcolorselect.length; i++) {
			if (document.bgcolorform.bgcolorselect[i].value == CookieHandler.getCookie('bgcolor')) {
				document.bgcolorform.bgcolorselect[i].selected = true;
			}
		}							
	}
}

function setUsername(username){
    CookieHandler.setCookie('username',username,30);
}

function getUsername(){
    return CookieHandler.getCookie('username');
}


	
	//----- PREVIEW SCREEN
	
	function lightboxPreview_onSelect()
	{
		if ($('preview_selector'))
		{
			$('preview_selector').disabled = true;
		}
	
		Basket.hidePreviewPanel();
		Basket.hide();
	
		Lightbox.showPreview(Lightbox.getSelectedId(),
			function()
			{
				Lightbox.showPreviewPanel(Lightbox.getSelectedId());	
			}
		);
		
	}
	
	function lightboxSelectedEvent_onLoad(lightbox)
	{
		Lightbox.showPreview(lightbox,
			function()
			{
				Lightbox.showPreviewPanel(lightbox);
			}
		);		
	}
	
	function lightboxCollapseLink_onClick(label)
	{
		Lightbox.collapse(label);
		User.collapseContainer();
	}
	
	function lightboxExpandLink_onClick()
	{
		Lightbox.expand();
		User.expandContainer();
	}
	
	function showEmailedLightboxPage(service, action, language, page, grid_layout, lightbox, code)
	{
	    url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout;  
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function()
			{ 
				document.location = '?service=' + service + '&action=' + action + '&language=' + language + '&page=' + page + '&grid_layout=' + grid_layout + '&lightbox=' + lightbox + '&code=' + code; 
			}
		});
	}	

	function lightboxMainScreenCreateButton_onClick(language)
	{
		Lightbox.showCreateWindow(
			function() 
			{
				
                Lightbox.create($('lightboxCreateWindowInput').value,
					function(id)
					{
						Lightbox.closeCreateWindow();
		
						Lightbox.showContent('en', id, '1', '1');
						
						if (Basket.isPreviewSelected())
						{
							Basket.showPreviewPanel();
						}								
						else
						{
							$('lightbox_name_selector').onchange();
						}	
					}
				);
                
                
			},
            function () {
              Lightbox.closeCreateWindow();  
            }
		);
	}
	
	function lightboxMainScreenRenameButton_onClick(language, lightbox)
	{
		Lightbox.showRenameWindow(lightbox, 
			function() 
			{
				Lightbox.rename(lightbox, $('lightboxRenameWindowInput').value,
					function()
					{
						Lightbox.closeRenameWindow();
						
						$('lightbox_name').onchange();
						
						if (Basket.isPreviewSelected())
						{
							Basket.showPreviewPanel();
						}
						else
						{
							$('lightbox_name_selector').onchange();
						}	
					}
				);
			},
			function()
			{
				Lightbox.closeRenameWindow();
				Lightbox.resetActionSeletor();
			}
		);		
	}	
	
	function lightboxMainScreenDeleteButton_onClick(language, lightbox)
	{
		Lightbox.showDeleteWindow(lightbox,
			function() 
			{
				Lightbox._delete(lightbox,
					function()
					{
						Lightbox.closeDeleteWindow();
						location.reload(true);
					}
				);
			},
			function(){
			 Lightbox.closeDeleteWindow(); 
            }
		);
	}
	
	function lightboxMainScreenEmptyButton_onClick(language, lightbox)
	{
		Lightbox.showEmptyWindow(lightbox, 
			function() 
			{
				Lightbox.empty(lightbox,
					function()
					{
						Lightbox.closeEmptyWindow();
				
						$('lightbox_name').onchange();
						
						if (Lightbox.isPreviewSelected())
						{
							$('lightbox_name_selector').onchange();
						}
					}
				);
			},
			function(){
			 Lightbox.closeEmptyWindow(); 
            }
			
		);	
	}
	
	function lightboxMainScreenAddToBasketButton_onClick(language, lightbox)
	{
		var addItemList = [];
		$A($('lightbox_content').getElementsByTagName('img')).each(
			function(imgEl)
			{
				if (Element.hasClassName(imgEl, 'imageDraggable'))
				{
					addItemList[addItemList.length] = Lightbox.getObjectId(imgEl);
				}
			}
		);
		Lightbox.showAddToBasketWindow(language, lightbox, 
			function() 
			{
				Lightbox.addAssetToBasket(lightbox, addItemList,
					function()
					{
						Lightbox.closeAddToBasketWindow();
						
						$('lightbox_name').onchange();
						
						Basket.initPreviewPanel(Basket.getBasketId(),
							function()
							{
								Basket.enableSlider();
								Basket.show();
								Lightbox.hide();
							}
						);
					}
				);
			} 
		);
	}
	
	function lightboxMainScreenEmailButton_onClick(lightbox, language)
	{
								Lightbox.showEmailWindow(Lightbox.getLightboxId(),
									function()
									{
										$('lightboxEmailFormErrors').innerHTML = "<span></span>";
										Lightbox.email(Lightbox.getLightboxId(), 'email', $('lightboxEmailWindowEmail').value, $('lightboxEmailWindowSubject').value, $('lightboxEmailWindowDescription').value, 
										function () {
											alert('Email successfully sent');
											Lightbox.closeEmailWindow();
										}, 
										function () {
											Lightbox.showEmailFormErrors(this.language);
										});
									},
									function()
									{
										Lightbox.closeEmailWindow();
									}
								);

	}
	
	function lightboxMainScreenDuplicateButton_onClick(language, lightbox)
	{
		Lightbox.showDuplicateWindow(lightbox,
			function() 
			{
				Lightbox.duplicate(lightbox, $('lightboxDuplicateWindowInput').value,
					function(id)
					{
						Lightbox.closeDuplicateWindow();
		
						Lightbox.showContent(id, '1', '1');
						
						if (Basket.isPreviewSelected())
						{
							Basket.showPreviewPanel();
						}								
						else
						{
							$('lightbox_name_selector').onchange();
						}	
					}
				);
			},
			function(){
			 Lightbox.closeDuplicateWindow(); 
            }
		);
	}
	
	function lightboxMainScreenItemRemoveButton_onClick(item, selected_lightbox_id, language)
	{

        Lightbox.removeAsset(selected_lightbox_id, item,
			function()
			{
                $('lightbox_name').onchange();
		   		if (Lightbox.isPreviewSelected())
				{
                	Lightbox.initPreviewPanel(Lightbox.getLightboxId());
				}
                
			}
		); 
	}

	function lightboxPreviewScreenAddToBasketButton_onClick(language)
	{
		Lightbox.showAddToBasketWindow(language, Lightbox.getSelectedId(),
			function() 
			{
				Lightbox.addToBasket(lightbox,
					function()
					{
						Lightbox.closeAddToBasketWindow();
						
						if ($('lightbox_name') != null)
						{
							$('lightbox_name').onchange();
						}
					}
				);
			} 
		);
	}
	
	function lightboxShowNotesButton_onClick(language, lightbox, asset)
	{	
		Lightbox.showNotesWindow(language, lightbox, asset, 
			function() 
			{
				Lightbox.saveNote(lightbox, $('lightboxNotesWindowInput').value, asset, 
					function()
					{					
						Lightbox.closeNotesWindow();
						
						if ($('lightbox_name') != null)
						{
							$('lightbox_name').onchange();
						}
						else
						{
							document.location.reload(true);
						}
					}
				);		
			}
		);	
	}
	
	function lightboxGridIcon_onClick(asset, lightbox_name)
	{
		/*
		if (typeof in_lightbox == 'undefined' || typeof browser == 'undefined') 
		{ 
			return false;
		}
		
        sequence_element = document.getElementsByName('lb_sequence');
		
        for (i = 0; i < sequence_element.length; i++)
       	{
			if (sequence_element[i].checked) 
			{
				sequence = sequence_element[i].value;
			}
		}
		*/
		
			sequence = 1;
		
			Lightbox.addAsset(Lightbox.getLightboxId(), asset, sequence,
				function()
				{
					if (Lightbox.isPreviewSelected())
					{
						Lightbox.expand();
					  				
						Lightbox.showPreview(Lightbox.getBasketId(),
							function()
							{
								Lightbox.showPreviewPanel();
								
								/*	
								if (sequence == 1)
								{
									Lightbox.scrollPreviewBottom();
								}
								else
								{
									Lightbox.scrollPreviewTop();
								}
								*/
							}
						);
					}
					
					Lightbox.changeGridIcon(true, asset, 'images/icons/Lightbox43_red.gif');
				}
			);

		/*
		if (Lightbox.getSelectedId() != null && Lightbox.getSelectedId() != '')
		{
			Lightbox.addItem(Lightbox.getLightboxId(), asset, sequence,
				function()
				{
					if (Lightbox.isPreviewSelected())
					{
						Lightbox.expand();
					  				
						Lightbox.showPreview(Lightbox.getSelectedId(),
							function()
							{
								Lightbox.showPreviewPanel();
										
								if (sequence == 1)
								{
									Lightbox.scrollPreviewBottom();
								}
								else
								{
									Lightbox.scrollPreviewTop();
								}
							}
						);
					}
					
					Lightbox.changeGridIcon(true, asset, 'images/icons/Lightbox43_red.gif');
				}
			);
		}
		else
		{
			Lightbox.create(lightbox_name,
				function(id)
				{
					//Lightbox.select(id);

					$('preview_selector').value = 'lightbox';
					$('preview_selector').onchange();
			
			    	Lightbox.addItem(Lightbox.getSelectedId(), asset, sequence,
						function()
						{
							if (Lightbox.isPreviewSelected())
							{
								Lightbox.expand();
					  				
						   		Lightbox.showPreview(Lightbox.getSelectedId(),
						  			function()
						   			{
										Lightbox.showPreviewPanel();
										
										if (sequence == 1)
										{
											Lightbox.scrollPreviewBottom();
										}
										else
										{
											Lightbox.scrollPreviewTop();
										}
						   			}
						   		);
					   		}
					   		
							Lightbox.changeGridIcon(true, asset, 'images/icons/Lightbox43_red.gif');
					   	}
			    	);
				}
			)
		}
		*/
		
		Lightbox.initPreviewPanel(Lightbox.getLightboxId());
		
		//added arranger panel
		Lightbox.initArrangerPanel(Lightbox.getLightboxId());
				
		if (browser.isIE && browser.version == 6)
		{ 
			return false;
		}
	}

	function removeAssetFromLightboxLink_onClick(asset)
	{
       	Lightbox.removeItem(Lightbox.getSelectedId(), asset,
	   		function()
	   		{
	   			if (Lightbox.isPreviewSelected())
	   			{
		        	Lightbox.showPreview(Lightbox.getSelectedId(),
		    			function()
		    			{
							Lightbox.showPreviewPanel();
		    			}
		        	);
	   			}

	   			if ($('lightbox_name') != null)
				{
					$('lightbox_name').onchange();
				}
				
   		       	Lightbox.changeGridIcon(false, asset, 'images/icons/Lightbox43.gif');
		   	}
        );
	}
	
	function lightboxNotes_onChange()
	{
		var max_len = 500;
		
		$('lightboxNotesCharsLeft').value = max_len - $('lightboxNotesWindowInput').value.length;
		
		if ($('lightboxNotesCharsLeft').value < 0)
		{
			$('lightboxNotesWindowInput').value = $('lightboxNotesWindowInput').value.substr(0, max_len);
			$('lightboxNotesCharsLeft').value = 0;
		}
	}


	newPage=1;
function Search()
{
	// *** VARS ***

	this.language = null;

	//

	// *** METHODS ***

	this.setLanguage = function(language)
	{
		this.language = language;
	}

	this.showSaveWindow = function(on_OK_button_action)
	{
		url = '?service=search&action=show_save_window&language=' + this.language;
		new Ajax.Updater('searchSaveWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('searchSaveWindow', on_OK_button_action);
			}
		});
	}

	this.closeSaveWindow = function()
	{
 		hideBox('searchSaveWindow');

	}

	this.processSaveForm = function()
	{
		if ($('searchSaveWindowIdSelect').value != '')
		{
			$('searchSaveWindowNameInput').value = $('searchSaveWindowIdSelect').options[$('searchSaveWindowIdSelect').selectedIndex].text;
			$('searchSaveWindowNameInput').disabled = true;
		}
		else
		{
			$('searchSaveWindowNameInput').disabled = false;
		}
	}

	this.save = function(saved_search, type, name, search_query, search_within, time_event, items_found, on_success_action, on_failure_action)
	{
		url = '?service=search&action=do_save&saved_search=' + saved_search + '&type=' + type + '&name=' + encodeURIComponent(name) + '&search_query=' + encodeURIComponent(search_query) + '&search_within=' + encodeURIComponent(search_within) + '&time_event=' + time_event + '&items_found=' + items_found + '&language=' + this.language;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;

				if (result == "true")
				{
					on_success_action();
				}
				else if (result == "false")
				{
					on_failure_action();
				}
				else
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			}
		});
	}


	this.showSaveWindowErrors = function()
	{
		url = '?service=search&action=show_save_window_errors&language=' + this.language;

		new Ajax.Updater('searchSaveWindowErrors', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.showSaveCompletedWindow = function(on_OK_button_action)
	{
		url = '?service=search&action=show_save_completed_window&language=' + this.language;
		new Ajax.Updater('searchSaveWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('searchSaveWindow', on_OK_button_action);
			}
		});
	}

	this.closeSaveCompletedWindow = function()
	{
		hideBox('searchSaveWindow');
	}

	this.showModifyWindow = function(saved_seach, on_complete_action, on_save_button_action, on_execute_button_action)
	{
		url = '?service=search&action=show_modify_window&language=' + this.language + '&saved_search=' + saved_seach;
		new Ajax.Updater('searchModifyWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('searchModifyWindow', on_save_button_action, on_execute_button_action);
				on_complete_action();
			}
		});

	}

	this.closeModifyWindow = function()
	{
		hideBox('searchModifyWindow');
	}

	this.deleteSavedSearch = function(saved_search, on_complete_action)
	{
		url = '?service=search&action=do_delete_saved_search&saved_search=' + saved_search;

		new Ajax.Request(url, {method: 'get', asynchronous:true,
			onSuccess: function(transport)
			{
				xml = transport.responseXML.documentElement;

				var response_code = xml.getElementsByTagName("code")[0].firstChild.nodeValue;

				if (response_code == 4)
				{
					document.location = '?service=error&action=show_db_error_page';
				}
			},
			onComplete:on_complete_action
		});
	}

	this.showDeleteConfirmationWindow = function(saved_search, on_OK_button_action)
	{
		url = '?service=search&action=show_delete_confirmation_window&language=' + this.language + '&saved_search=' + saved_search;
		new Ajax.Updater('searchDeleteConfirmationWindow', url, {method: 'get', asynchronous:true, evalScripts:true,
			onComplete: function()
			{
				showBox('searchDeleteConfirmationWindow', on_OK_button_action);
			}
		});
	}

	this.closeDeleteConfirmationWindow = function()
	{
		hideBox('searchDeleteConfirmationWindow');
	}

	this.showSavedSearchList = function(page)
	{
		url = '?service=search&action=show_saved_search_list&language=' + this.language + '&page=' + page;
		new Ajax.Updater('saved_search_list', url, {method: 'get', asynchronous:true, evalScripts:true});
	}

	this.storeGridLayout = function(grid_layout, grid_thumb, completeFunc, old_grid_layout, new_grid_layout) {
	    currentPage = getQuerystring('page');
		if(currentPage == ''){
			currentPage = 1;
		}
		if(parseInt(old_grid_layout) < parseInt(new_grid_layout)){
			tt = new_grid_layout / old_grid_layout;
			newPage = Math.ceil(currentPage/tt);
		
		completeFunc=function(){document.location=document.location+'&page='+newPage;};
		}

		
		
	    url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout + '&grid_thumb=' + grid_thumb;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true, onComplete: completeFunc });
	}
	

	this.storeBackgroundColor = function(color)
	{
	    url = '?service=user&action=do_store_background_color&color=' + escape(color);
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true
		});
	}

	this.showQuickSearchResultPage = function(service, action, mode, q, qw, page, grid_layout, grid_thumb)
	{
		language = this.language;
		var extra='';
		if(getQuerystring('licence_type_rm') == '1'){
		extra = extra + '&licence_type_rm=1';
		}
		if(getQuerystring('licence_type_rf') == '1'){
		extra = extra + '&licence_type_rf=1';
		}


	    url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout + '&grid_thumb=' + grid_thumb;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function()
			{
				document.location = '?service=' + service + '&action=' + action + '&language=' + language + '&mode=' + mode + '&q=' + unescape(q) + '&qw=' + unescape(qw) + '&page=' + page + '&grid_layout=' + grid_layout + '&grid_thumb=' + grid_thumb + extra;
			}
		});
	}


	this.showQuickSearchResultPageOld = function(service, action, mode, q, qw, page, grid_layout)
	{
		language = this.language;

	    url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function()
			{
				document.location = '?service=' + service + '&action=' + action + '&language=' + language + '&mode=' + mode + '&q=' + unescape(q) + '&qw=' + unescape(qw) + '&page=' + page + '&grid_layout=' + grid_layout;
			}
		});
	}

	this.disableAdvancedSearchForm = function()
	{
		if($('title')) {$('title').disabled = true;}
		if($('description')) {$('description').disabled = true;}
		if($('keywords')) {$('keywords').disabled = true;}
		if($('photographer')) {$('photographer').disabled = true;}
		if($('dateFrom')) {$('dateFrom').disabled = true;}
		if($('dateEnd')) {$('dateEnd').disabled = true;}
		if($('timePeriod')) {$('timePeriod').disabled = true;}
		if($('resetButton')) {$('resetButton').disabled = true;}
	}

	this.enableAdvancedSearchForm = function()
	{
		if($('title')) {$('title').disabled = false;}
		if($('description')) {$('description').disabled = false;}
		if($('keywords')) {$('keywords').disabled = false;}
		if($('photographer')) {$('photographer').disabled = false;}
		if($('dateFrom')) {$('dateFrom').disabled = false;}
		if($('dateEnd')) {$('dateEnd').disabled = false;}
		if($('timePeriod')) {$('timePeriod').disabled = false;}
		if($('resetButton')) {$('resetButton').disabled = false;}
	}

	// *** EVENTS ***

	this.pageHeader_saveSearchButton_onClick = function()
	{
		Search.showSaveWindow(
			function()
			{
			     if($('searchSaveWindowIdSelect')){
			         var a = $('searchSaveWindowIdSelect').value;
                 }else{
                    var a = '';  
                 }

			     if($('searchTypeHidden')){
			         var b = $('searchTypeHidden').value;
                 }else{
                    var b = '';  
                 }
			     if($('searchSaveWindowNameInput')){
			         var c = $('searchSaveWindowNameInput').value;
                 }else{
                    var c = '';  
                 }
			     if($('searchTextInput')){
			         var d = $('searchTextInput').value;
                 }else{
                    var d = '';  
                 }
			     if($('searchTextWithin')){
			         var e = $('searchTextWithin').value;
                 }else{
                    var e = '';  
                 }
			     if($('searchSaveWindowTimeEventSelect')){
			         var f = $('searchSaveWindowTimeEventSelect').value;
                 }else{
                    var f = '';  
                 }
			     if($('itemsFound')){
			         var g = $('itemsFound').value;
                 }else{
                    var g = '';  
                 }                                                                                                      

				
                Search.save(
                a,
                b, 
                c, 
                d, 
                e, 
                f, 
                g,
					// on success
					function()
					{
						Search.closeSaveWindow();
						Search.showSaveCompletedWindow(
							// ok
							function()
							{
								Search.closeSaveCompletedWindow();
							}
							//
						);
					},
					//
					// on failure
					function()
					{
						Search.showSaveWindowErrors();
					}
					//
				);
			}
		);
	}

	this.pageHeader_modifySearchButton_onClick = function()
	{
		Search.showModifyWindow($('userSearchIdHidden').value,
			// on complete
			function()
			{
				datePickerController.refresh();
			},
			//
			// on save
			function()
			{
				//
				search_type = $('searchType').value;

				search_query = (search_type == 'QS') ? $('searchModifyWindowQueryInput').value : $('advancedSearchForm').serialize();
				search_within = (search_type == 'QS') ? $('searchModifyWindowQueryWithinInput').value : '';
				//

				Search.save($('userSearchIdHidden').value, search_type, $('searchModifyWindowNameInput').value, search_query, search_within, $('searchModifyWindowTimeEventSelect').value, '',
					// on save
					function()
					{
						Search.closeModifyWindow();
						Search.showSaveCompletedWindow(
							// ok
							function()
							{
								Search.closeSaveCompletedWindow();
							}
							//
						);
					},
					//
					// on failure
					function()
					{
						Search.showSaveWindowErrors();
					}
					//
				);
			},
			//
			// on execute
			function()
			{
				//
				search_type = $('searchType').value;

				search_query = (search_type == 'QS') ? $('searchModifyWindowQueryInput').value : $('advancedSearchForm').serialize();
				search_within = (search_type == 'QS') ? $('searchModifyWindowQueryWithinInput').value : '';
				//

				Search.savedSearchPage_executeSavedSearch_onClick($('userSearchIdHidden').value, $('searchType').value, $('languageCode').value, search_query, search_within);
			}
			//
		);
	}

	this.savedSearchPage_modifyButton_onClick = function(saved_search, page)
	{
		Search.showModifyWindow(saved_search,
			// on complete
			function()
			{
				datePickerController.refresh();
			},
			//
			// on save
			function()
			{
				//
				search_type = $('searchType').value;

				search_query = (search_type == 'QS') ? $('searchModifyWindowQueryInput').value : $('advancedSearchForm').serialize();
				search_within = (search_type == 'QS') ? $('searchModifyWindowQueryWithinInput').value : '';
				//

				Search.save(saved_search, search_type, $('searchModifyWindowNameInput').value, search_query, search_within, $('searchModifyWindowTimeEventSelect').value, '',
					// on save
					function()
					{
						Search.closeModifyWindow();
						Search.showSaveCompletedWindow(
							// ok
							function()
							{
								Search.closeSaveCompletedWindow();
								Search.showSavedSearchList(page);
							}
							//
						);
					},
					//
					// on failure
					function()
					{
						Search.showSaveWindowErrors();
					}
					//
				);
			},
			//
			// on execute
			function()
			{
				//
				search_type = $('searchType').value;

				search_query = (search_type == 'QS') ? $('searchModifyWindowQueryInput').value : $('advancedSearchForm').serialize();
				search_within = (search_type == 'QS') ? $('searchModifyWindowQueryWithinInput').value : '';
				//

				Search.savedSearchPage_executeSavedSearch_onClick(saved_search, $('searchType').value, $('languageCode').value, search_query, search_within);
			}
			//
		);
	}

	this.advancedSearchFormPage_savedSearchListSelect_onClick = function()
	{
		if ($('searchSaveWindowIdSelect').value != '')
		{
			Search.disableAdvancedSearchForm();
		}
		else
		{
			Search.enableAdvancedSearchForm();
		}
	}

	this.advancedSearchFormPage_submitButton_onClick = function()
	{
		if ($('searchSaveWindowIdSelect') != null && $('searchSaveWindowIdSelect').value != '') {
			params = $('searchSaveWindowIdSelect').value.split('|');
			Search.savedSearchPage_executeSavedSearch_onClick(params[0], params[1], params[2], params[3], '');
	
		} else if ($('recentSaveWindowIdSelect') != null && $('recentSaveWindowIdSelect').value != '') {
			params = $('recentSaveWindowIdSelect').value.split('|');
			Search.recentSearchPage_executeRecentSearch_onClick(params[0], params[1], params[2], params[3], params[4]);
		} else {
			$('advancedSearchForm').submit();
		}
	}

	this.savedSearchPage_executeSavedSearch_onClick = function(saved_search, type, language, q, within)
	{
		if (type == 'QS')
		{
			document.location = '?service=search&action=do_quick_search&language=' + language + '&q=' + q + '&saved_search=' + saved_search + '&qw=' + within;
		}
		else
		{
			document.location = '?service=search&action=do_advanced_search&language=' + language + '&' + q + '&saved_search=' + saved_search;
		}
	}

	this.recentSearchPage_executeRecentSearch_onClick = function(saved_search, type, language, q, within) {
	if(within == undefined){within='';}
		if (type == 'QS') {
			document.location = '?service=search&action=do_quick_search&language=' + language + '&q=' + q + '&qw=' + within;
		} else {
			document.location = '?service=search&action=do_advanced_search&language=' + language + '&' + q;
		}
	}



	this.savedSearchPage_deleteSavedSearch_onClick = function(saved_search, page)
	{
		Search.showDeleteConfirmationWindow(saved_search,
			function()
			{
				Search.closeDeleteConfirmationWindow();
				Search.deleteSavedSearch(saved_search,
					// on complete
					function()
					{
						Search.showSavedSearchList(page);
					}
				);
			}
		);
	}
	//
	
	this.savedQuickSearchFilter = function(mdConfigId, value)
	{
		var params = "md_congif_id="+mdConfigId+"&value="+value;
		var rq = new Ajax.Request("/en/search/update_quicksearch_filter.html", {parameters: params, evalScripts:true});
	}
}

// *** OBJECT ***

var Search = new Search();

//

//here form name is included
	function showAdvancedSearchPage(currentUrl, qw, page, grid_layout)
	{
		url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function()
			{
				document.location = currentUrl + '&qw=' + unescape(qw) + '&page=' + page + '&grid_layout=' + grid_layout;
			}
		});
	}

	function showKeywordSearchPage(service, action, language, page, grid_layout)
	{
	    url = '?service=user&action=do_store_grid_layout&layout=' + grid_layout;
		new Ajax.Request(url, {method: 'get', asynchronous:true, evalScripts:true,
			onSuccess: function()
			{
				document.location = '?service=' + service + '&action=' + action + '&language=' + language + '&page=' + page + '&grid_layout=' + grid_layout;
			}
		});
	}
	
	
	function setFormValue(form_id, field_name, field_column, field_value) 
	{
		var params = "form_id="+form_id+"&field_name="+field_name+"&field_column="+field_column+"&field_value="+field_value;
		var rq = new Ajax.Request("?service=search&action=update_form_value", {parameters: params, evalScripts:true});
	}

	function setSessionValue(session_id, field_value) 
	{
		var params = "session_id="+session_id+"&field_value="+field_value;
		var rq = new Ajax.Request("?service=search&action=update_session_value", {parameters: params, evalScripts:true});
	}
function getQuerystring(key, default_)
{
  if (default_==null) default_="";
  key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
  var qs = regex.exec(window.location.href);
  if(qs == null)
    return default_;
  else
    return qs[1];
}



function Gallery()
{
	this.newPopupWindow = function(setId)
	{
   	    
   	    url = '?service=gallery&action=show_slideshow_page&language=en&gallery=1&set=' + setId;
   	    var slideshow_width = 850;
		var slideshow_height = 687;
		var slideshow_scroll = 1;
		var slideshow_resizeable = 1;
		var win_left = (screen.width - slideshow_width) / 2;
		var win_top = (screen.height - slideshow_height) / 2;
		var winprops = 'address=no,menubar=no,toolbar=no,height='+slideshow_height+',width='+slideshow_width+',top='+win_top+',left='+win_left+',scrollbars='+slideshow_scroll+',resizable='+slideshow_resizeable;
		
				 
   	    //commented working..
   	    browser=navigator.appName;
   		browserindex = browser.search(/Netscape/);
		if(browserindex >= '0')
		{
		
   	    	//window.open(url, 'viewSlideShow','width=550, height=480');
   	    	win = window.open(url, 'viewSlideShow',winprops);
   	    	if (parseInt(navigator.appVersion) >= 4) 
			{ 
				win.window.focus(); 
			}
   	    	
   	    }
   	    else
   	    {
   	    	window.open(url, 'viewSlideShow', winprops);
   	    	//win = window.open(url, 'viewSlideShow', winprops);
   	    	//if (parseInt(navigator.appVersion) >= 4) 
			//{ 
				//win.window.focus(); 
			//}
   	    	
   	    }
        return false;
   	   
  	}
	
	this.setNewGallery = function(setId)
	{
		gallery_id = setId.value;
		//alert('new gallery id is '+setId.value);
		url = '?service=gallery&action=show_slideshow_page&language=en&gallery=1&set=' + gallery_id;
   	    window.location = url;
	}
	
	this.share = function()
	{
		document.location.href = 'mailto:?body=' + encodeURIComponent($('gallery-share-url').value);
	}
	
	this.searchImage = function(image)
	{
		url = "?service=search&action=do_quick_search&language=en&mime_type=all&q='"+image+"'";
		window.opener.location.href = url;
		window.opener.focus();
	}

}

// *** OBJECT ***

var Gallery = new Gallery();

//



	function nextvvc(vvcs, vvcids, vvcitemid, vvctext, vvcid, vvctitle,vvcratios) {
		var vvcimgelement = null;
		var itemType = '';
        
		$A($(vvcitemid).getElementsByTagName('img')).each(
				function(element)
				{
					var idVal = element.id+'';
					if (idVal.search('grid-item_') != -1) {
						vvcimgelement = element;
						itemType = idVal.substr(10,1);
					}
				}
			);
        
		var vvcelementsrcrel = vvcimgelement.getAttribute('rel');
        
		var newrel = 0;
		if((parseInt(vvcelementsrcrel) + 1) == vvcs.length) {
			newrel = 0;
		} else {
			newrel = parseInt(vvcelementsrcrel) + 1;
		}
		
		vvcimgelement.src = vvcs[newrel];
		vvcimgelement.setAttribute('rel',newrel);
		vvcimgelement.setAttribute('assetid',vvcids[newrel]);
        vvcimgelement.setAttribute('title',vvctitle[newrel]);

        
        
		$A($(vvcitemid).getElementsByTagName('*')).each(
				function(element)
				{
					var idVal = element.id+'';
					if (idVal.search(vvcids[vvcelementsrcrel]+'') != -1) {
						var newId = idVal.replace(vvcids[vvcelementsrcrel]+'', vvcids[newrel]+'');
						element.id = newId;
					}
				}
			);
		
        $$('#assetLink_'+vvcids[newrel]).each (function(el){el.setAttribute('assetid',vvcids[newrel]);});
        $$('#assetLink_'+vvcids[newrel]).each (function(el){el.setAttribute('assettype',itemType);});
        
            
            var vvcelementsrcoffset = vvcimgelement.getAttribute('offset');
                var vtotal = vvcids.length;
                var displayrel = newrel - vvcelementsrcoffset;
                if(displayrel >= 1){               
                } else {
                    displayrel = parseInt(displayrel) + parseInt(vtotal);
                }
    		$A($(vvcitemid).getElementsByTagName('span')).each(
    	    	function(el) {
					var idVal = el.id+'';
					if (idVal.search('spanvvc') != -1) {
						el.innerHTML =  displayrel;
					}
    	    	});
                
		$$('#divvvc'+vvcids[newrel]).each(
		function (el) {
			el.innerHTML = vvctext[newrel];
		});
		$$('#idvvc'+vvcids[newrel]).each(
		function (el) {
			el.innerHTML = vvcid[newrel];
		});
        
        // set the alt attribute of the autozoom image to the new image URL. 
        // Ensures autozoom will display the new image, not the old one
        $$('#'+vvcids[newrel]).each(function(el){
            url = '?service=asset&action=show_preview&asset=' + vvcids[newrel];
            el.alt = url;
        });
		

		if (Lightbox) {
 		Lightbox.initPreviewPanel(Lightbox.getLightboxId(),function(){});

			visible = false;
			if ($('lightbox-minimize')) {
				var visible = $('lightbox-minimize').style.display != 'none';
			}
			if (Lightbox.isPreviewSelected())
			{
				if (visible) {
					Lightbox.enableSlider();
				}
			}
		}

		if (Basket) {
			Basket.initPreviewPanel(Basket.getBasketId(),function(){});		
			visible = false;
			if ($('basket-minimize')) {
				visible = $('basket-minimize').style.display != 'none';
			}
			if (Basket.isPreviewSelected())
			{
				if (visible) {
					Basket.enableSlider();
				}
			}
		}

        // recompute image positioning
        $(vvcimgelement).observe("load",function(){
            adjustImagePanelHeights(vvcimgelement);
        });
       
	}

function adjustImagePanelHeights(changedImage)
{
    // the images may need realigning vertically in their grid panel.
    // this is because the images are position:static in IE to fix
    // grid stacking issue, and so can't have bottom:0 set.
    
    if(Prototype.Browser.IE){
            var changedImages = [];
            if(changedImage != null)
            {
                changedImages.push(changedImage);
            }
            else
            {
                changedImages = $$('.mainThumbImage');
            }
    
            $A(changedImages).each(function(el){
                $(el).observe("load",function(){
                // for each thumbnail...
               var imageLink = el.parentNode;           // the link for the image
               var pictureBox = imageLink.parentNode;   // the surrounding box for the image
               
               // set the position to static (this is the main fix)
               $(el).setStyle({"position":"static"});
               $(pictureBox).setStyle({"position":"static"});
               
               // because position is static, need another way to align the images to the bottom of picturebox
               // ...use computed top padding for this
               $(imageLink).setStyle({"paddingTop":"0px"});
               var imageHeight = $(imageLink).getHeight();      // height of the link
               var margin = parseInt($(el).getStyle("marginTop").replace("px","")); // top margin of the image
               var imageWidth = $(el).getWidth();               // width of the image
               
               // put all this together to get the amount needed for top padding
               
               var topGap = $(pictureBox).getHeight() - parseInt($(pictureBox).getStyle("paddingTop").replace("px","")) - imageHeight + margin;
               /*if(typeof console != "undefined") console.log(
                    $(pictureBox).getHeight(),
                    " ",
                    parseInt($(pictureBox).getStyle("paddingTop").replace("px","")),
                    " ",imageHeight," ",margin);*/
               
               // apply the style
               // also set width of the link to shrink to the width of the image, as now it's block, not inline
               $(imageLink).setStyle({"paddingTop":topGap+"px","width":imageWidth});
               });
            });
        }   
    
}
nextObject = function(n) {
do n = n.nextSibling;
while (n && n.nodeType != 1);
return n;
}
	function prevvvc(vvcs, vvcids, vvcitemid, vvctext, vvcid, vvctitle,vvcratios) {
		var vvcimgelement;
		var itemType = '';
		$A($(vvcitemid).getElementsByTagName('img')).each(
				function(element)
				{
					var idVal = element.id+'';
					if (idVal.search('grid-item_') != -1) {
						vvcimgelement = element;
						itemType = idVal.substr(10,1);
					}
				}
			);
        
		var vvcelementsrcrel = vvcimgelement.getAttribute('rel');
		var newrel = 0;
		if((parseInt(vvcelementsrcrel)) == 0) {
			newrel = vvcs.length - 1;
		} else {
			newrel = parseInt(vvcelementsrcrel) - 1;
		}
		
		vvcimgelement.src = vvcs[newrel];
		vvcimgelement.setAttribute('rel',newrel);
		vvcimgelement.setAttribute('assetid',vvcids[newrel]);
        vvcimgelement.setAttribute('title',vvctitle[newrel]);



        
		$A($(vvcitemid).getElementsByTagName('*')).each(
				function(element)
				{
					var idVal = element.id+'';
					if (idVal.search(vvcids[vvcelementsrcrel]+'') != -1) {
						var newId = idVal.replace(vvcids[vvcelementsrcrel]+'', vvcids[newrel]+'');
						element.id = newId;
					}
				}
			);

        $$('#assetLink_'+vvcids[newrel]).each (function(el){el.setAttribute('assetid',vvcids[newrel]);});
        $$('#assetLink_'+vvcids[newrel]).each (function(el){el.setAttribute('assettype',itemType);});
		
            var vvcelementsrcoffset = vvcimgelement.getAttribute('offset');
                var vtotal = vvcids.length;
                var displayrel = newrel - vvcelementsrcoffset;
                if(displayrel >= 1){               
                } else {
                    displayrel = parseInt(displayrel) + parseInt(vtotal);
                }
    		$A($(vvcitemid).getElementsByTagName('span')).each(
    	    	function(el) {
					var idVal = el.id+'';
					if (idVal.search('spanvvc') != -1) {
						el.innerHTML =  displayrel;
					}
    	    	});
        
		$$('#divvvc'+vvcids[newrel]).each(
		function (el) {
			el.innerHTML = vvctext[newrel];
		});
		$$('#idvvc'+vvcids[newrel]).each(
		function (el) {
			el.innerHTML = vvcid[newrel];
		});
        
        // set the alt attribute of the autozoom image to the new image URL. 
        // Ensures autozoom will display the new image, not the old one
        $$('#'+vvcids[newrel]).each(function(el){
            url = '?service=asset&action=show_preview&asset=' + vvcids[newrel];
            el.alt = url;
        });
        
		
        if (Lightbox) {
		  
 		Lightbox.initPreviewPanel(Lightbox.getLightboxId(),function(){});

			visible = false;
			if ($('lightbox-minimize')) {
				var visible = $('lightbox-minimize').style.display != 'none';
			}
			if (Lightbox.isPreviewSelected())
			{
				if (visible) {
					Lightbox.enableSlider(100);
				}
			}
		}

		if (Basket) {
			Basket.initPreviewPanel(Basket.getBasketId(),function(){});		
			visible = false;
			if ($('basket-minimize')) {
				visible = $('basket-minimize').style.display != 'none';
			}
			if (Basket.isPreviewSelected())
			{
				if (visible) {
					Basket.enableSlider(100);
				}
			}
		}
        
        // recompute image positioning
        $(vvcimgelement).observe("load",function(){
            adjustImagePanelHeights(vvcimgelement);
        });
     
	}

	function setInnerHTML(element,html,count){
		setTimeout(function(){element.innerHTML=html;}, 50);

		return false;
	}

	function countvalues(a) {
	var b = {}, i = a.length, j;
	while( i-- ) {
	j = b[a[i]];
	b[a[i]] = j ? j+1 : 1;
	}
	return b;
	}

	var alertTimerId = 0;


	function TimerStart(func, time)
	{
	  alertTimerId = setTimeout ( func,time );
	  return alertTimerId;
	}

	function TimerStop (timers) {
		clearTimeout ( timers );
	}

	function handlePrice(item) {
	}

	function init_grid() {
		addOnClickEvents();
	}
	var lastPanel = 'lightbox';
	var lastsize='max';
	var showsim='0';
	function addMainThumbOnClick(element) {
		element.onclick = function() {
		
 
			var idVal = this.id+'';
			var itemNumber = parseInt(idVal.substr(12));
			noclear = 1;
			setTimeout(function() {
			element.toggleClassName('clicked2');
			
			if(Similars) {
				if(Element.hasClassName(element, 'clicked2')){
				    temp = 0;
				    $$('.clicked2').each(function(el,index){
				        temp++;
				    });
				    
				    if(temp == 1){
				        Similars.initPreviewPanel(itemNumber, function(){
				            if($('autoShowSimilars')) {
				            if($('autoShowSimilars').value == 1) {
				            	if(Similars.countSimilars() > 0) {

					                if($('basket-preview-panel')){
					                	if($('basket-preview-panel').style.display == 'none'){

					                	}else{
					                		lastPanel = 'basket';
					                		if($('basket-maximize').style.display == 'none') {
					                			lastsize='max';
					                		} else {
					                			lastsize='min';
					                		}
					                		
					                	}
					                }
					                if($('lightbox-preview-panel')){
					                	if($('lightbox-preview-panel').style.display =='none'){
					                	}else{
					                		lastPanel = 'lightbox';
					                		if($('lightbox-maximize').style.display == 'none') {
					                			lastsize='max';
					                		} else {
					                			lastsize='min';
					                		}

					                		
					                	}
					                }
					                Similars.enableSlider();
					                Similars.show();

					                
					                if($('basket-preview-panel-content')){Basket.hide();}
					                Lightbox.hide();
					                Similars.maximize();
					                showSim=1;
					                
				            	}else if(1==showSim) {
				            	showSim=0;
				            		if(lastPanel == 'lightbox'){
										Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
											function() {
												Lightbox.show();
												object.hide();
												Lightbox.enableSlider();
												if(getCookie("maximized")==1) {
													Lightbox.maximize();
												} else {
													Lightbox.minimize();
												}
											}
										);
											
									}
									
									if(lastPanel == 'basket') {
										Basket.initPreviewPanel(Basket.getBasketId(),
											function() {
												try{
    	            		                		Basket.show();
		                    		            }catch(e){}
        		                    		    try{
													object.hide();
                    		    		        }catch(e){}
                            		    		try{
													Basket.enableSlider();
													if(getCookie("maximized")==1) {
														Basket.maximize();
													} else {
														Basket.minimize();
													}
												}catch(e){}
											}
										);
									}
				            		}
				            	
				            }
				            }
				        });
				    }
				}else{
				    temp = 0;
				    $$('.clicked2').each(function(el,index){
				        temp++;
				        lastid = el.id;
				    });
				    if(temp == 1){
				        arrayids = lastid.split('_');
				        Similars.initPreviewPanel(arrayids[2], function(){
				            if($('autoShowSimilars')) {
				            if($('autoShowSimilars').value == 1) {
				            	if(Similars.countSimilars() > 0) {

					                if($('basket-preview-panel')){
					                	if($('basket-preview-panel').style.display !='none'){
					                		lastPanel = 'basket';
					                		if($('basket-maximize').style.display == 'none') {
					                			lastsize='max';
					                		} else {
					                			lastsize='min';
					                		}
					                		
					                	}
					                }
					                if($('lightbox-preview-panel')){
					                	if($('lightbox-preview-panel').style.display !='none'){
					                		lastPanel = 'lightbox';
					                		if($('lightbox-maximize').style.display == 'none') {
					                			lastsize='max';
					                		} else {
					                			lastsize='min';
					                		}

					                		
					                	}
					                }

					                Similars.enableSlider();
					                Similars.show();

					                
					                if($('basket-preview-panel-content')){Basket.hide();}
					                Lightbox.hide();
					                Similars.maximize();
				            	}else{
				            		if(lastPanel == 'lightbox'){
										Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
											function() {
												Lightbox.show();
												object.hide();
												Lightbox.enableSlider();
												if(getCookie("maximized")==1) {
													Lightbox.maximize();
												} else {
													Lightbox.minimize();
												}
											}
										);
											
									}
									
									if(lastPanel == 'basket') {
										Basket.initPreviewPanel(Basket.getBasketId(),
											function() {
												try{
    	            		                		Basket.show();
		                    		            }catch(e){}
        		                    		    try{
													object.hide();
                    		    		        }catch(e){}
                            		    		try{
													Basket.enableSlider();
													if(getCookie("maximized")==1) {
														Basket.maximize();
													} else {
														Basket.minimize();
													}
												}catch(e){}
											}
										);
									}
				            		}
				            	
				            }
				            }
				        });

				        
				        
				        
				        
				        
				        
				        
				        
				    }else{

				            		if(lastPanel == 'lightbox'){
										Lightbox.initPreviewPanel(Lightbox.getLightboxId(),
											function() {
												Lightbox.show();
												Similars.hide();
												Lightbox.enableSlider();
												if(getCookie("maximized")==1) {
													Lightbox.maximize();
												} else {
													Lightbox.minimize();
												}
											}
										);
											
									}
									
									if(lastPanel == 'basket') {
										Basket.initPreviewPanel(Basket.getBasketId(),
											function() {
												try{
    	            		                		Basket.show();
		                    		            }catch(e){}
        		                    		    try{
													Similars.hide();
                    		    		        }catch(e){}
                            		    		try{
													Basket.enableSlider();
													if(getCookie("maximized")==1) {
														Basket.maximize();
													} else {
														Basket.minimize();
													}
												}catch(e){}
											}
										);
									}



				    }
				}
			}
            
            // update totals (e.g. "Similars (0)")
            if(Lightbox) Lightbox.updateTotals();
            if(Basket) Basket.updateTotals();
            
			},100);
			noclear=0;
 

		}
	}
	
	function addActionsOnClick(element, itemNumber, type) {
		element.onclick = function() {
			noclear=1;
			
			if(document.getElementById('picturepopmenuback_'+itemNumber).style.display =='none'){
				var newHeight = $('grid-item_'+type+'_'+itemNumber).height;
				var newWidth = $('grid-item_'+type+'_'+itemNumber).width;
			
				newMargin = newHeight + 9;
				newMargin = newMargin * -2;
				newHeight.toString();
				newHeight = newHeight + 'px';
				newWidth.toString();
				newWidth = newWidth + 'px';
				newMargin.toString();
				newMargin = newMargin + 'px 0 0 0';
			
				$('picturepopmenuback_'+itemNumber).setStyle({'width':newWidth});
				$('picturepopmenuback_'+itemNumber).style.display = '';
			}
			else {
				$('picturepopmenuback_'+itemNumber).style.display = 'none';
			}
			noclear=0;	
		}
	}
	
	function addAssetLinkEvents(element, itemNumber, type) {
		switch(type) {
			case 'F':
				element.href='?service=feature&action=show_content_page&language=en&feature='+itemNumber;
				break;
			case 'C':
				element.href='?service=cd&action=show_content_page&language=en&cd='+itemNumber;
				break;
			default:
				element.ondblclick = function() {
					noclear=1; 
					Asset.zoomPopup(itemNumber, 'grid', 'grid-item_'+type+'_'+itemNumber, grid_item_list_text); 
					noclear=0;
				}
				
				imgId=element.id.replace('assetLink','grid-item');
				
				$(imgId).onmouseover = function() {
					Asset.showAutoZoomWindow(itemNumber, element);
				}
				imgId=element.id.replace('assetLink_A_','');
				
				$(imgId).ondblclick = function() {
					noclear=1; 
					Asset.zoomPopup(itemNumber, 'grid', 'grid-item_'+type+'_'+itemNumber, grid_item_list_text); 
					noclear=0;
				}				
				
				break;
		}
	}

	function addPopMenuEvents(element, itemNumber) {
		element.onmouseout = function() {
			this.rel=TimerStart(
				function() {
					$('picturepopmenuback_'+itemNumber).style.display = 'none';
				}
				,3000
			);
		}
		element.onmouseover = function() {
			TimerStop(this.rel);
		}
	}

	function addOnClickEvents() {
		$A($('mainContent').getElementsByTagName('img')).each(
			function(element)
			{
				var id = element.id+'';
				if (id.search('grid-item_') != -1) {
					addMainThumbOnClick(element);
				}
			}
		);
		$A($('mainContent').getElementsByTagName('a')).each(
			function(element)
			{
				var id = element.id+'';
				if (id.search('menu_icon_link_') != -1) {
					var itemType = id.substr(15, 1);
					var itemNumber = parseInt(id.substr(17));
					addActionsOnClick(element, itemNumber, itemType);
				}
				else if (id.search('assetLink_') != -1) {
					var itemType = id.substr(10, 1);
					var itemNumber = parseInt(id.substr(12));
					addAssetLinkEvents(element, itemNumber, itemType);
				}
			}
		);
		$A($('mainContent').getElementsByTagName('div')).each(
			function(element)
			{
				var id = element.id+'';
				if (id.search('picturepopmenuback_') != -1) {
					var itemNumber = parseInt(id.substr(19));
					addPopMenuEvents(element, itemNumber);
				}
			}
		);
	}
	
	function ajaxAssetImages() {
		$A($('mainContent').getElementsByTagName('a')).each(
			function(element)
			{
				var id = element.id+'';
				if (id.search('assetLink_') != -1) {
					if (element.rel != '') {
						var itemType = id.substr(10, 1);
						var itemNumber = parseInt(id.substr(12));
						var parts = element.rel.split('|');
						setThumbSource('grid-item_'+itemType+'_'+itemNumber, parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]);
					}
				}
			}
		);
	}
	
	function setThumbSource(imgId, folderName, secureFileName, ratio, fileExtension, baseType, subType, selectedGridThumbId) {
		var params = 'folderName='+folderName+'&secureFileName='+secureFileName+'&ratio='+ratio+'&fileExtension='+fileExtension+'&baseType='+baseType+'&subType='+subType+'&selectedGridThumbId='+selectedGridThumbId;
		var url = "?service=asset&action=get_thumb_path";
		var id = imgId;
		//if($(id).src2 !=''){
		//	$(id).src = $(id).src2;
		//} else {
		//new Ajax.Request(url, {method: 'post', asynchronous:true, parameters:params,
//			onSuccess: function(transport)
//			{
//				$(id).src = transport.responseText;
//			}
//		});
//		}
	}
	
	function openPriceWindow(item, usage_code, ms_menus, target) {
		if ($('basket-preview-panel')) {
			var winRef = window.open('?service=pricebook&action=show_media_selector_page&item='+item+'&base_type=image&sub_type=jpeg&usage_code='+usage_code+'&ms_menus='+ms_menus+'&target='+target, 'usage', 'left=0, top=0, width=700, height=800, menubar=0, toolbar=0, scrollbars=1, alwaysRaised=0'); 
			winRef.focus(); 
			return false;
		}
		else {
			alert('Please login to use this feature.'); 
		}
	}
	
//MJL


 

function lightboxLinkOnClick(element){

    if(Lightbox.isOwner() == false)
    {
        Lightbox.showNotOwnerError();
        return false;   
    }
	LightboxId = Lightbox.getLightboxId();
	if (LightboxId < 1){return false;}
	sequence =  Lightbox.getSequence();
	
	Lightbox.addAsset(
		LightboxId,
		Lightbox.getObjectId(element),
		sequence,
		function() {
			Lightbox.initPreviewPanel(
				LightboxId,
				function() {
					Lightbox.enableSlider();
					Lightbox.show();
					Basket.hide();
				}
			);
		}
	);
	
	$jq('.clicked2').each(
		function(index){
			$jq(this).removeClass('clicked');
			$jq(this).removeClass('clicked2');
			Lightbox.addAsset(
				LightboxId,
				Lightbox.getObjectId(this),
				sequence,
				function() {
					Lightbox.initPreviewPanel(
						LightboxId,
						function() {
							Lightbox.enableSlider();
							Lightbox.show();
							Basket.hide();
						}
					);
				}
			);
		}
	);	
}

function basketLinkOnClick(element){
	if ($('basket-preview-panel')) {
		if (!Basket) { return false; }
		var sequence = Basket.getSequence();
		var type = Basket.getItemType(element);
		var basketId = Basket.getBasketId();
		switch(type) {
			case 'F':
				Basket.addFeature(
					basketId,
					Basket.getObjectId(element),
					sequence,
					function() {
						Basket.initPreviewPanel(basketId);
					}
				);		
			break;
			case 'C':
				Basket.addCd(
					basketId,
					Basket.getObjectId(element),
					sequence,
					function() {
						Basket.initPreviewPanel(basketId);
					}
				);		
			break;
			case 'A':
			default:
				Basket.addAsset(
					Basket.getBasketId(),
					Basket.getObjectId(element),
					sequence,
					function() {
						Basket.initPreviewPanel(
							Basket.getBasketId(),
							function() {
								Basket.enableSlider();
								Basket.show();
								Lightbox.hide();
							}
						);
					}
				);
 
				
				$jq('.clicked2').each(
					function(index){
						this.removeClassName('clicked');
						this.removeClassName('clicked2');
						if (Basket.getObjectId(this) != Basket.getObjectId(element)) {
							Basket.addAsset(
								Basket.getBasketId(),
								Basket.getObjectId(this),
								sequence,
								function() {
									Basket.initPreviewPanel(
										Basket.getBasketId(),
										function() {
											Basket.enableSlider();
											Basket.show();
											Lightbox.hide();
										}
									);
								}
							);
 
						}
					}
				);
			break;
		}
	} else {
		alert('Please login to use this feature.'); 
	}
}



	
	
