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

var Prototype = {
  Version: '1.5.0',
  BrowserFeatures: {
    XPath: !!document.evaluate
  },

  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
  emptyFunction: function() {},
  K: function(x) { return x }
}

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

var Abstract = new Object();

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

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

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

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

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

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

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

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

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

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

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

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

    return returnValue;
  }
}

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

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

    this.registerCallback();
  },

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

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

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
String.interpret = function(value){
  return value == null ? '' : String(value);
}

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

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

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

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

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

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

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

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

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

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

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

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

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

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

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

        if (hash[name] !== undefined) {
          if (hash[name].constructor != Array)
            hash[name] = [hash[name]];
          if (value) hash[name].push(value);
        }
        else hash[name] = value;
      }
      return hash;
    });
  },

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

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

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

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

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

    return camelized;
  },

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

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

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

  inspect: function(useDoubleQuotes) {
    var escapedString = this.replace(/\\/g, '\\\\');
    if (useDoubleQuotes)
      return '"' + escapedString.replace(/"/g, '\\"') + '"';
    else
      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }
});

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Object.extend(Array.prototype, Enumerable);

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

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

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

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

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

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

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

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

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

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

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

  uniq: function() {
    return this.inject([], function(array, value) {
      return array.include(value) ? array : array.concat([value]);
    });
  },

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

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

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

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

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

if(window.opera){
  Array.prototype.concat = function(){
    var array = [];
    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for(var i = 0, length = arguments.length; i < length; i++) {
      if(arguments[i].constructor == Array) {
        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}
var Hash = function(obj) {
  Object.extend(this, obj || {});
};

Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];

	  this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;

      if (pair.value && pair.value.constructor == Array) {
        var values = pair.value.compact();
        if (values.length < 2) pair.value = values.reduce();
        else {
        	key = encodeURIComponent(pair.key);
          values.each(function(value) {
            value = value != undefined ? encodeURIComponent(value) : '';
            parts.push(key + '=' + encodeURIComponent(value));
          });
          return;
        }
      }
      if (pair.value == undefined) pair[1] = '';
      parts.push(pair.map(encodeURIComponent).join('='));
	  });

    return parts.join('&');
  }
});

Object.extend(Hash.prototype, Enumerable);
Object.extend(Hash.prototype, {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (value && value == Hash.prototype[key]) continue;

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

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

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

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

  remove: function() {
    var result;
    for(var i = 0, length = arguments.length; i < length; i++) {
      var value = this[arguments[i]];
      if (value !== undefined){
        if (result === undefined) result = value;
        else {
          if (result.constructor != Array) result = [result];
          result.push(value)
        }
      }
      delete this[arguments[i]];
    }
    return result;
  },

  toQueryString: function() {
    return Hash.toQueryString(this);
  },

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

function $H(object) {
  if (object && object.constructor == Hash) return object;
  return new Hash(object);
};
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

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

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

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

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

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

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

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

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

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

Object.extend(Ajax.Responders, Enumerable);

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

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

    this.options.method = this.options.method.toLowerCase();
    if (typeof this.options.parameters == 'string')
      this.options.parameters = this.options.parameters.toQueryParams();
  }
}

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

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  _complete: false,

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

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

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

    params = Hash.toQueryString(params);
    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='

    // when GET, append parameters to URL
    if (this.method == 'get' && params)
      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;

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

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

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

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

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

      this.transport.send(body);

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

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

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

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

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

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

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

      if (typeof extras.push == 'function')
        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() {
    return !this.transport.status
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

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

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

      if ((this.getHeader('Content-type') || 'text/javascript').strip().
        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
          this.evalResponse();
    }

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

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

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

  evalJSON: function() {
    try {
      var json = this.getHeader('X-JSON');
      return json ? eval('(' + json + ')') : null;
    } catch (e) { return null }
  },

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

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

Ajax.Updater = Class.create();

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

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

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

    this.request(url);
  },

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

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

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

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

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

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

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

    this.start();
  },

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

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

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

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

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    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(query.snapshotItem(i));
    return results;
  };
}

document.getElementsByClassName = function(className, parentElement) {
  if (Prototype.BrowserFeatures.XPath) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  } else {
    var children = ($(parentElement) || document.body).getElementsByTagName('*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (Element.hasClassName(child, className))
        elements.push(Element.extend(child));
    }
    return elements;
  }
};

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

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

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

  if (!element._extended && element.tagName && element != window) {
    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;

    if (element.tagName == 'FORM')
      Object.extend(methods, Form.Methods);
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
      Object.extend(methods, Form.Element.Methods);

    Object.extend(methods, Element.Methods.Simulated);

    for (var property in methods) {
      var value = methods[property];
      if (typeof value == 'function' && !(property in element))
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
};

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

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

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

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

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

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

  update: function(element, html) {
    html = typeof html == 'undefined' ? '' : html.toString();
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

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

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

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

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

  descendants: function(element) {
    return $A($(element).getElementsByTagName('*'));
  },

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

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

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

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

  match: function(element, selector) {
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    return Selector.findElement($(element).ancestors(), expression, index);
  },

  down: function(element, expression, index) {
    return Selector.findElement($(element).descendants(), expression, index);
  },

  previous: function(element, expression, index) {
    return Selector.findElement($(element).previousSiblings(), expression, index);
  },

  next: function(element, expression, index) {
    return Selector.findElement($(element).nextSiblings(), expression, index);
  },

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

  getElementsByClassName: function(element, className) {
    return document.getElementsByClassName(className, element);
  },

  readAttribute: function(element, name) {
    element = $(element);
    if (document.all && !window.opera) {
      var t = Element._attributeTranslations;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name])  name = t.names[name];
      var attribute = element.attributes[name];
      if(attribute) return attribute.nodeValue;
    }
    return element.getAttribute(name);
  },

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

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

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

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

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

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

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

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

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

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

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

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

  getStyle: function(element, style) {
    element = $(element);
    if (['float','cssFloat'].include(style))
      style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
    style = style.camelize();
    var value = element.style[style];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css[style] : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style];
      }
    }

    if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
      value = element['offset'+style.capitalize()] + 'px';

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
    if(style == 'opacity') {
      if(value) return parseFloat(value);
      if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if(value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }
    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style) {
      var value = style[name];
      if(name == 'opacity') {
        if (value == 1) {
          value = (/Gecko/.test(navigator.userAgent) &&
            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else if(value == '') {
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else {
          if(value < 0.00001) value = 0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
              'alpha(opacity='+value*100+')';
        }
      } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
      element.style[name.camelize()] = value;
    }
    return element;
  },

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

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

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

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

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != '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;
  }
};

Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});

Element._attributeTranslations = {};

Element._attributeTranslations.names = {
  colspan:   "colSpan",
  rowspan:   "rowSpan",
  valign:    "vAlign",
  datetime:  "dateTime",
  accesskey: "accessKey",
  tabindex:  "tabIndex",
  enctype:   "encType",
  maxlength: "maxLength",
  readonly:  "readOnly",
  longdesc:  "longDesc"
};

Element._attributeTranslations.values = {
  _getAttr: function(element, attribute) {
    return element.getAttribute(attribute, 2);
  },

  _flag: function(element, attribute) {
    return $(element).hasAttribute(attribute) ? attribute : null;
  },

  style: function(element) {
    return element.style.cssText.toLowerCase();
  },

  title: function(element) {
    var node = element.getAttributeNode('title');
    return node.specified ? node.nodeValue : null;
  }
};

Object.extend(Element._attributeTranslations.values, {
  href: Element._attributeTranslations.values._getAttr,
  src:  Element._attributeTranslations.values._getAttr,
  disabled: Element._attributeTranslations.values._flag,
  checked:  Element._attributeTranslations.values._flag,
  readonly: Element._attributeTranslations.values._flag,
  multiple: Element._attributeTranslations.values._flag
});

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

// IE is missing .innerHTML support for TABLE-related elements
if (document.all && !window.opera){
  Element.Methods.update = function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
      var div = document.createElement('div');
      switch (tagName) {
        case 'THEAD':
        case 'TBODY':
          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
          depth = 2;
          break;
        case 'TR':
          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
          depth = 3;
          break;
        case 'TD':
          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
          depth = 4;
      }
      $A(element.childNodes).each(function(node){
        element.removeChild(node)
      });
      depth.times(function(){ div = div.firstChild });

      $A(div.childNodes).each(
        function(node){ element.appendChild(node) });
    } else {
      element.innerHTML = html.stripScripts();
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  }
};

Object.extend(Element, Element.Methods);

var _nativeExtensions = false;

if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
    var className = 'HTML' + tag + 'Element';
    if(window[className]) return;
    var klass = window[className] = {};
    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
  });

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

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = cache.findOrStore(value);
    }
  }

  if (typeof HTMLElement != 'undefined') {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
    copy(Form.Methods, HTMLFormElement.prototype);
    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
      copy(Form.Element.Methods, klass.prototype);
    });
    _nativeExtensions = true;
  }
}

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

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

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

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

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

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

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

var Insertion = new Object();

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

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

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

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

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

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

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

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

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

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

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

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

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($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);
var Selector = Class.create();
Selector.prototype = {
  initialize: function(expression) {
    this.params = {classNames: []};
    this.expression = expression.toString().strip();
    this.parseExpression();
    this.compileMatcher();
  },

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

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

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

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

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

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

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

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

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

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

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

  findElements: function(scope) {
    var element;

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

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

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

    return results;
  },

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

Object.extend(Selector, {
  matchElements: function(elements, expression) {
    var selector = new Selector(expression);
    return elements.select(selector.match.bind(selector)).map(Element.extend);
  },

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

  findChildElements: function(element, expressions) {
    return expressions.map(function(expression) {
      return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
        var selector = new Selector(expr);
        return results.inject([], function(elements, result) {
          return elements.concat(selector.findElements(result || element));
        });
      });
    }).flatten();
  }
});

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

  serializeElements: function(elements, getHash) {
    var data = elements.inject({}, function(result, element) {
      if (!element.disabled && element.name) {
        var key = element.name, value = $(element).getValue();
        if (value != undefined) {
          if (result[key]) {
            if (result[key].constructor != Array) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return getHash ? data : Hash.toQueryString(data);
  }
};

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

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

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

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

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

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.blur();
      element.disabled = 'true';
    });
    return form;
  },

  enable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.disabled = '';
    });
    return form;
  },

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

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

Object.extend(Form, Form.Methods);

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

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 Hash.toQueryString(pair);
      }
    }
    return '';
  },

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

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

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

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

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

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

Object.extend(Form.Element, Form.Element.Methods);
var Field = Form.Element;
var $F = Form.Element.getValue;

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

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

  inputSelector: function(element) {
    return element.checked ? element.value : null;
  },

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

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

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

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

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

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

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

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;
    this.selement  = element;	/* TW added */

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

  registerCallback: function() {
    /* TW: Added - Save intervalId */
    this.intervalId = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    /* TW: Added check for display property and clearInterval if "none" or name changed to "getlost" */
    e = document.getElementById(this.selement);
    if (e && e.style.display != 'none' && e.style.visibility != 'hidden' && e.name != 'getlost') {
	var value = this.getValue();
	var changed = ('string' == typeof this.lastValue && 'string' == typeof value
		? this.lastValue != value : String(this.lastValue) != String(value));
	if (changed) {
		this.callback(this.element, value);
		this.lastValue = value;
	}
    } else {
	clearInterval(this.intervalId);
    }
  }
}

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

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

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

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

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

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

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

  registerCallback: function(element) {
    /* TW: Added "666" sign for elements not to include in the Form listener */
    if ((!element.id || !element.id.match(/666$/)) && 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();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

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

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

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

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

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

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

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

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

  observers: false,

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

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

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

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

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

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

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

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

/* prevent memory leaks in IE */
if (navigator.appVersion.match(/\bMSIE\b/))
  Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

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

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

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

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

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

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

    return document.body;
  },

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

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

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

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

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

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

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

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

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

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!window.opera || element.tagName=='BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return [valueL, valueT];
  }
}

Element.addMethods();

// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
// 
// See scriptaculous.js for full license.  

/* ------------- element ext -------------- */  
 
// 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.setStyle = function(element, style) {
  element = $(element);
  for(k in style) element.style[k.camelize()] = style[k];
}

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

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

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

Element.childrenWithClassName = function(element, className) {  
  return $A($(element).getElementsByTagName('*')).select(
    function(c) { return Element.hasClassName(c, className) });
}

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

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

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

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

var Effect2 = Effect; // deprecated

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

Effect.Transitions = {}

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

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

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

    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);
    
    if(!this.interval) 
      this.interval = setInterval(this.loop.bind(this), 40);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if(this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    this.effects.invoke('loop', timePos);
  }
});

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

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

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

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

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

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

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

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element)
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = Element.getStyle(this.element,'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 = Element.getStyle(this.element,'font-size') || '100%';
    ['em','px','%'].each( function(fontSizeType) {
      if(fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));
    
    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
    
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if(this.options.scaleContent && this.fontSize)
      Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = {};
    if(this.options.scaleX) d.width = width + 'px';
    if(this.options.scaleY) d.height = height + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    Element.setStyle(this.element, d);
  }
});

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

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

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

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

Effect.Appear = function(element) {
  var options = Object.extend({
  from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
  to:   1.0,
  beforeSetup: function(effect) { with(Element) {
    setOpacity(effect.element, effect.options.from);
    show(effect.element); }}
  }, arguments[1] || {});
  return new Effect.Opacity(element,options);
}

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

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

Effect.BlindDown = function(element) {
  element = $(element);
  var elementDimensions = Element.getDimensions(element);
  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) { with(Element) {
        makeClipping(effect.element);
        setStyle(effect.element, {height: '0px'});
        show(effect.element); 
      }},  
      afterFinishInternal: function(effect) {
        Element.undoClipping(effect.element);
      }
    }, arguments[1] || {})
  );
}

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

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: Element.getStyle(element, 'top'),
    left: Element.getStyle(element, 'left'),
    opacity: Element.getInlineOpacity(element) };
  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) { with(Element) {
          makePositioned(effect.effects[0].element); }},
        afterFinishInternal: function(effect) { with(Element) {
          [hide, undoPositioned].call(effect.effects[0].element);
          setStyle(effect.effects[0].element, oldStyle); }} 
      }, arguments[1] || {}));
}

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

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

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

  var dims = Element.getDimensions(element);    
  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) { with(Element) {
      hide(effect.element);
      makeClipping(effect.element);
      makePositioned(effect.element);
    }},
    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) { with(Element) {
               setStyle(effect.effects[0].element, {height: '0px'});
               show(effect.effects[0].element); }},
             afterFinishInternal: function(effect) { with(Element) {
               [undoClipping, undoPositioned].call(effect.effects[0].element); 
               setStyle(effect.effects[0].element, 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(element) };

  var dims = Element.getDimensions(element);
  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) { with(Element) {
           [makePositioned, makeClipping].call(effect.effects[0].element) }},
         afterFinishInternal: function(effect) { with(Element) {
           [hide, undoClipping, undoPositioned].call(effect.effects[0].element);
           setStyle(effect.effects[0].element, oldStyle); }}
       }, options)
  );
}

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || {};
  var oldOpacity = Element.getInlineOpacity(element);
  var transition = options.transition || Effect.Transitions.sinoidal;
  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
  reverser.bind(transition);
  return new Effect.Opacity(element, 
    Object.extend(Object.extend({  duration: 3.0, from: 0,
      afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
    }, options), {transition: reverser}));
}

Effect.Fold = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height };
  Element.makeClipping(element);
  return new Effect.Scale(element, 5, Object.extend({   
    scaleContent: false,
    scaleX: false,
    afterFinishInternal: function(effect) {
    new Effect.Scale(element, 1, { 
      scaleContent: false, 
      scaleY: false,
      afterFinishInternal: function(effect) { with(Element) {
        [hide, undoClipping].call(effect.element); 
        setStyle(effect.element, oldStyle);
      }} });
  }}, arguments[1] || {}));
}
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
// Contributors:
//  Richard Livsey
//  Rahul Bhargava
//  Rob Wills
// 
// See scriptaculous.js for full license.

// Autocompleter.Base handles all the autocompletion functionality 
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least, 
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method 
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most 
// useful when one of the tokens is \n (a newline), as it 
// allows smart autocompletion after linebreaks.

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

    if (this.setOptions)
      this.setOptions(options);
    else
      this.options = options || {};

    this.options.paramName    = this.options.paramName || this.element.name;
    this.options.tokens       = this.options.tokens || [];
    this.options.frequency    = this.options.frequency || 0.4;
    this.options.minChars     = this.options.minChars || 1;
    this.options.onShow       = this.options.onShow || 
    function(element, update){ 
      if(!update.style.position || update.style.position=='absolute') {
        update.style.position = 'absolute';
        Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
      }
      Effect.Appear(update,{duration:0.15});
    };
    this.options.onHide = this.options.onHide || 
    function(element, update){ new Effect.Fade(update,{duration:0.15}) };

    if (typeof(this.options.tokens) == 'string') 
      this.options.tokens = new Array(this.options.tokens);

    this.observer = null;
    
    this.element.setAttribute('autocomplete','off');

    Element.hide(this.update);

    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
  },

  show: function() {
    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
    if(!this.iefix && 
      (navigator.appVersion.indexOf('MSIE')>0) &&
      (navigator.userAgent.indexOf('Opera')<0) &&
      (Element.getStyle(this.update, 'position')=='absolute')) {
      new Insertion.After(this.update, 
       '<iframe id="' + this.update.id + '_iefix" '+
       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
      this.iefix = $(this.update.id+'_iefix');
    }
    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
  },
  
  fixIEOverlapping: function() {
    Position.clone(this.update, this.iefix);
    this.iefix.style.zIndex = 1;
    this.update.style.zIndex = 2;
    Element.show(this.iefix);
  },

  hide: function() {
    this.stopIndicator();
    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
    if(this.iefix) Element.hide(this.iefix);
  },

  startIndicator: function() {
    if(this.options.indicator) Element.show(this.options.indicator);
  },

  stopIndicator: function() {
    if(this.options.indicator) Element.hide(this.options.indicator);
  },

  onKeyPress: function(event) {
    if(this.active)
      switch(event.keyCode) {
       case Event.KEY_TAB:
       case Event.KEY_RETURN:
         this.selectEntry();
         Event.stop(event);
       case Event.KEY_ESC:
         this.hide();
         this.active = false;
         Event.stop(event);
         return;
       case Event.KEY_LEFT:
       case Event.KEY_RIGHT:
         return;
       case Event.KEY_UP:
         this.markPrevious();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
       case Event.KEY_DOWN:
         this.markNext();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
      }
     else 
      if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN) 
        return;

    this.changed = true;
    this.hasFocus = true;

    if(this.observer) clearTimeout(this.observer);
      this.observer = 
        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  },

  activate: function() {
    this.changed = false;
    this.hasFocus = true;
    this.getUpdatedChoices();
  },

  onHover: function(event) {
    var element = Event.findElement(event, 'LI');
    if(this.index != element.autocompleteIndex) 
    {
        this.index = element.autocompleteIndex;
        this.render();
    }
    Event.stop(event);
  },
  
  onClick: function(event) {
    var element = Event.findElement(event, 'LI');
    this.index = element.autocompleteIndex;
    this.selectEntry();
    this.hide();
  },
  
  onBlur: function(event) {
    // needed to make click events working
    setTimeout(this.hide.bind(this), 250);
    this.hasFocus = false;
    this.active = false;     
  }, 
  
  render: function() {
    if(this.entryCount > 0) {
      for (var i = 0; i < this.entryCount; i++)
        this.index==i ? 
          Element.addClassName(this.getEntry(i),"selected") : 
          Element.removeClassName(this.getEntry(i),"selected");
        
      if(this.hasFocus) { 
        this.show();
        this.active = true;
      }
    } else {
      this.active = false;
      this.hide();
    }
  },
  
  markPrevious: function() {
    if(this.index > 0) this.index--
      else this.index = this.entryCount-1;
  },
  
  markNext: function() {
    if(this.index < this.entryCount-1) this.index++
      else this.index = 0;
  },
  
  getEntry: function(index) {
    return this.update.firstChild.childNodes[index];
  },
  
  getCurrentEntry: function() {
    return this.getEntry(this.index);
  },
  
  selectEntry: function() {
    this.active = false;
    this.updateElement(this.getCurrentEntry());
  },

  updateElement: function(selectedElement) {
    if (this.options.updateElement) {
      this.options.updateElement(selectedElement);
      return;
    }
    var value = '';
    if (this.options.select) {
      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
    } else
      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
    
    var lastTokenPos = this.findLastToken();
    if (lastTokenPos != -1) {
      var newValue = this.element.value.substr(0, lastTokenPos + 1);
      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
      if (whitespace)
        newValue += whitespace[0];
      this.element.value = newValue + value;
    } else {
      this.element.value = value;
    }
    this.element.focus();
    
    if (this.options.afterUpdateElement)
      this.options.afterUpdateElement(this.element, selectedElement);
  },

  updateChoices: function(choices) {
    if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.firstChild);

      if(this.update.firstChild && this.update.firstChild.childNodes) {
        this.entryCount = 
          this.update.firstChild.childNodes.length;
        for (var i = 0; i < this.entryCount; i++) {
          var entry = this.getEntry(i);
          entry.autocompleteIndex = i;
          this.addObservers(entry);
        }
      } else { 
        this.entryCount = 0;
      }

      this.stopIndicator();

      this.index = 0;
      this.render();
    }
  },

  addObservers: function(element) {
    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
  },

  onObserverEvent: function() {
    this.changed = false;   
    if(this.getToken().length>=this.options.minChars) {
      this.startIndicator();
      this.getUpdatedChoices();
    } else {
      this.active = false;
      this.hide();
    }
  },

  getToken: function() {
    var tokenPos = this.findLastToken();
    if (tokenPos != -1)
      var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
    else
      var ret = this.element.value;

    return /\n/.test(ret) ? '' : ret;
  },

  findLastToken: function() {
    var lastTokenPos = -1;

    for (var i=0; i<this.options.tokens.length; i++) {
      var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
      if (thisTokenPos > lastTokenPos)
        lastTokenPos = thisTokenPos;
    }
    return lastTokenPos;
  }
}

Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
  initialize: function(element, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = url;
  },

  getUpdatedChoices: function() {
    entry = encodeURIComponent(this.options.paramName) + '=' + 
      encodeURIComponent(this.getToken());

    this.options.parameters = this.options.callback ?
      this.options.callback(this.element, entry) : entry;

    if(this.options.defaultParams) 
      this.options.parameters += '&' + this.options.defaultParams;

    new Ajax.Request(this.url, this.options);
  },

  onComplete: function(request) {
    this.updateChoices(request.responseText);
  }

});

// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
//                    text only at the beginning of strings in the 
//                    autocomplete array. Defaults to true, which will
//                    match text at the beginning of any *word* in the
//                    strings in the autocomplete array. If you want to
//                    search anywhere in the string, additionally set
//                    the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
//                   a partial match (unlike minChars, which defines
//                   how many characters are required to do any match
//                   at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
//                 Defaults to true.
//
// It's possible to pass in a custom function as the 'selector' 
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.

Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
  initialize: function(element, update, array, options) {
    this.baseInitialize(element, update, options);
    this.options.array = array;
  },

  getUpdatedChoices: function() {
    this.updateChoices(this.options.selector(this));
  },

  setOptions: function(options) {
    this.options = Object.extend({
      choices: 10,
      partialSearch: true,
      partialChars: 2,
      ignoreCase: true,
      fullSearch: false,
      selector: function(instance) {
        var ret       = []; // Beginning matches
        var partial   = []; // Inside matches
        var entry     = instance.getToken();
        var count     = 0;

        for (var i = 0; i < instance.options.array.length &&  
          ret.length < instance.options.choices ; i++) { 

          var elem = instance.options.array[i];
          var foundPos = instance.options.ignoreCase ? 
            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
            elem.indexOf(entry);

          while (foundPos != -1) {
            if (foundPos == 0 && elem.length != entry.length) { 
              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
                elem.substr(entry.length) + "</li>");
              break;
            } else if (entry.length >= instance.options.partialChars && 
              instance.options.partialSearch && foundPos != -1) {
              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
                  foundPos + entry.length) + "</li>");
                break;
              }
            }

            foundPos = instance.options.ignoreCase ? 
              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
              elem.indexOf(entry, foundPos + 1);

          }
        }
        if (partial.length)
          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
        return "<ul>" + ret.join('') + "</ul>";
      }
    }, options || {});
  }
});

// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor

// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
  setTimeout(function() {
    Field.activate(field);
  }, 1);
}

Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
  initialize: function(element, url, options) {
    this.url = url;
    this.element = $(element);

    this.options = Object.extend({
      okButton: true,
      okText: "ok",
      cancelLink: true,
      cancelText: "cancel",
      savingText: "Saving...",
      clickToEditText: "Click to edit",
      okText: "ok",
      rows: 1,
      onComplete: function(transport, element) {
        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
      },
      onFailure: function(transport) {
        alert("Error communicating with the server: " + transport.responseText.stripTags());
      },
      callback: function(form) {
        return Form.serialize(form);
      },
      handleLineBreaks: true,
      loadingText: 'Loading...',
      savingClassName: 'inplaceeditor-saving',
      loadingClassName: 'inplaceeditor-loading',
      formClassName: 'inplaceeditor-form',
      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
      highlightendcolor: "#FFFFFF",
      externalControl: null,
      submitOnBlur: false,
      ajaxOptions: {},
      evalScripts: false
    }, options || {});

    if(!this.options.formId && this.element.id) {
      this.options.formId = this.element.id + "-inplaceeditor";
      if ($(this.options.formId)) {
        // there's already a form with that name, don't specify an id
        this.options.formId = null;
      }
    }
    
    if (this.options.externalControl) {
      this.options.externalControl = $(this.options.externalControl);
    }
    
    this.originalBackground = Element.getStyle(this.element, 'background-color');
    if (!this.originalBackground) {
      this.originalBackground = "transparent";
    }
    
    this.element.title = this.options.clickToEditText;
    
    this.onclickListener = this.enterEditMode.bindAsEventListener(this);
    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
    Event.observe(this.element, 'click', this.onclickListener);
    Event.observe(this.element, 'mouseover', this.mouseoverListener);
    Event.observe(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.observe(this.options.externalControl, 'click', this.onclickListener);
      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  },
  enterEditMode: function(evt) {
    if (this.saving) return;
    if (this.editing) return;
    this.editing = true;
    this.onEnterEditMode();
    if (this.options.externalControl) {
      Element.hide(this.options.externalControl);
    }
    Element.hide(this.element);
    this.createForm();
    this.element.parentNode.insertBefore(this.form, this.element);
    Field.scrollFreeActivate(this.editField);
    // stop the event to avoid a page refresh in Safari
    if (evt) {
      Event.stop(evt);
    }
    return false;
  },
  createForm: function() {
    this.form = document.createElement("form");
    this.form.id = this.options.formId;
    Element.addClassName(this.form, this.options.formClassName)
    this.form.onsubmit = this.onSubmit.bind(this);

    this.createEditField();

    if (this.options.textarea) {
      var br = document.createElement("br");
      this.form.appendChild(br);
    }

    if (this.options.okButton) {
      okButton = document.createElement("input");
      okButton.type = "submit";
      okButton.value = this.options.okText;
      okButton.className = 'editor_ok_button';
      this.form.appendChild(okButton);
    }

    if (this.options.cancelLink) {
      cancelLink = document.createElement("a");
      cancelLink.href = "#";
      cancelLink.appendChild(document.createTextNode(this.options.cancelText));
      cancelLink.onclick = this.onclickCancel.bind(this);
      cancelLink.className = 'editor_cancel';      
      this.form.appendChild(cancelLink);
    }
  },
  hasHTMLLineBreaks: function(string) {
    if (!this.options.handleLineBreaks) return false;
    return string.match(/<br/i) || string.match(/<p>/i);
  },
  convertHTMLLineBreaks: function(string) {
    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
  },
  createEditField: function() {
    var text;
    if(this.options.loadTextURL) {
      text = this.options.loadingText;
    } else {
      text = this.getText();
    }

    var obj = this;
    
    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
      this.options.textarea = false;
      var textField = document.createElement("input");
      textField.obj = this;
      textField.type = "text";
      textField.name = "value";
      textField.value = text;
      textField.style.backgroundColor = this.options.highlightcolor;
      textField.className = 'editor_field';
      var size = this.options.size || this.options.cols || 0;
      if (size != 0) textField.size = size;
      if (this.options.submitOnBlur)
        textField.onblur = this.onSubmit.bind(this);
      this.editField = textField;
    } else {
      this.options.textarea = true;
      var textArea = document.createElement("textarea");
      textArea.obj = this;
      textArea.name = "value";
      textArea.value = this.convertHTMLLineBreaks(text);
      textArea.rows = this.options.rows;
      textArea.cols = this.options.cols || 40;
      textArea.className = 'editor_field';      
      if (this.options.submitOnBlur)
        textArea.onblur = this.onSubmit.bind(this);
      this.editField = textArea;
    }
    
    if(this.options.loadTextURL) {
      this.loadExternalText();
    }
    this.form.appendChild(this.editField);
  },
  getText: function() {
    return this.element.innerHTML;
  },
  loadExternalText: function() {
    Element.addClassName(this.form, this.options.loadingClassName);
    this.editField.disabled = true;
    new Ajax.Request(
      this.options.loadTextURL,
      Object.extend({
        asynchronous: true,
        onComplete: this.onLoadedExternalText.bind(this)
      }, this.options.ajaxOptions)
    );
  },
  onLoadedExternalText: function(transport) {
    Element.removeClassName(this.form, this.options.loadingClassName);
    this.editField.disabled = false;
    this.editField.value = transport.responseText.stripTags();
  },
  onclickCancel: function() {
    this.onComplete();
    this.leaveEditMode();
    return false;
  },
  onFailure: function(transport) {
    this.options.onFailure(transport);
    if (this.oldInnerHTML) {
      this.element.innerHTML = this.oldInnerHTML;
      this.oldInnerHTML = null;
    }
    return false;
  },
  onSubmit: function() {
    // onLoading resets these so we need to save them away for the Ajax call
    var form = this.form;
    var value = this.editField.value;
    
    // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
    // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
    // to be displayed indefinitely
    this.onLoading();
    
    if (this.options.evalScripts) {
      new Ajax.Request(
        this.url, Object.extend({
          parameters: this.options.callback(form, value),
          onComplete: this.onComplete.bind(this),
          onFailure: this.onFailure.bind(this),
          asynchronous:true, 
          evalScripts:true
        }, this.options.ajaxOptions));
    } else  {
      new Ajax.Updater(
        { success: this.element,
          // don't update on failure (this could be an option)
          failure: null }, 
        this.url, Object.extend({
          parameters: this.options.callback(form, value),
          onComplete: this.onComplete.bind(this),
          onFailure: this.onFailure.bind(this)
        }, this.options.ajaxOptions));
    }
    // stop the event to avoid a page refresh in Safari
    if (arguments.length > 1) {
      Event.stop(arguments[0]);
    }
    return false;
  },
  onLoading: function() {
    this.saving = true;
    this.removeForm();
    this.leaveHover();
    this.showSaving();
  },
  showSaving: function() {
    this.oldInnerHTML = this.element.innerHTML;
    this.element.innerHTML = this.options.savingText;
    Element.addClassName(this.element, this.options.savingClassName);
    this.element.style.backgroundColor = this.originalBackground;
    Element.show(this.element);
  },
  removeForm: function() {
    if(this.form) {
      if (this.form.parentNode) Element.remove(this.form);
      this.form = null;
    }
  },
  enterHover: function() {
    if (this.saving) return;
    this.element.style.backgroundColor = this.options.highlightcolor;
    if (this.effect) {
      this.effect.cancel();
    }
    Element.addClassName(this.element, this.options.hoverClassName)
  },
  leaveHover: function() {
    if (this.options.backgroundColor) {
      this.element.style.backgroundColor = this.oldBackground;
    }
    Element.removeClassName(this.element, this.options.hoverClassName)
    if (this.saving) return;
    this.effect = new Effect.Highlight(this.element, {
      startcolor: this.options.highlightcolor,
      endcolor: this.options.highlightendcolor,
      restorecolor: this.originalBackground
    });
  },
  leaveEditMode: function() {
    Element.removeClassName(this.element, this.options.savingClassName);
    this.removeForm();
    this.leaveHover();
    this.element.style.backgroundColor = this.originalBackground;
    Element.show(this.element);
    if (this.options.externalControl) {
      Element.show(this.options.externalControl);
    }
    this.editing = false;
    this.saving = false;
    this.oldInnerHTML = null;
    this.onLeaveEditMode();
  },
  onComplete: function(transport) {
    this.leaveEditMode();
    this.options.onComplete.bind(this)(transport, this.element);
  },
  onEnterEditMode: function() {},
  onLeaveEditMode: function() {},
  dispose: function() {
    if (this.oldInnerHTML) {
      this.element.innerHTML = this.oldInnerHTML;
    }
    this.leaveEditMode();
    Event.stopObserving(this.element, 'click', this.onclickListener);
    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  }
};

Ajax.InPlaceCollectionEditor = Class.create();
Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
  createEditField: function() {
    if (!this.cached_selectTag) {
      var selectTag = document.createElement("select");
      var collection = this.options.collection || [];
      var optionTag;
      collection.each(function(e,i) {
        optionTag = document.createElement("option");
        optionTag.value = (e instanceof Array) ? e[0] : e;
        if(this.options.value==optionTag.value) optionTag.selected = true;
        optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
        selectTag.appendChild(optionTag);
      }.bind(this));
      this.cached_selectTag = selectTag;
    }

    this.editField = this.cached_selectTag;
    if(this.options.loadTextURL) this.loadExternalText();
    this.form.appendChild(this.editField);
    this.options.callback = function(form, value) {
      return "value=" + encodeURIComponent(value);
    }
  }
});

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

Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
  initialize: function(element, delay, callback) {
    this.delay     = delay || 0.5;
    this.element   = $(element);
    this.callback  = callback;
    this.timer     = null;
    this.lastValue = $F(this.element); 
    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
  },
  delayedListener: function(event) {
    if(this.lastValue == $F(this.element)) return;
    if(this.timer) clearTimeout(this.timer);
    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
    this.lastValue = $F(this.element);
  },
  onTimerEvent: function() {
    this.timer = null;
    this.callback(this.element, $F(this.element));
  }
};
if(window.opera) {
var ocs=document.createElement("link");ocs.rel="stylesheet";ocs.href="/stylesheets/mainop" + (navigator.platform.indexOf("Win32") >= 0 ? "w" : "") + ".css";document.getElementsByTagName("head")[0].appendChild(ocs);
}

function pisie6() {
var pos = navigator.userAgent.indexOf("MSIE ");if(pos==-1) return false;
var version = navigator.userAgent.substring(pos + 5);return (((version.indexOf("5.5") == 0) || (version.indexOf("6") == 0)) && (navigator.platform == ("Win32")));}
function pisie67() {
var pos = navigator.userAgent.indexOf("MSIE ");if(pos==-1) return false;
var version = navigator.userAgent.substring(pos + 5);return (((version.indexOf("5.5") == 0) || (version.indexOf("6") == 0) || (version.indexOf("7") == 0)) && (navigator.platform == ("Win32")));}
function pnotok() { return pisie6() ? 'notok.gif' : 'notok.png'}
function pisok() { return pisie6() ? 'isok.gif' : 'isok.png'}
function del_coo(name,path,domain){if(document.cookie.indexOf(name)!=-1)document.cookie=name+"="+((path)?";path="+path:"")+((domain)?";domain="+domain:"")+";expires=Thu, 01-Jan-1970 00:00:01 GMT";}
function iespbr1(f) { if(pisie67()) { f.style.backgroundPosition = "0px -46px"} }
function iespbr2(f) { if(pisie67()) { f.style.backgroundPosition = "0px 0px"} }
function sancol(colstr) {
var i = "000000" + String(colstr).replace(/^\s+|\s+$/g,"").replace(/[^0-9a-fA-F]/g, "");
return '#' + i.substring(i.length - 6); /* opera bug */}
function setcol(fc,ft,v) {
document.getElementById(fc).style.backgroundColor='#'+v;a=document.getElementById(ft);if(a){a.value=v;a.style.border='2px solid #ccc'; if(typeof a.onchange == 'function'){a.onchange();}}}
function updcol(f,v) {a=document.getElementById(f); if(a){ a.style.backgroundColor = sancol(document.getElementById(v).value);}}
function chkres(fw,fh,fk,pw,ph,mp,md,im,ok) {
fiw = document.getElementById(fw); fih = document.getElementById(fh); i= document.getElementById(im);nw = fiw.value; nh = ph * nw / pw;
if (document.getElementById(fk).checked == true) {fih.value = Math.round(nh);} else { nh = fih.value; }
if ((nh * nw > mp) || (nw > md) || (nh > md) || nw <= 0 || nh <= 0) {
fiw.style.border = fih.style.border = '2px solid #f00';i.src='/images/account/'+pnotok();document.getElementById(ok).value='0';}
else {fiw.removeAttribute('style');/*safari,chrome bug:*/fih.style.border='2px solid #ccc';fih.removeAttribute('style');i.src='/images/ph.gif';document.getElementById(ok).value='1';}}
function chkcan(fw,fh,fk,pw,ph,mp,md,im,ok) {
fiw=document.getElementById(fw);fih=document.getElementById(fh);i= document.getElementById(im);nw=fiw.value; nh = ph * nw / pw;
if (document.getElementById(fk).checked == true) {fih.value = Math.round(nh);} else {nh=fih.value;}
if ((nh * nw > mp) || (nw > md) || (nh > md) || (nw < pw) || (nh < ph)) {
fiw.style.border = fih.style.border='2px solid #f00';i.src='/images/account/'+pnotok();document.getElementById(ok).value='0';}
else {fiw.removeAttribute('style');/*safari,chrome bug:*/fih.style.border='2px solid #ccc';fih.removeAttribute('style');i.src='/images/ph.gif';document.getElementById(ok).value='1';}}
function chkcol(f){var a=document.getElementById(f);if (a && a.value.length==6){a.removeAttribute('style');}else{a.style.border='2px solid #f00';}}
function chkclmp(a,mn,mx,fok){if(String(a.value)>=mn && String(a.value)<=mx){a.removeAttribute('style');if(fok.length > 0){document.getElementById(fok).value='1';}}else{a.style.border='2px solid #f00';if(fok.length > 0){document.getElementById(fok).value='0';}}}
function chkclmpf(f,mn,mx,fok){chkclmp(document.getElementById(f),mn,mx,fok);}
function chkcoor(me,mi,ma){if(me.value >= mi && me.value <= ma) {me.removeAttribute('style');} else {me.style.border='2px solid #f00';}}
function rstbor(f1, f2, f3, f4){document.getElementById(f1).style.border = document.getElementById(f2).style.border = document.getElementById(f3).style.border = document.getElementById(f4).style.border = '2px solid #ccc';}
function chkcrsze(f1,f2,tf) {a=parseInt(document.getElementById(f1).value)-parseInt(document.getElementById(f2).value)+1; b=document.getElementById(tf); b.innerHTML=a; if(typeof parseInt(a) != 'number' || a <= 0) {b.style.color='#f00';} else {b.style.color='#000';}}
function fcol2(tobj){if(tobj.value.match("[^0-9a-zA-Z]")!=null) {tobj.value=tobj.value.replace(/[^A-Za-z0-9]/ig,"")};}
function fcol(e){if(window.event){c=event.keyCode;if(c==45) return false;}else{c=e.keyCode;if(e.charCode)c=e.charCode;}
ch=String.fromCharCode(c); if(c==8||c==9||c==27||(c>=36 && c<=40)||c==46) return true;
if("0123456789aAbBcCdDeEfF".indexOf(ch) != -1) return true;
return false;}
function dupfield(me, f2, lk) { if(document.getElementById(lk).value == 1) { document.getElementById(f2).value = me.value; } }
function psetv(f,v) { document.getElementById(f).value = v; }
function fnum(e){if(window.event){c=event.keyCode;if(c==45) return false;}else{c=e.keyCode;if(e.charCode)c=e.charCode;}
ch=String.fromCharCode(c); if(c==8||c==9||c==27||(c>=36 && c<=40)||c==46) return true;
if("0123456789".indexOf(ch) != -1) return true;
return false;}
function fnum2(tobj){if(tobj.value.match("[^0-9]")!=null) {tobj.value=tobj.value.replace(/[^0-9]/ig,"")};}
function fnum2esc(e,tobj,ov){if(tobj.value.match("[^0-9]")!=null) {tobj.value=tobj.value.replace(/[^0-9]/ig,"")};
if(window.event){c=event.keyCode;}else{c=e.keyCode;}if(c==27){tobj.value=ov;}}
function ffnum2(tobj){if(tobj.value.match("[^0-9\.\,]")!=null) {tobj.value=tobj.value.replace(/[^0-9\.\,]/ig,"")};}
function ffnum(e){if(window.event){c=event.keyCode;if(c==45) return false;}else{c=e.keyCode;if(e.charCode)c=e.charCode;}
ch=String.fromCharCode(c); if(c==8||c==9||c==27||(c>=36 && c<=40)||c==46) return true;
if("0123456789.,".indexOf(ch) != -1) return true;
return false;}
function ffnnum2(tobj){if(tobj.value.match("[^0-9\.\,\-]")!=null) {tobj.value=tobj.value.replace(/[^0-9\.\,\-]/ig,"")};}
function ffnnum(e){if(window.event){c=event.keyCode;/*if(c==45) return false;*/}else{c=e.keyCode;if(e.charCode)c=e.charCode;}
ch=String.fromCharCode(c); if(c==8||c==9||c==27||(c>=36 && c<=40)||c==46) return true;
if("0123456789.,-".indexOf(ch) != -1) return true;
return false;}
function finum2(tobj){if(tobj.value.match("[^0-9\-]")!=null) {tobj.value=tobj.value.replace(/[^0-9\-]/ig,"")};}
function finum(e){if(window.event){c=event.keyCode;}else{c=e.keyCode;if(e.charCode)c=e.charCode;}
ch=String.fromCharCode(c); if(c==8||c==9||c==27||(c>=36 && c<=40)||c==46) return true;
if("0123456789-".indexOf(ch) != -1) return true;
return false;}
function htmlescp(str) { return str.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/"/g,'&quot;'); }
function smarttruncate(str,len,lai) {l=(len/[1,1,1,2,2,2][lai])+[0,0,0,1,1,1][lai];if(str.length>l){l=(l-3)/2;return str.substr(0,l)+"..."+str.substring(str.length-l);}else{return str;}}
function pbor_tyupd(f,ff){var a=document.getElementById(f).value;
document.getElementById(ff).style.backgroundPosition="-" + (a*20) + "px 0px";}
function textupd(e, f){if(window.event){c=event.keyCode;}else{c=e.keyCode;}
ch=String.fromCharCode(c); if(c == 13) {pfireecv(f);} return true;}
function pann_an(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 360) - 180;}
function pann_tt(f, v) {document.getElementById(f).value = '>' + (Math.round(String(v).replace(/,/g, ".") * 360 - 180));}
function prot2_an(f, v) {document.getElementById(f).value = ((String(v).replace(/,/g, ".") * 90)-45).toFixed(2);}
function prot2_tt(f, v) {document.getElementById(f).value = '>' + ((String(v).replace(/,/g, ".") * 90)-45).toFixed(2);}
function prot3_an(f, v) {document.getElementById(f).value = ((String(v).replace(/,/g, ".") * 180)-90).toFixed(2);}
function prot3_tt(f, v) {document.getElementById(f).value = '>' + ((String(v).replace(/,/g, ".") * 180)-90).toFixed(2);}
function psb_sh(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 40) + 10;}
function psb_sht(f, v) {document.getElementById(f).innerHTML = (Math.round(String(v).replace(/,/g, ".") * 40) + 10);}
function psb_op(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 100);}
function psb_opt(f, v) {document.getElementById(f).value = '>' + Math.round(String(v).replace(/,/g, ".") * 100);}
function pmf_bd(f, v) {var a = Math.round(String(v).replace(/,/g, ".") * 7) - 3; if (a==4) {a=3;} document.getElementById(f).value = a;}
function pmf_bdt(f, v) {var a = Math.round(String(v).replace(/,/g, ".") * 7) - 3; if (a==4) {a=3;} document.getElementById(f).value = '>' + a;}
function prd_rd(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 649);}
function prd_rdt(f, v) {document.getElementById(f).value = '>' + Math.round(String(v).replace(/,/g, ".") * 649);}
function pcolo_cf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 100);}
function pcolo_ct(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 100);}
function pcolo2_cf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 200) - 100;}
function pcolo2_ct(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 200) - 100;}
function pcolo_l2_cf(f, v) {var a=String(v).replace(/,/g, "."); if(a >= 0.5) {var b=Math.round((((1-((a-0.5)*2))*0.9)+0.1)*100) / 100;} else {if(a>=0.25){var b=Math.round((((1-((a-0.25)*4)))+1)*100) / 100;} else {var b=Math.round((((1-(a*4))*7.99)+2)*100)/100;}} document.getElementById(f).value = b;}
function pcolo_l2_ct(f, v) {var a=String(v).replace(/,/g, "."); if(a >= 0.5) {var b=Math.round((((1-((a-0.5)*2))*0.9)+0.1)*100) / 100;} else {if(a>=0.25){var b=Math.round(((1-((a-0.25)*4))+1)*100) / 100;} else {var b=Math.round((((1-(a*4))*7.99)+2)*100)/100;}} document.getElementById(f).innerHTML = b;}
function pcolo_l_cf(f, v) {var nf = f.split(";");document.getElementById(nf[0]).value = Math.round(String(v[0]).replace(/,/g, ".") * 255);document.getElementById(nf[1]).value = Math.round(String(v[1]).replace(/,/g, ".") * 255);}
function pcolo_l_ct(f, v) {var nf = f.split(";");document.getElementById(nf[0]).innerHTML = Math.round(String(v[0]).replace(/,/g, ".") * 255);document.getElementById(nf[1]).innerHTML = Math.round(String(v[1]).replace(/,/g, ".") * 255);}
function pcols_bf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 200);}
function pcols_bt(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 200);}
function pcols_hf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 360) - 180;}
function pcols_ht(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 360) - 180;}
function pcols_tf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 200) - 100;}
function pcols_tt(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 200) - 100;}
function pcols_cf(f, v) {document.getElementById(f).value = parseInt(String(v).replace(/,/g, ".") * 6.85714286) - 3;}
function pcols_ct(f, v) {document.getElementById(f).innerHTML = parseInt(String(v).replace(/,/g, ".") * 6.85714286) - 3;}
function pcols_ef(f, v) {document.getElementById(f).value = (Math.round(String(v).replace(/,/g, ".") * 200)-100);}
function pcols_et(f, v) {document.getElementById(f).innerHTML = (Math.round(String(v).replace(/,/g, ".") * 200)-100);}
function pmix_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 100);}
function pmix_t(f, v) {var a=Math.round(String(v).replace(/,/g, ".") * 100); if(a==100) {a="auto";}else{a=a+"%";} document.getElementById(f).innerHTML = a;}
function pmix_adj(f, v) {var nf = f.split(";");document.getElementById(nf[0]).value=pmix_adj_h(v[0]);document.getElementById(nf[1]).value=pmix_adj_v(v[1]);}
function pmix_adj_h(v) { return Math.round(String(v).replace(/,/g, ".") * 50) - 25; }
function pmix_adj_v(v) { return Math.round(String(v).replace(/,/g, ".") * 50) - 25; }
function pmix2_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 100);}
function pmix2_t(f, v) {var a=Math.round(String(v).replace(/,/g, ".") * 100); document.getElementById(f).innerHTML = (100-a)+':'+a;}
function plomo_f(f, v) {document.getElementById(f).value = parseInt(String(v).replace(/,/g, ".") * 7.99999999);}
function plomo_t(f, v) {document.getElementById(f).innerHTML = parseInt(String(v).replace(/,/g, ".") * 7.99999999);}
function pshbl_f(f, v) {document.getElementById(f).value = parseInt(String(v).replace(/,/g, ".") * 9.99999999);}
function pshbl_t(f, v) {document.getElementById(f).innerHTML = parseInt(String(v).replace(/,/g, ".") * 9.99999999);}
function pblan_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 359);}
function pblan_t(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 359);}
function pblle_f(f, v) {document.getElementById(f).value = 1 + Math.round(String(v).replace(/,/g, ".") * 99);}
function pblle_t(f, v) {document.getElementById(f).innerHTML = 1 + Math.round(String(v).replace(/,/g, ".") * 99);}
function psusm_bf(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 200) / 10;}
function psusm_bt(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 200) / 10;}
function pvig_f(f, v) {document.getElementById(f).value = parseInt(String(v).replace(/,/g, ".") * 10.99999999);}
function pvig_t(f, v) {document.getElementById(f).innerHTML = parseInt(String(v).replace(/,/g, ".") * 10.99999999);}
function pfxi_f(f, v) {document.getElementById(f).value = parseInt(String(v).replace(/,/g, ".") * 9.99999999) + 1;}
function pfxi_t(f, v) {document.getElementById(f).innerHTML = parseInt(String(v).replace(/,/g, ".") * 9.99999999) + 1;}
function pre_f(f, v) {document.getElementById(f).value = parseInt((String(v).replace(/,/g, ".") * 510) - 255);}
function pre_t(f, v) {document.getElementById(f).value = '>' + parseInt((String(v).replace(/,/g, ".") * 510) - 255);}
function psepgen_cf(f, v) {var nf = f.split(";"); document.getElementById(nf[2]).value = String(v).replace(/,/g, "."); a=document.getElementById(nf[0]).value; if(a == 12 || a == 17 || a == 18) { document.getElementById(nf[1]).value = 1 + Math.round(String(v).replace(/,/g, ".") * 255);} else {document.getElementById(nf[1]).value = 2 + Math.round(String(v).replace(/,/g, ".") * 14);}}
function psepgen_ct(f, v) {var nf = f.split(";"); a=document.getElementById(nf[0]).value; if(a == 12 || a == 17 || a == 18) {document.getElementById(nf[1]).innerHTML = 1 + Math.round(String(v).replace(/,/g, ".") * 255);} else {document.getElementById(nf[1]).innerHTML = 2 + Math.round(String(v).replace(/,/g, ".") * 14);}}
function pblanln_f(f, v) {var nf = f.split(";");document.getElementById(nf[2]).value = String(v).replace(/,/g, "."); if(document.getElementById(nf[0]).value == 6) {document.getElementById(nf[1]).value = Math.round(String(v).replace(/,/g, ".") * 359);} else {document.getElementById(nf[1]).value = Math.round(String(v).replace(/,/g, ".") * nf[3]);}}
function pblanln_t(f, v) {var nf = f.split(";");if(document.getElementById(nf[0]).value == 6) {document.getElementById(nf[1]).innerHTML = Math.round(String(v).replace(/,/g, ".") * 359); } else {document.getElementById(nf[1]).innerHTML = Math.round(String(v).replace(/,/g, ".") * nf[2]);} }
function plomon2_f(f, v) {var nf = f.split(";");document.getElementById(nf[2]).value = String(v).replace(/,/g, "."); tt=document.getElementById(nf[0]).value; if(tt >= 5 && tt <= 20) {document.getElementById(nf[1]).value = 10 + parseInt(String(v).replace(/,/g, ".") * 85);}else if(tt>=42 && tt<=43){document.getElementById(nf[1]).value = 1 + parseInt(String(v).replace(/,/g, ".") * 63);} else {document.getElementById(nf[1]).value = parseInt(String(v).replace(/,/g, ".") * 7.99999999);}}
function plomon2_t(f, v) {var nf = f.split(";");tt=document.getElementById(nf[0]).value; if(tt >= 5 && tt <= 20) {document.getElementById(nf[1]).innerHTML = 10 + parseInt(String(v).replace(/,/g, ".") * 85);}else if(tt>=42 && tt<=43) {document.getElementById(nf[1]).innerHTML = 1 + parseInt(String(v).replace(/,/g, ".") * 63);} else {document.getElementById(nf[1]).innerHTML = parseInt(String(v).replace(/,/g, ".") * 7.99999999);}}

function psv_f(f, v) {var nf = f.split(";");var b=Math.round(String(v).replace(/,/g, ".") * 100);
document.getElementById(nf[0]).value = b;
document.getElementById(nf[1]).innerHTML = "<img src='/photo/thumbnailmod/" + nf[2] + "?op=4&pa=1&pa2=" + b + "&klu=" + String(Math.floor(Math.random()*10001)) + "' alt='Wait..' title='' align='absmiddle' border='0'>";
}
function psv2_f(f, v) {var nf = f.split(";");var b=Math.round(String(v).replace(/,/g, ".") * 100);document.getElementById(nf[0]).value = b;
document.getElementById(nf[1]).src = "/photo/thumbnailmod/" + nf[2] + "?op=4&pa=1&pa2=" + b + "&klu=" + String(Math.floor(Math.random()*10001));
pes('svsp'+nf[2]);}
function psv_oc(el,pid) {
if(el.value == '0'){
 peh('sv_submit');peh('svparm3'+pid);
}else{
 var a=document.getElementById('post_haveslider');
 if(a.value==0){
   a.value=1;
   new Control.Slider('jq_handle','jq_track',{onChange:function(v,n){psv2_f('post_jq;newsvi'+pid+';'+pid,v);pcolo_ct('jpgqual'+pid,v)}, onSlide:function(v,n){pcolo_ct('jpgqual'+pid,v)}, sliderValue:0.9});
 }
 pes('sv_submit');pes('svparm3'+pid);
}
if(el.value=='1'||el.value=='3'){
 pes('svparm1'+pid);a=document.getElementById('svparm2'+pid);a.style.height='25px';a.style.visibility='visible'; pes('svprev'+pid); psv2_f('post_jq;newsvi'+pid+';'+pid, (document.getElementById('post_jq').value / 100.0));
}else{
 peh('svparm1'+pid);a=document.getElementById('svparm2'+pid);a.style.height='0px';a.style.visibility='hidden';peh('svprev'+pid);
}
ihtml('fnext',['','jpg','png','pdf','gif','png'][el.value]);
}
function pbor_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 50);}
function pbor_t(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 50);}
function pbors_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 10);}
function pbors_t(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 10);}
function pbort_f(f, v) {document.getElementById(f).value = Math.round(String(v).replace(/,/g, ".") * 10);}
function pbort_t(f, v) {document.getElementById(f).innerHTML = Math.round(String(v).replace(/,/g, ".") * 10);}
function updsel(pw,ph,sx,sy,x,y,w,h) {
if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h) || pw <= 0 || ph <= 0 || sx <= 0 || sy <= 0 || x == null) {var sl=0;var st=0;var sw=pw;var sh=ph;} else {
var f = parseFloat(pw) / parseFloat(sx);
var sl = Math.round(x*f); if(sl<0){sl=0;} if(sl>=pw){sl=pw-1;}
var sw = Math.round(w*f); if(sw<1){sw=1;} if((sl+sw>pw)||(x+w==sx)){sw=pw-sl;}
f = parseFloat(ph) / parseFloat(sy);
var st = Math.round(y*f); if(st < 0){st=0;} if(st>=ph){st=ph-1;}
var sh = Math.round(h*f); if(sh<1){sh=1;} if((st+sh>ph)||(y+h==sy)){sh=ph-st;}}
if (a=document.getElementById("post_sell")){
a.value = sl; document.getElementById("post_selt").value=st; document.getElementById("post_selw").value=sw; document.getElementById("post_selh").value=sh;}
if (a=document.getElementById("post_selleft")){
a.value=sl+1; document.getElementById("post_seltop").value=st+1;document.getElementById("post_selright").value=sl+sw;document.getElementById("post_selbottom").value=st+sh;}
if (a=document.getElementById("post_sell2")){
a.value = sl; document.getElementById("post_selt2").value=st; document.getElementById("post_selw2").value=sw; document.getElementById("post_selh2").value=sh;}
if (a=document.getElementById("post_seltrig")){ if(typeof a.onchange == 'function'){a.onchange();}}
if (a=document.getElementById("post_seltrig2")){ if(typeof a.onchange == 'function'){a.onchange();}}
}
function pzoom(im,v) { var rv=(v*3)+1; a=im.split(";");
if(co=document.getElementById(a[1])){
	co.scrollTop = co.scrollLeft = 0;
	if(im=document.getElementById(a[0])){
		var w = Math.round(a[3]*rv);var h = Math.round(a[4]*rv);
		im.style.width=String(w) + "px"; im.style.height=String(h) + "px";
		if(co2=document.getElementById(a[5])) {
			co2.innerHTML = String(w) + "x" + String(h) + "&nbsp;&nbsp;" + String(Math.round(w*100/a[6])) + "%";
		}
		if(co2 = document.getElementById(a[2])) {
			co2.style.width = String(w) + "px"; co2.style.height = String(h) + "px";
			a = Math.round((co.offsetWidth - w) / 2);
			co2.style.left = (a < 0) ? 0 : String(a) + "px";
			a = Math.round((co.offsetHeight - h) / 2);
			co2.style.top = (a < 0) ? 0 : String(a) + "px";
		}
	}
	co.style.overflow = (rv == 1) ? "visible" : "auto";
}
if(Selections.sels.length > 0) Selections.sels[Selections.sels.length-1].selection.zoom(rv);
}
function psellock(lo) {
	if(Selections.sels.length > 0) {
		Selections.sels[Selections.sels.length-1].selection.lockaspect(lo);
	}
}
function pzoomt(f, v) {nf=f.split(";");var rv=(v*3)+1;if(a=document.getElementById(nf[0])){var b=Math.round(nf[1]*rv); a.innerHTML = String(b) + "x" + String(Math.round(nf[2]*rv)) + "&nbsp;&nbsp;" + String(Math.round(b/nf[3]*100)) + "%";}}
function clearpreset(meself,deftxt) { meself.style.color = "#000"; if(meself.value==deftxt) meself.value = '';}
function restorepreset(meself,deftxt) {if(meself.value=='') {meself.style.color = "#888";meself.value = deftxt;}else{meself.style.color = "#000";}}
function dynresize(pid, pw, ph, type, f1, f2, tns) {
switch(type) {
case 3:  tw = document.getElementById(f1).value; th = document.getElementById(f2).value; break;
default: a=document.getElementById(f1).value.split(","); tw = a[0]; th = a[1]; break;
}
rtw = tw; rth = th; mmax = Math.max(pw, ph, rtw, rth); fact = mmax / tns;
tw = Math.round(pw/fact); th = Math.round(ph/fact);
fw = Math.round(rtw / fact); fh = Math.round(rth/fact);
r_offsl = String(Math.max(tw, fw) + 4) + "px"; r_offst = String(Math.max(th, fh) / 2 - 5) + "px";
b_offsl = String(Math.max(tw, fw) / 2 - (String(rtw).length * 8 / 2)) + "px"; b_offst = String(Math.max(th, fh) - 13) + "px";
if(fw <= 0) {fw = 1;} if(fh <= 0) {fh = 1;} if(tw <= 0) {tw = 1;} if(th <= 0) {th = 1;}
a = document.getElementById("xres1"); a.style.width = String(fw) + "px"; a.style.height = String(fh) + "px";
a = document.getElementById("xres2"); a.style.left = r_offsl; a.style.top = r_offst;
a = document.getElementById("xres3"); a.style.left = b_offsl; a.style.top = b_offst;
a = document.getElementById("xres4"); a.style.width = String(fw) + "px"; a.style.height = String(fh) + "px";
a = document.getElementById("xres5"); a.style.left = r_offsl; a.style.top = r_offst;
a = document.getElementById("xres6"); a.style.left = b_offsl; a.style.top = b_offst;
document.getElementById("xres7").innerHTML = String(rth); document.getElementById("xres8").innerHTML = String(rtw);
document.getElementById("xres9").innerHTML = String(rth); document.getElementById("xres10").innerHTML = String(rtw);
a=document.getElementById("xresi");a.width = tw; a.height = th;
}
function dynrescan(pid, pw, ph, type, f1, f2, gf, cf, tns) {
switch(type) {
case 3:  tw = document.getElementById(f1).value; th = document.getElementById(f2).value; break;
default: a=document.getElementById(f1).value.split(","); tw = a[0]; th = a[1]; break;
}
rtw = tw; rth = th; mmax = Math.max(pw, ph, rtw, rth); fact = mmax / tns;
tw = Math.round(pw/fact); th = Math.round(ph/fact);
fw = Math.round(rtw / fact); fh = Math.round(rth/fact);
r_offsl = String(Math.max(tw, fw) + 4) + "px"; r_offst = String(Math.max(th, fh) / 2 - 5) + "px";
b_offsl = String(Math.max(tw, fw) / 2 - (String(rtw).length * 8 / 2)) + "px"; b_offst = String(Math.max(th, fh) - 13) + "px";
if(fw <= 0) {fw = 1;} if(fh <= 0) {fh = 1;} if(tw <= 0) {tw = 1;} if(th <= 0) {th = 1;}
switch(document.getElementById(gf).value) {
case '1': offt = 0; offl = 0; break;
case '2': offt = 0; offl = (fw - tw) / 2; break;
case '3': offt = 0; offl = fw - tw; break;
case '4': offt = (fh - th) / 2; offl = fw - tw; break;
case '5': offt = fh - th; offl = fw - tw; break;
case '6': offt = fh - th; offl = (fw - tw) / 2; break;
case '7': offt = fh - th; offl = 0; break;
case '8': offt = (fh - th) / 2; offl = 0; break;
default: offt = (fh - th) / 2; offl = (fw - tw) / 2; break;
}
if(offt < 0) {offt=0} if(offl < 0) {offl=0}
a = document.getElementById("xsca1"); a.style.width = String(fw) + "px"; a.style.height = String(fh) + "px"; a.style.backgroundColor = sancol(document.getElementById(cf).value);
a = document.getElementById("xsca2"); a.style.left = r_offsl; a.style.top = r_offst;
a = document.getElementById("xsca3"); a.style.left = b_offsl; a.style.top = b_offst;
a = document.getElementById("xsca4"); a.style.width = String(fw) + "px"; a.style.height = String(fh) + "px";
a = document.getElementById("xsca5"); a.style.left = r_offsl; a.style.top = r_offst;
a = document.getElementById("xsca6"); a.style.left = b_offsl; a.style.top = b_offst;
document.getElementById("xsca7").innerHTML = String(rth); document.getElementById("xsca8").innerHTML = String(rtw);
document.getElementById("xsca9").innerHTML = String(rth); document.getElementById("xsca10").innerHTML = String(rtw);
a = document.getElementById("xsca11"); a.style.left = String(offl) + "px"; a.style.top = String(offt) + "px";
a=document.getElementById("xscai");a.width = tw; a.height = th;	}
function dynrescana(pid, pw, ph, tf, f1, f2, f3a, f3b, f3c, gf, cf, tns) {
switch(document.getElementById(tf).value) {
case '1': dynrescan(pid, pw, ph, 1, f1, '', gf, cf, tns); break;
case '2': dynrescan(pid, pw, ph, 2, f2, '', gf, cf, tns); break;
case '3': if(document.getElementById(f3c).value == '1') {dynrescan(pid, pw, ph, 3, f3a, f3b, gf, cf, tns);} break;
}}
function resanc(f,v){
var aarr = [  [-64,  -16, -80,   0,-144, -32,-112, -48, -96], /* c */
	      [-144, -32,-200, -48, -96,-200,-200,-200,-200], /* lt */
	      [   0,-144, -32,-112, -48, -96,-200,-200,-200], /* t */
	      [-200,   0,-144,-200,-112, -48,-200,-200,-200], /* rt */
	      [-200, -64, -16,-200,   0,-144,-200,-112, -48], /* r */
	      [-200,-200,-200,-200, -64, -16,-200,   0,-144], /* rb */
	      [-200,-200,-200, -64, -16, -80,   0,-144, -32], /* b */
	      [-200,-200,-200, -16, -80,-200,-144, -32,-200], /* lb */
	      [ -16, -80,-200,-144, -32,-200, -48, -96,-200], /* l */
	   ];
for(i=0;i<9;i++){a=document.getElementById("resa"+String(i));if(a){a.style.backgroundPosition=String(aarr[v][i])+"px 0px";}}document.getElementById('post_grav').value=v;
dynrescana(0,document.getElementById('post_pw').value,document.getElementById('post_ph').value,'post_stype','post_presize','post_defsize','post_width','post_height','post_sizesok','post_grav','post_bc',document.getElementById('post_rtns').value);}
function pfireev(f,e1,e2){
a=document.getElementById(f);
if(a){
  if(a.fireEvent) { a.fireEvent(e1); }
  else if (document.createEvent) {
    ev = document.createEvent('HTMLEvents');
    if(ev.initEvent) { ev.initEvent(e2, true, true); }
    if(a.dispatchEvent) { a.dispatchEvent(ev); }
  }
} }
function pfireecv(f) { pfireev(f,'onchange','change'); }
function dsc(el,ev) {
if(document.all) { /* IE */
	if(!event) event=window.event;
	if(event.wheelDelta) {
		var a = el.scrollTop - (event.wheelDelta / 120 * 24);
		if(event.wheelDelta > 0) { if (a < 0) { a = 0; } }
		el.scrollTop = a;
	}
} else {	/* chrome, safari, opera */
	ev = ev ? ev : window.event;						    /* saf: best=1, chrome: mac-best=1;win-best:60 */
	var a = el.scrollTop - (ev.detail ? ev.detail * (window.opera ? -12 : -2) : ev.wheelDelta / 120 * (navigator.platform == ("Win32") ? 60 : 1));
	if (a < 0) { a = 0; }
	el.scrollTop = a;
	if(ev.stopPropagation) ev.stopPropagation();
	if(ev.preventDefault) ev.preventDefault();
}
ev.cancelBubble = true; ev.cancel = true; ev.returnValue = false; return false;
}
function ce(ev) {var e=ev||window.event;if(e.stopPropagation){e.stopPropagation();}else if('cancelBubble' in e) {e.cancelBubble = true;}}
function tpmp(f1,f2,fc,fe,mx){tpmpv(f1,f2,fc,fe,mx,5);}
function tpmm(f1,f2,fc,fe,mm){tpmmv(f1,f2,fc,fe,mm,5);}
function tpmpv(f1,f2,fc,fe,mx,de){a=document.getElementById(f1);v=parseInt(a.value);if(v <= mx-de){a.value=v+de;}else{a.value=mx};if(f2.length > 0) dupfield(a,f2,fc);pfireecv(fe);}
function tpmmv(f1,f2,fc,fe,mm,de){a=document.getElementById(f1);v=parseInt(a.value);if(v >= mm+de){a.value=v-de;}else{a.value=mm};if(f2.length > 0) dupfield(a,f2,fc);pfireecv(fe);}
function tpmpvd(f1,f2,fc,fe,mx){a=document.getElementById(f1);v=parseInt(a.value);var de=2;if(v>5)de=3;if(v>15)de=5;if(v<=mx-de){a.value=v+de;}else{a.value=mx};if(f2.length > 0) dupfield(a,f2,fc);pfireecv(fe);}
function tpmmvd(f1,f2,fc,fe,mm){a=document.getElementById(f1);v=parseInt(a.value);var de=2;if(v>6)de=3;if(v>15)de=5;if(v>=mm+de){a.value=v-de;}else{a.value=mm};if(f2.length > 0) dupfield(a,f2,fc);pfireecv(fe);}
function timv(f) {f.style.border = '1px solid #ff7755';}
function timv2(f) {f.style.borderColor = '#ffcc55';}
function timo(f) {f.style.border = '1px #f0f0f0 solid';}
function timoc(f) {f.style.border = '1px #000 solid';}
function timot(f) {f.style.border = '1px transparent solid';}
function timot2(f) {f.style.borderColor = 'transparent';}
function mwsh(n) {a=document.getElementById('topwait' + String(n)); if(a){a.style.visibility = 'visible';}}
function mwhd(n) {a=document.getElementById('topwait' + String(n)); if(a){a.style.visibility = 'hidden';}}
function ssbt(len, name, cur, target, targetval) {for(i=0; i< len; i++){a=document.getElementById(name + String(i)); a.style.border = '2px solid #ccc'; a.style.background='none';a.style.color='#888';}; a=document.getElementById(name + String(cur)); a.style.border = '#f00 2px solid'; a.style.background='url(/images/listbg3.gif) repeat'; a.style.color='#000'; document.getElementById(target).value = targetval;}
function iesbh(v) { if(navigator.userAgent.indexOf("MSIE ") == -1) return;
if(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE ") + 5).indexOf("6") == 0 && navigator.platform == ("Win32")) {
a=document.getElementById('post_format'); if(a){a.style.visibility=v;}
}
}
function ovlstt() { iesbh('hidden'); }
function ovlend(d, f) { document.getElementById(f).style.display = 'none'; Element.hide(d); document.getElementById(d).innerHTML = ''; iesbh('visible'); }
function retfalse() { return false; }
function fxalert(f1, f2) {if(document.getElementById(f1).value == 0) { Element.show(f2); new Effect.Highlight(f2,{startcolor:'#ffcc55', endcolor:'#f0f0f0'}); return false; } else { return true; }}
function fxalertv(f1, v, f2) {if(document.getElementById(f1).value == v) { Element.show(f2); new Effect.Highlight(f2,{startcolor:'#ffcc55', endcolor:'#f0f0f0'}); return false; } else { return true; }}
function fxalert2(f1, f2, bf) {if(document.getElementById(f1).value == 0) { Element.show(f2); new Effect.Highlight(f2,{startcolor:'#ffcc55', endcolor:'#f0f0f0'}); return false; } else { bf.onclick = retfalse; return true; }}
function fxalert2v(f1, v, f2, bf) {if(document.getElementById(f1).value == v) { Element.show(f2); new Effect.Highlight(f2,{startcolor:'#ffcc55', endcolor:'#f0f0f0'}); return false; } else { bf.onclick = retfalse; return true; }}
function fxdcp(bf) { bf.onclick = retfalse; return true; }
function clralert(f) { if(document.getElementById(f).style.display != 'none') {new Effect.Fade(f); }}
function ssft(len, name, cur, target, targetval) {for(i=0; i< len; i++){a=document.getElementById(name + String(i)); a.style.background = 'none'; }; a=document.getElementById(name + String(cur)); a.style.background = 'url("/images/listbg3b4.gif") repeat'; document.getElementById(target).value = targetval;}
function toggleme2(f1, f2) { a=document.getElementById(f1); a.checked = !a.checked; if(a.checked) { document.getElementById(f2).style.borderColor = '#000';} else {document.getElementById(f2).style.borderColor = '#ccc';} }
function vis(f) {document.getElementById(f).style.visibility='visible';}
function invis(f) {document.getElementById(f).style.visibility='hidden';}
function setfie(f,v) {document.getElementById(f).value = v;}
function upldbuha(pid,ego,wt){
Element.hide('pbupload_placeholder' + String(pid)); Element.hide('pupload_placeholder' + String(pid)); Element.hide('pupload_placeholdera' + String(pid)); Element.hide('pupload_wait' + String(pid));Element.hide('pupload_waita' + String(pid));for(i=1;i<=14;i++){a=document.getElementById('tabrupl'+i); if(a){a.style.background='none';}};document.getElementById(ego).style.background='url(\"/images/winbgb2.gif\") repeat left top';
if(wt.length > 0){Element.show(String(wt) + String(pid));}}
function dnldbuha(mynm,clr2,ego){if(clr2.length > 0){a=document.getElementById(clr2); if(a){a.innerHTML = ''}}; if(mynm.length > 0){a=document.getElementById('ff_fl'); if(a){a.innerHTML = mynm;}} for(i=1;i<=9;i++){a=document.getElementById('tabupl'+i); if(a){a.style.background='none'};};a=document.getElementById(ego);if(a){a.style.background='url(\"/images/winbgb2.gif\") repeat left top'};}
function dnldcan(ae,ta,ff) { peh(ae);a=document.getElementById(ta);if(a){a.style.background='none';}if(ff.length>0 && (a=document.getElementById(ff))){a.name='getlost';}}
function chkupl(f,su,sp) { if(a=document.getElementById(f)){ if(a.value.length > 1) {document.getElementById(su).disabled = 'disabled'; transf_spin(sp); return true;}} return false;}
function chkupl_fb(f) { if(a=document.getElementById(f)){ if(a.value.length > 1) {return true;}} return false;}
function upldcan(ae,ta) { peh(ae);a=document.getElementById(ta);if(a){a.style.background='none';}}
function ihtml(f,v) {document.getElementById(f).innerHTML = v;}
function peh(f) { Element.hide(f); }
function pes(f) { Element.show(f); }
function stbcl(f, c) {var a=document.getElementById(f);if(a){a.className = "boxinboxarea2" + c;}}
function pmixh(cl,i,nm,igs,vs) { clralert('falert');ssbt(cl,'decor',i ,'post_effect',nm);setfie('post_ignsel',igs);document.getElementById('mixrot1').style.visibility=vs;document.getElementById('mixrot2').style.visibility=vs;pfireecv('post_effect'); }
function ccc_gc(x, y) {
if(x<0) x=0; if(y<0) y=0; if(x>219) x=219; if(y>191) y=191;
if(x <= 13) { ar = ["ff0000", "ffff00", "00ff00", "00ffff", "0000ff", "ff00ff"]; v = ar[parseInt(String(y / 32))];
} else if (x <= 27) {
if(y<=31) v = 'ffffff';
else if (y >= 160) v = '000000';
else {a=Math.round((160-y) * 255 / 128).toString(16); if(a.length == 1) {a = "0" + a;} v = a + a + a;}
} else {
x-=28;y=(191-y) * 255 / 191;
if(x < 32) {
r = y * 2; if (r > 255) r = 255;
b = y - 128; if(b < 0) { b=0; } else { b *= 2; if (b>255) b= 255; }
if(y < 128) { g = r * (x / 31); } else { g = b + ((255 - b) * x / 31); }
} else if (x < 64) {
x = 31 - (x - 32);
g = y * 2; if (g > 255) g = 255;
b = y - 128; if(b < 0) { b=0; } else { b *= 2; if (b>255) b= 255; }
if(y < 128) { r = g * (x / 31); } else { r = b + ((255 - b) * x / 31); }
} else if (x < 96) {
x -= 64;
g = y * 2; if (g > 255) g = 255;
r = y - 128; if(r < 0) { r=0; } else { r *= 2; if (r>255) r= 255; }
if(y < 128) { b = g * (x / 31); } else { b = r + ((255 - r) * x / 31); }
} else if (x < 128) {
x = 31 - (x - 96);
b = y * 2; if (b > 255) b = 255;
r = y - 128; if(r < 0) { r=0; } else { r *= 2; if (r>255) r= 255; }
if(y < 128) { g = b * (x / 31); } else { g = r + ((255 - r) * x / 31); }
} else if (x < 160) {
x -= 128;
b = y * 2; if (b > 255) b = 255;
g = y - 128; if(g < 0) { g=0; } else { g *= 2; if (g>255) g= 255; }
if(y < 128) { r = b * (x / 31); } else { r = g + ((255 - g) * x / 31); }
} else {
x = 31 - (x - 160);
r = y * 2; if (r > 255) r = 255;
g = y - 128; if(g < 0) { g=0; } else { g *= 2; if (g>255) g= 255; }
if(y < 128) { b = r * (x / 31); } else { b = g + ((255 - g) * x / 31); }
}
rt = Math.round(r).toString(16); if (rt.length == 1) rt = "0" + rt;
gt = Math.round(g).toString(16); if (gt.length == 1) gt = "0" + gt;
bt = Math.round(b).toString(16); if (bt.length == 1) bt = "0" + bt;
v =  rt + gt + bt;
}
return v;
}
function ccc(event, mydiv, fc, ft) {
if(document.getElementById && !document.all) {
var top=0,left=0,elm=mydiv;
while (elm) {left += elm.offsetLeft;top += elm.offsetTop;elm = elm.offsetParent;}
x = event.pageX - left - 2; y = event.pageY - top - 2; if(navigator.userAgent.indexOf("AppleWebKit") > -1) { x=x-1; y=y-1;}
} else { x = event.offsetX;y=event.offsetY;}
v=ccc_gc(x, y);
document.getElementById(fc).style.backgroundColor='#'+v;
a=document.getElementById(ft);if(a){a.value=v;a.style.border='2px solid #ccc'; if(typeof a.onchange == 'function'){a.onchange();}}
}
function ccc_mm(event, mydiv, fc) {
if(document.getElementById && !document.all) {
var top=0,left=0,elm=mydiv;
while (elm) {left += elm.offsetLeft;top += elm.offsetTop;elm = elm.offsetParent;}
x = event.pageX - left - 2; y = event.pageY - top - 2; if(navigator.userAgent.indexOf("AppleWebKit") > -1) { x=x-1; y=y-1;}
} else { x = event.offsetX;y=event.offsetY;}
document.getElementById(fc).style.backgroundColor='#'+ccc_gc(x, y);
}
function transf_spin(f) { if(window.opera){ Element.show(f); } else { new Effect.Appear(f); } }

function myaddBookmark(title, url) {if ((typeof window.sidebar == "object") && (typeof window.sidebar.addPanel == "function")) {window.sidebar.addPanel(title, url, "");} else if(document.all) {window.external.AddFavorite(url, title);} else return false;}
function tac(name,target,maxl){var a = maxl - document.getElementById(name).value.length; if (a < 10) { var h = "<span style='color:#f00;'>" + a + "<span>" } else { var h = a } document.getElementById(target).innerHTML = h;}

function selboxswitcher(sb, sbbg, osz, sbg) { selboxswitcherv(sb, sbbg, osz, sbg, 100); }
function selboxswitcherv(sb, sbbg, osz, sbg, dist) {
var a=document.getElementById(sb); var b=document.getElementById(sbbg); var c=document.getElementById(sbg);
if(a.style.height==osz+'px'){a.style.height=(osz+dist) + 'px';b.style.backgroundPosition='0px ' + (osz-78+dist) + 'px';c.style.backgroundPosition='-143px 0px';}else{a.style.height=osz+'px';b.style.backgroundPosition='0px ' + (osz-78) + 'px';c.style.backgroundPosition='-46px 0px';};
}
function ptoolswitcher(nm,ic, pl) {
var a=document.getElementById(nm); var b=document.getElementById(ic);
if(a){if(a.style.height == (25+pl)+"px") { a.style.height = ''; b.style.backgroundPosition='-143px 0px'; } else { a.style.height = (25+pl)+"px"; a.style.overflow = "hidden"; b.style.backgroundPosition='-46px 0px'; }}
}
function premfixed(e1,e2) {
var rf, a=document.getElementById(e1); if(a) { a.style.display='block'; rf = a.offsetHeight; a.style.display='none';}
if(e2) { a=document.getElementById(e2); if(a) {a.style.display='block'; rf = a.offsetHeight; a.style.display='none';}}
}

/* dragobj */
var ie=document.all;
var nn6=document.getElementById&&!document.all;
var isdrag=false;
var dragObj;
function findPosX(obj) {
var curleft = 0;
if(obj.offsetParent) while(1) {
curleft += obj.offsetLeft;
if(!obj.offsetParent) break;
obj = obj.offsetParent;
} else if(obj.x) curleft += obj.x;
return curleft;
}
function findPosY(obj) {
var curtop = 0;
if(obj.offsetParent) while(1) {
curtop += obj.offsetTop;
if(!obj.offsetParent) break;
obj = obj.offsetParent;
}
else if(obj.y) curtop += obj.y;
return curtop;
}
function dragStart(e, id) {
dragObj = new Object();
if (id) dragObj.elNode = document.getElementById(id);
else { if (ie) dragObj.elNode = window.event.srcElement;
else if (nn6) dragObj.elNode = e.target;
if (dragObj.elNode.nodeType == 3) dragObj.elNode = dragObj.elNode.parentNode;
}
dragObj.x = nn6 ? e.clientX : event.clientX; dragObj.y = nn6 ? e.clientY : event.clientY;
dragObj.tx = findPosX(dragObj.elNode); dragObj.ty = findPosY(dragObj.elNode);
dragObj.sx = dragObj.elNode.offsetWidth - 4;  /* -4 because border is included */
if (isNaN(dragObj.tx)) dragObj.tx = 0;if (isNaN(dragObj.ty)) dragObj.ty = 0;
isdrag = true;
if (ie) {
document.attachEvent("onmousemove", dragGo);
document.attachEvent("onmouseup",   dragStop);
window.event.cancelBubble = true;
window.event.returnValue = false;
} else if (nn6) {
document.addEventListener("mousemove", dragGo,   true);
document.addEventListener("mouseup",   dragStop, true);
e.preventDefault();
}
return false;
}
function dragGo(e) {
if (isdrag) {
dragObj.elNode.style.left = (dragObj.tx + (nn6 ? e.clientX : event.clientX) - dragObj.x) + "px";
dragObj.elNode.style.top  = (dragObj.ty + (nn6 ? e.clientY : event.clientY) - dragObj.y) + "px";
dragObj.elNode.style.width = dragObj.sx + "px";  /* IE sometimes resizes, we don't want that */
return false;
}
}
function dragStop(event) {
if (ie) {
document.detachEvent("onmousemove", dragGo);
document.detachEvent("onmouseup",   dragStop);
} else if (nn6) {
document.removeEventListener("mousemove", dragGo,   true);
document.removeEventListener("mouseup",   dragStop, true);
}}
function ietruebody(){return (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body;}
function ptool_coords(event, mydiv, formx, formy, pw, ph) {
if(window.opera) {
document.getElementById(formx).value = Math.round(event.offsetX * pw / mydiv.offsetWidth);
document.getElementById(formy).value = Math.round(event.offsetY * ph / mydiv.offsetHeight);
} else if(document.getElementById && !document.all) {
if(typeof(event.layerX) != 'undefined') { var x = event.layerX;var y = event.layerY;
} else { var x = event.offsetX;var y = event.offsetY; }
document.getElementById(formx).value = Math.round(x * pw / mydiv.offsetWidth);
document.getElementById(formy).value = Math.round(y * ph / mydiv.offsetHeight);
} else {
document.getElementById(formx).value = Math.round(event.offsetX * pw / mydiv.offsetWidth);
document.getElementById(formy).value = Math.round(event.offsetY * ph / mydiv.offsetHeight);
}}
function dynupd_rot(imgel, pid) {
pes('rot_wspinner');peh('rot_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=12&pa=" + document.getElementById('post_targetangle').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
function dynupd_rot2(imgel, pid) {
if(document.getElementById('post_bc').value.length == 6 && document.getElementById('post_targetangle').value.charAt(0) != '>') {
updcol('rot2cs','post_bc');
pes('rot2_wspinner');peh('rot2_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=0&pa=" + (Number(String(document.getElementById('post_targetangle').value).replace(/,/g, ".")) % 360.0)  +
	"&pa2=" + document.getElementById('post_bc').value +
	"&pa3=" + (document.getElementById('post_cut').checked ? 1 : 0) +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_flip(imgel, pid) {
pes('flip_wspinner');peh('flip_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=13&pa=" + document.getElementById('post_fliph').value +
	"&pa2=" + document.getElementById('post_flipv').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
function dynupd_crop(imgel, pid) { /* obsolete */
var t = document.getElementById('post_preset').value.split('@',6);
if(t[0] == 1 && document.getElementById('post_cropres').checked) {
	document.getElementById('crw').innerHTML = t[3];
	document.getElementById('crh').innerHTML = t[4];
} else {
	chkcrsze('post_selright','post_selleft','crw'); chkcrsze('post_selbottom','post_seltop','crh');
}
pes('crop_wspinner');peh('crop_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=5&pa=" + document.getElementById('post_selleft').value +
	"&pa2=" + document.getElementById('post_seltop').value +
	"&pa3=" + document.getElementById('post_selright').value +
	"&pa4=" + document.getElementById('post_selbottom').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
function dynupd_crop2(imgel, pid) {
var t = document.getElementById('post_preset').value.split('@',6);
if(t[0] == 1 && document.getElementById('post_cropres666').checked) {
	document.getElementById('crw').innerHTML = t[3];
	document.getElementById('crh').innerHTML = t[4];
} else {
	chkcrsze('post_selright','post_selleft','crw'); chkcrsze('post_selbottom','post_seltop','crh');
}
if(imgel != undefined) {
 pes('crop_wspinner');peh('crop_warrow');
 document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=5&pa=" + document.getElementById('post_selleft').value +
	"&pa2=" + document.getElementById('post_seltop').value +
	"&pa3=" + document.getElementById('post_selright').value +
	"&pa4=" + document.getElementById('post_selbottom').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_cols(imgel, pid) {
pes('cols_wspinner');peh('cols_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=2&pa=" + document.getElementById('post_targetbri').value +
	"&pa2=" + document.getElementById('post_targetsat').value +
	"&pa3=" + document.getElementById('post_targethue').value +
	"&pa4=" + document.getElementById('post_targetcon').value +
	"&pa5=" + document.getElementById('post_targettem').value +
	"&pa6=" + document.getElementById('post_targetexp').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
function dynupd_colo(imgel, pid) {
var nu = "/photo/thumbnailmod/" + pid + "?op=20&pa=";
pes('colo_wspinner');peh('colo_warrow');
if(document.getElementById('post_targetop').value == 0) {
	var tmpp = 0;
	if(document.getElementById('post_sha').checked) tmpp |= 1;
	if(document.getElementById('post_mid').checked) tmpp |= 2;
	if(document.getElementById('post_hi').checked)  tmpp |= 4;
  	nu += "0&pa2=" + document.getElementById('post_targetred').value +
		"&pa3=" + document.getElementById('post_targetgreen').value +
		"&pa4=" + document.getElementById('post_targetblue').value +
		"&pa5=" + tmpp +
		"&pa6=" + (document.getElementById('post_lum').checked ? 1 : 0);
} else {
   	nu += "1&pa2=" + document.getElementById('post_targetlev1').value +
		"&pa3=" + document.getElementById('post_targetlev2').value +
		"&pa4=" + document.getElementById('post_targetlev3').value +
		"&pa5=" + document.getElementById('post_targetlev4').value +
		"&pa6=" + String(document.getElementById('post_targetlev5').value).replace(/,/g, ".");
}
document.getElementById(imgel).src = nu + "&klu=" + String(Math.floor(Math.random()*10001));
}
function dynupd_sep(imgel, pid) { /* obsolete */
var tmpp = document.getElementById('post_type').value;
if((tmpp != '0') && (tmpp != '1' || document.getElementById('post_bc').value.length == 6) && ((tmpp != '8' && tmpp != '15') || document.getElementById('post_bcc').value.length == 6) && (tmpp != '3' || (document.getElementById('post_bca').value.length == 6 && document.getElementById('post_bcb').value.length == 6)) && (tmpp != '9' || (document.getElementById('post_bcd').value.length == 6 && document.getElementById('post_bce').value.length == 6 && document.getElementById('post_bcf').value.length == 6))) {
updcol('sepcs','post_bc'); updcol('sepcsa','post_bca'); updcol('sepcsb','post_bcb'); updcol('sepcsc','post_bcc'); updcol('sepcsd','post_bcd'); updcol('sepcse','post_bce'); updcol('sepcsf','post_bcf');
pes('sep_wspinner');peh('sep_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=6&pa8=" + document.getElementById('post_mode').value +
	"&pa9=" + document.getElementById('post_sell').value +
	"&pa10=" + document.getElementById('post_selt').value +
	"&pa11=" + document.getElementById('post_selw').value +
	"&pa12=" + document.getElementById('post_selh').value +
	"&pa13=" + (document.getElementById('post_invert').checked ? 1 : 0) +
	"&pa=" + tmpp +
	"&pa2=" + ( (tmpp == 4) ? (200 - document.getElementById('post_targetbri').value) : document.getElementById('post_targetbri').value ) +
	"&pa3=" + document.getElementById('post_targetcon').value +
	"&pa4=" + document.getElementById('post_targetopa').value;
switch(Number(tmpp)) {
case 1: nu += ("&pa5=" + document.getElementById('post_bc').value);
	break;
case 3:	nu += ( "&pa5=" + document.getElementById('post_bca').value +
		"&pa6=" + document.getElementById('post_bcb').value );
	break;
case 8:
case 15:nu += ("&pa5=" + document.getElementById('post_bcc').value);
	break;
case 9:	nu += ( "&pa5=" + document.getElementById('post_bcd').value +
		"&pa6=" + document.getElementById('post_bce').value +
		"&pa7=" + document.getElementById('post_bcf').value );
	break;
case 12:
case 17:
case 18:nu += ("&pa5=" + document.getElementById('post_generic').value);
	break;
case 13:
case 26:nu += ( "&pa5=" + document.getElementById('post_generic').value +
		"&pa6=" + (document.getElementById('post_genc').checked ? 1 : 0) );
	break;
case 14:nu += ( "&pa5=" + (document.getElementById('post_sobh').checked ? 1 : 0) +
		"&pa6=" + (document.getElementById('post_sobv').checked ? 1 : 0) +
		"&pa7=" + (document.getElementById('post_sobod').checked ? 1 : 0) );
	break;
}
document.getElementById(imgel).src = nu + "&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_sep2(imgel, pid) {
var tmpp = document.getElementById('post_type').value;
if((tmpp != '0') && (tmpp != '1' || document.getElementById('post_bc').value.length == 6) && ((tmpp != '8' && tmpp != '15') || document.getElementById('post_bcc').value.length == 6) && (tmpp != '3' || (document.getElementById('post_bca').value.length == 6 && document.getElementById('post_bcb').value.length == 6)) && (tmpp != '9' || (document.getElementById('post_bcd').value.length == 6 && document.getElementById('post_bce').value.length == 6 && document.getElementById('post_bcf').value.length == 6))) {
updcol('sepcs','post_bc'); updcol('sepcsa','post_bca'); updcol('sepcsb','post_bcb'); updcol('sepcsc','post_bcc'); updcol('sepcsd','post_bcd'); updcol('sepcse','post_bce'); updcol('sepcsf','post_bcf');
pes('sep_wspinner');peh('sep_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=6&pa8=" + document.getElementById('post_mode').value +
	"&pa9=" + document.getElementById('post_sell').value +
	"&pa10=" + document.getElementById('post_selt').value +
	"&pa11=" + document.getElementById('post_selw').value +
	"&pa12=" + document.getElementById('post_selh').value +
	"&pa13=" + (document.getElementById('post_invert').checked ? 1 : 0) +
	"&pa=" + tmpp +
	"&pa2=" + ( (tmpp == 4) ? (200 - document.getElementById('post_targetbri').value) : document.getElementById('post_targetbri').value ) +
	"&pa3=" + document.getElementById('post_targetcon').value +
	"&pa4=" + document.getElementById('post_targetopa').value;
switch(Number(tmpp)) {
case 1: nu += ("&pa5=" + document.getElementById('post_bc').value);
	break;
case 2: if(document.getElementById('post_bwty_0').checked) nu += ("&pa5=0");
	else if(document.getElementById('post_bwty_1').checked) nu += ("&pa5=1");
	else if(document.getElementById('post_bwty_2').checked) nu += ("&pa5=2");
	break;
case 3:	nu += ( "&pa5=" + document.getElementById('post_bca').value +
		"&pa6=" + document.getElementById('post_bcb').value );
	break;
case 8:
case 15:nu += ("&pa5=" + document.getElementById('post_bcc').value);
	break;
case 9:	nu += ( "&pa5=" + document.getElementById('post_bcd').value +
		"&pa6=" + document.getElementById('post_bce').value +
		"&pa7=" + document.getElementById('post_bcf').value );
	break;
case 12:
case 17:
case 18:nu += ("&pa5=" + document.getElementById('post_generic').value);
	break;
case 13:
case 26:nu += ( "&pa5=" + document.getElementById('post_generic').value +
		"&pa6=" + (document.getElementById('post_genc').checked ? 1 : 0) );
	break;
case 14:nu += ( "&pa5=" + (document.getElementById('post_sobh').checked ? 1 : 0) +
		"&pa6=" + (document.getElementById('post_sobv').checked ? 1 : 0) +
		"&pa7=" + (document.getElementById('post_sobod').checked ? 1 : 0) );
	break;
}
document.getElementById(imgel).src = nu + "&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_re(imgel, type, pid) {
if(type != 0 || document.getElementById('post_th').value.charAt(0) != '>') {
if(type == 0) {
pes('re_wspinner');peh('re_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=30&pa=" + document.getElementById('post_sell').value +
	"&pa2=" + document.getElementById('post_selt').value +
	"&pa3=" + document.getElementById('post_selw').value +
	"&pa4=" + document.getElementById('post_selh').value +
	"&pa5=" + document.getElementById('post_th').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
} else {
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=31&pa=" + document.getElementById('post_sell').value +
	"&pa2=" + document.getElementById('post_selt').value +
	"&pa3=" + document.getElementById('post_selw').value +
	"&pa4=" + document.getElementById('post_selh').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
}
function dynupd_lomo(imgel, pid) { /* obsolete */
var tmpt = document.getElementById('post_type').value;
if((tmpt != '0')  && (tmpt != '2' || document.getElementById('post_bc').value.length == 6)) {
updcol('lomocs','post_bc'); updcol('lomocs2','post_bc'); updcol('lomobcs','post_bbc'); updcol('lomogcs','post_gbc');
pes('lomo_wspinner');peh('lomo_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=23&pa=" + document.getElementById('post_targetint').value +
	"&pa2=" + (document.getElementById('post_sat').checked ? 1 : 0) +
	"&pa3=" + (document.getElementById('post_bri').checked ? 1 : 0) +
	"&pa4=" + tmpt +
	"&pa5=" + document.getElementById('post_bc').value +
	"&pa6=" + document.getElementById('post_targetopa').value +
	"&pa7=" + document.getElementById('post_targetsha').value +
	"&pa8=" + document.getElementById('post_targetshi').value +
	"&pa9=" + document.getElementById('post_mode').value +
	"&pa10=" + document.getElementById('post_cenx').value +
	"&pa11=" + document.getElementById('post_ceny').value +
	"&pa12=" + document.getElementById('post_targetrot').value +
	"&pa13=" + (document.getElementById('post_blr').checked ? 1 : 0) +
	"&pa14=" + (document.getElementById('post_dar').checked ? 1 : 0) +
	"&pa15=" + (document.getElementById('post_tin').checked ? 1 : 0) +
	"&pa16=" + document.getElementById('post_bbc').value +
	"&pa17=" + document.getElementById('post_gbc').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_lomo2(imgel, pid) {
var tmpt = document.getElementById('post_type').value;
if((tmpt != '0')  && (tmpt != '2' || document.getElementById('post_bc').value.length == 6)) {
updcol('lomocs','post_bc'); updcol('lomocs2','post_bc'); updcol('lomobcs','post_bbc'); updcol('lomogcs','post_gbc');
pes('lomo_wspinner');peh('lomo_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=23&pa=" + document.getElementById('post_targetint').value +
	"&pa2=" + (document.getElementById('post_sat').checked ? 1 : 0) +
	"&pa3=" + (document.getElementById('post_bri').checked ? 1 : 0) +
	"&pa4=" + tmpt +
	"&pa5=" + document.getElementById('post_bc').value +
	"&pa6=" + document.getElementById('post_targetopa').value +
	"&pa7=" + document.getElementById('post_targetsha').value +
	"&pa8=" + document.getElementById('post_targetshi').value +
	"&pa9=" + document.getElementById('post_mode').value +
	"&pa10=" + document.getElementById('post_cenx').value +
	"&pa11=" + document.getElementById('post_ceny').value +
	"&pa12=" + document.getElementById('post_targetrot').value +
	"&pa13=" + (document.getElementById('post_blr').checked ? 1 : 0) +
	"&pa14=" + (document.getElementById('post_dar').checked ? 1 : 0) +
	"&pa15=" + (document.getElementById('post_tin').checked ? 1 : 0) +
	"&pa16=" + document.getElementById('post_bbc').value +
	"&pa17=" + document.getElementById('post_gbc').value +
	"&pa18=" + (document.getElementById('post_desat').checked ? 1 : 0) +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_fill(imgel, type, pid) {
if( (type == 19 && (document.getElementById('post_ty').value != -1 && document.getElementById('post_col').value.length == 6 && document.getElementById('post_bcol').value.length == 6)) ||
    (type == 22 && (document.getElementById('post_col').value.length == 6 && document.getElementById('post_bcol').value.length == 6 && document.getElementById('post_shape').value.charAt(0) != '>')) ) {
if(type == 19)  { updcol('filcs','post_col'); updcol('fil2cs','post_bcol'); }
else 		{ updcol('sb1cs','post_col'); updcol('sb2cs','post_bcol'); }
pes('fill_wspinner');peh('fill_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=" + type + "&pa=" + document.getElementById('post_selleft').value +
	"&pa2=" + document.getElementById('post_seltop').value +
	"&pa3=" + document.getElementById('post_selright').value +
	"&pa4=" + document.getElementById('post_selbottom').value +
	"&pa5=" + document.getElementById('post_col').value +
	"&pa6=" + document.getElementById('post_opacity').value +
	"&pa7=" + document.getElementById('post_ty').value +
	"&pa8=" + document.getElementById('post_grav').value +
	"&pa9=" + ((type == 22) ? document.getElementById('post_shape').value : 0) +
	"&pa10=" + document.getElementById('post_bcol').value +
	"&pa11=" + document.getElementById('post_mode').value +
	"&pa12=" + ((type == 19 && document.getElementById('post_fcolyn').checked) ? 1 : 0) +
	"&pa13=" + (document.getElementById('post_bcolyn').checked ? 1 : 0) +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_ann(imgel, img2el, pid) {
if(document.getElementById('post_col').value.length == 6 && document.getElementById('post_bcol').value.length == 6 && document.getElementById('post_text').value.length > 0 && document.getElementById('post_angle').value.charAt(0) != '>' && document.getElementById('post_font').value.length > 0) {
updcol('anncs','post_col'); updcol('ann2cs','post_bcol'); updcol('ann3cs','post_scol');
try {pes('ann_wspinner');peh('ann_warrow');} catch(err) {}
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=16&pa=" + document.getElementById('post_sell').value +
	"&pa2=" + document.getElementById('post_selt').value +
	"&pa3=" + document.getElementById('post_selw').value +
	"&pa4=" + document.getElementById('post_selh').value +
	"&pa5=" + document.getElementById('post_grav').value +
	"&pa6=" + document.getElementById('post_col').value +
	"&pa7=" + document.getElementById('post_font').value +
	"&pa8=" + document.getElementById('post_fontsize').value +
	"&pa9=" + (document.getElementById('post_ital').checked ? 1 : 0) +
	"&pa10=" + (document.getElementById('post_bold').checked ? 1 : 0) +
	"&pa11=" + (document.getElementById('post_undr').checked ? 1 : 0) +
	"&pa12=" + encodeURIComponent(document.getElementById('post_text').value) +
	"&pa13=" + document.getElementById('post_angle').value +
	"&pa14=" + document.getElementById('post_bcol').value +
	"&pa15=" + (document.getElementById('post_outl').checked ? 1 : 0) +
	"&pa16=" + (document.getElementById('post_tran').checked ? 1 : 0) +
	"&pa17=" + document.getElementById('post_targetopa').value +
	"&pa18=" + document.getElementById('post_mode').value +
	"&pa19=" + document.getElementById('post_sdis').value +
	"&pa20=" + document.getElementById('post_scol').value +
	"&pa21=" + document.getElementById('post_sangle').value +
	"&pa22=" + document.getElementById('post_sopa').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
document.getElementById(img2el).src = "/photo/thumbnailmod/" + pid +
	"?op=17&pa=" + document.getElementById('post_col').value +
	"&pa2=" + document.getElementById('post_font').value +
	"&pa3=" + document.getElementById('post_fontsize').value +
	"&pa4=" + (document.getElementById('post_ital').checked ? 1 : 0) +
	"&pa5=" + (document.getElementById('post_bold').checked ? 1 : 0) +
	"&pa6=" + (document.getElementById('post_undr').checked ? 1 : 0) +
	"&pa7=" + encodeURIComponent(document.getElementById('post_text').value) +
	"&pa8=" + document.getElementById('post_angle').value +
	"&pa9=" + document.getElementById('post_bcol').value +
	"&pa10=" + (document.getElementById('post_outl').checked ? 1 : 0) +
	"&pa11=" + (document.getElementById('post_tran').checked ? 1 : 0) +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_desp(imgel, img2el, pid) {
var tmpt = document.getElementById('post_dt').value;
if(tmpt != '0') {
pes('desp_wspinner');peh('desp_warrow');
var dl = 0, algo = 0;
if(tmpt == '1') {
	if(document.getElementById('post_algo_1').checked) algo = 1;
	else if(document.getElementById('post_algo_2').checked) algo = 2;
	else if(document.getElementById('post_algo_3').checked) algo = 3;
} else if(tmpt == '2') {
	if(document.getElementById('post_gd').checked) dl |= 1;
	if(document.getElementById('post_gl').checked) dl |= 2;
}
var nu = "/photo/thumbnailmod/" + pid +
	"?op=14&pa=" + ((tmpt == 1) ?  algo : document.getElementById('post_grain').value) +
	"&pa7=" + tmpt + "&pa8=" + dl +
	"&pa9=" + document.getElementById('post_vl').value +
	"&pa10=" + document.getElementById('post_vt').value;
if(document.getElementById('post_lock').value == 0) {
	document.getElementById(imgel).src = nu + "&pa6=0&klu=" + String(Math.floor(Math.random()*10001));
} else {
	document.getElementById('post_lock').value = 0;
}
document.getElementById(img2el).src = nu + "&pa6=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_sha(imgel, img2el, pid) {
var tmpt = document.getElementById('post_st').value;
if(tmpt != '0') {
pes('sharpen_wspinner');peh('sharpen_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=10&pa=" + document.getElementById('post_si').value +
	"&pa2=" + document.getElementById('post_sell').value +
	"&pa3=" + document.getElementById('post_selt').value +
	"&pa4=" + document.getElementById('post_selw').value +
	"&pa5=" + document.getElementById('post_selh').value +
	"&pa7=" + tmpt +
	"&pa8=" + String(document.getElementById('post_usmrad').value).replace(/,/g, ".") +
	"&pa9=" + document.getElementById('post_usmamo').value +
	"&pa10=" + document.getElementById('post_vl').value +
	"&pa11=" + document.getElementById('post_vt').value +
	"&pa12=" + (document.getElementById('post_invert').checked ? 1 : 0);
if(document.getElementById('post_lock').value == 0) {
	document.getElementById(imgel).src = nu + "&pa6=0&klu=" + String(Math.floor(Math.random()*10001));
} else {
	document.getElementById('post_lock').value = 0;
}
document.getElementById(img2el).src = nu + "&pa6=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_blur(imgel, img2el, pid) { /* obsolete */
var tmpt = document.getElementById('post_bt').value; var nut = "";
if(tmpt != '0') {
var nu = "/photo/thumbnailmod/" + pid +
	"?op=15&pa=" + tmpt +
	"&pa2=" + document.getElementById('post_bi').value +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa8=" + document.getElementById('post_targetopa').value +
	"&pa11=" + document.getElementById('post_mode').value +
	"&pa16=" + document.getElementById('post_vl').value +
	"&pa17=" + document.getElementById('post_vt').value +
	"&pa18=" + (document.getElementById('post_invert').checked ? 1 : 0);
switch(Number(tmpt)) {
case 2: nu +=  ("&pa9=" + document.getElementById('post_cenx').value +
		"&pa10=" + document.getElementById('post_ceny').value);
	break;
case 5:
case 8: nu +=  ("&pa9=" + document.getElementById('post_pw').value +
		"&pa10=" + document.getElementById('post_ph').value);
	break;
case 6: nu +=  ("&pa9=" + document.getElementById('post_angle').value +
		"&pa10=" + document.getElementById('post_len').value);
	break;
case 7:
case 9: nu += ( "&pa9=" + (document.getElementById('post_outw').checked ? 1 : 0) +
		"&pa10=" + document.getElementById('post_len').value +
		"&pa12=" + document.getElementById('post_cenx').value +
		"&pa13=" + document.getElementById('post_ceny').value +
		"&pa14=" + document.getElementById('post_angle').value );
	nut = "&pa15=" + (document.getElementById('post_shcn').checked ? 1 : 0);
	break;
}
if((tmpt != '5' && tmpt != '8') || document.getElementById('post_ok').value == '1') {
pes('blur_wspinner');peh('blur_warrow');
if(document.getElementById('post_lock').value == 0) {
	document.getElementById(imgel).src = nu + nut + "&pa7=0&klu=" + String(Math.floor(Math.random()*10001));
} else {
	document.getElementById('post_lock').value = 0;
}
document.getElementById(img2el).src = nu + "&pa7=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
}
function dynupd_blur2(imgel, img2el, pid, prevonly) {
var tmpt = document.getElementById('post_bt').value; var nut = "";
if(tmpt != '0') {
var nu = "/photo/thumbnailmod/" + pid +
	"?op=15&pa=" + tmpt +
	"&pa2=" + document.getElementById('post_bi').value +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa8=" + document.getElementById('post_targetopa').value +
	"&pa11=" + document.getElementById('post_mode').value +
	"&pa16=" + document.getElementById('post_vl').value +
	"&pa17=" + document.getElementById('post_vt').value +
	"&pa18=" + (document.getElementById('post_invert').checked ? 1 : 0);
switch(Number(tmpt)) {
case 2: nu +=  ("&pa9=" + document.getElementById('post_cenx').value +
		"&pa10=" + document.getElementById('post_ceny').value);
	break;
case 5:
case 8: nu +=  ("&pa9=" + document.getElementById('post_pw').value +
		"&pa10=" + document.getElementById('post_ph').value);
	break;
case 6: nu +=  ("&pa9=" + document.getElementById('post_angle').value +
		"&pa10=" + document.getElementById('post_len').value);
	break;
case 7:
case 9: nu += ( "&pa9=" + (document.getElementById('post_outw').checked ? 1 : 0) +
		"&pa10=" + document.getElementById('post_len').value +
		"&pa12=" + document.getElementById('post_cenx').value +
		"&pa13=" + document.getElementById('post_ceny').value +
		"&pa14=" + document.getElementById('post_angle').value +
		"&pa19=" + (document.getElementById('post_dark').checked ? 1 : 0) +
		"&pa20=" + (document.getElementById('post_bw').checked ? 1 : 0));
	nut = "&pa15=" + (document.getElementById('post_shcn666').checked ? 1 : 0);
	break;
}
if((tmpt != '5' && tmpt != '8') || document.getElementById('post_ok').value == '1') {
 pes('blur_wspinner');peh('blur_warrow');
 if(document.getElementById('post_lock').value == 0) {
	document.getElementById(imgel).src = nu + nut + "&pa7=0&klu=" + String(Math.floor(Math.random()*10001));
 } else {
	document.getElementById('post_lock').value = 0;
 }
 if(!prevonly) {
	document.getElementById(img2el).src = nu + "&pa7=1&klu=" + String(Math.floor(Math.random()*10001));
 }
}}}
function dynupd_fx(imgel, img2el, pid) {
var tmpt = Number(document.getElementById('post_effect').value);
if(tmpt != 0) {
pes('fx_wspinner');peh('fx_warrow');
if(tmpt < 70 || tmpt > 91) tmpt = 97;
var nu = "/photo/thumbnailmod/" + pid + "?op=" + String(tmpt) +
	"&pa=" + document.getElementById('post_targetopa').value +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa7=" + document.getElementById('post_targetint').value +
	"&pa8=" + document.getElementById('post_mode').value +
	"&pa9=" + document.getElementById('post_vl').value +
	"&pa10=" + document.getElementById('post_vt').value +
	"&pa11=" + (document.getElementById('post_invert').checked ? 1 : 0);
if(document.getElementById('post_lock').value == 0) {
	document.getElementById(imgel).src = nu + "&pa2=0&klu=" + String(Math.floor(Math.random()*10001));
} else {
	document.getElementById('post_lock').value = 0;
}
document.getElementById(img2el).src = nu + "&pa2=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_mf(imgel, pid) {
if(document.getElementById('post_col').value.length == 6 && document.getElementById('post_col2').value.length == 6 && document.getElementById('post_angle').value.charAt(0) != '>' && document.getElementById('post_bend').value.charAt(0) != '>') {
updcol('mf1cs','post_col'); updcol('mf2cs','post_col2');
pes('mf_wspinner');peh('mf_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=21&pa=" + document.getElementById('post_col').value +
	"&pa2=" + document.getElementById('post_col2').value +
	"&pa3=" + document.getElementById('post_angle').value +
	"&pa4=" + document.getElementById('post_bend').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_mix(imgel, img2el, pid) { /* obsolete */
var tmpt = document.getElementById('post_effect').value;
if((tmpt != '0') && (document.getElementById('post_targetangle').value.charAt(0) != '>')) {
pes('mix_wspinner');peh('mix_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=60&pa=" + (Number(tmpt) - 60) +
	"&pa2=" + document.getElementById('post_mopa').value +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa7=" + document.getElementById('post_mode').value +
	"&pa8=" + (Number(String(document.getElementById('post_targetangle').value).replace(/,/g, ".")) % 360.0)  +
	"&pa10=" + document.getElementById('post_xo').value +
	"&pa11=" + document.getElementById('post_yo').value +
	"&pa12=" + document.getElementById('post_targethue').value +
	"&pa13=" + document.getElementById('post_ignsel').value +
	"&pa14=" + (document.getElementById('post_prop').checked ? 1 : 0) +
	"&pa15=" + (document.getElementById('post_flip').checked ? 1 : 0) +
	"&pa16=" + (document.getElementById('post_flop').checked ? 1 : 0);
document.getElementById(img2el).src = nu + "&pa9=0&klu=" + String(Math.floor(Math.random()*10001));
document.getElementById(imgel).src = nu + "&pa9=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_mix_new(imgel, img2el, pid) {
var tmpt = document.getElementById('post_effect').value;
if((tmpt != '0') && (document.getElementById('post_targetangle').value.charAt(0) != '>')) {
pes('mix_wspinner');peh('mix_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=60&pa=" + (Number(tmpt) - 60) +
	"&pa2=" + document.getElementById('post_mopa').value +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa7=" + document.getElementById('post_mode').value +
	"&pa8=" + (Number(String(document.getElementById('post_targetangle').value).replace(/,/g, ".")) % 360.0)  +
	"&pa10=" + document.getElementById('post_xo').value +
	"&pa11=" + document.getElementById('post_yo').value +
	"&pa12=" + document.getElementById('post_targethue').value +
	"&pa13=" + document.getElementById('post_ignsel').value +
	"&pa14=" + (document.getElementById('post_prop').checked ? 1 : 0) +
	"&pa15=" + (document.getElementById('post_flip').checked ? 1 : 0) +
	"&pa16=" + (document.getElementById('post_flop').checked ? 1 : 0) +
	"&pa17=" + (document.getElementById('post_desat').checked ? 1 : 0);
document.getElementById(img2el).src = nu + "&pa9=0&klu=" + String(Math.floor(Math.random()*10001));
document.getElementById(imgel).src = nu + "&pa9=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_mix2(imgel, img2el, pid) {
var tmpt = document.getElementById('post_effect').value;
if(tmpt != '0') {
updcol('mix22cs','post_ocol');
pes('mix2_wspinner');peh('mix2_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=59&pa=" + tmpt +
	"&pa2=" + document.getElementById('post_mopa').value +
	"&pa4=" + document.getElementById('post_mixdest').value +
	"&pa5=" + document.getElementById('post_sell').value +
	"&pa6=" + document.getElementById('post_selt').value +
	"&pa7=" + document.getElementById('post_selw').value +
	"&pa8=" + document.getElementById('post_selh').value +
	"&pa9=" + document.getElementById('post_mode').value +
	"&pa10=" + document.getElementById('post_ocol').value +
	"&pa11=" + (document.getElementById('post_ocolyn').checked ? 1 : 0) +
	"&pa12=" + document.getElementById('post_ocolfz').value;
document.getElementById(img2el).src = nu + "&pa3=0&klu=" + String(Math.floor(Math.random()*10001));
document.getElementById(imgel).src = nu + "&pa3=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_mix3(imgel, img2el, pid) {
var tmpt = document.getElementById('post_effect').value;
if((tmpt != '0') && (document.getElementById('post_targetangle').value.charAt(0) != '>')) {
pes('mix3_wspinner');peh('mix3_warrow');
var nu = "/photo/thumbnailmod/" + pid +
	"?op=61&pa=" + tmpt +
	"&pa3=" + document.getElementById('post_sell').value +
	"&pa4=" + document.getElementById('post_selt').value +
	"&pa5=" + document.getElementById('post_selw').value +
	"&pa6=" + document.getElementById('post_selh').value +
	"&pa7=" + (Number(String(document.getElementById('post_targetangle').value).replace(/,/g, ".")) % 360.0)  +
	"&pa9=" + document.getElementById('post_xo').value +
	"&pa10=" + document.getElementById('post_yo').value +
	"&pa11=" + document.getElementById('post_targetexp').value +
	"&pa12=" + document.getElementById('post_targetsat').value +
	"&pa13=" + document.getElementById('post_targethue').value;
document.getElementById(img2el).src = nu + "&pa8=0&klu=" + String(Math.floor(Math.random()*10001));
document.getElementById(imgel).src = nu + "&pa8=1&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_rnd(imgel, pid) {
if(document.getElementById('post_bc').value.length == 6 && document.getElementById('post_targetangle').value.charAt(0) != '>') {
updcol('roucs','post_bc');
pes('round_wspinner');peh('round_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=18&pa=" + document.getElementById('post_targetangle').value +
	"&pa2=" + document.getElementById('post_bc').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_bor(imgel, pid) {
var tmpt = document.getElementById('post_ty').value;
if((tmpt != '0') && (document.getElementById('post_bc').value.length == 6 || tmpt == 6 || tmpt == 7 || tmpt == 3 || tmpt == 4)) {
updcol('borbcs','post_bbc'); updcol('borcs','post_bc'); updcol('borcs2','post_bc');
if(tmpt != 6 && tmpt != 7 && tmpt != 3 && tmpt != 4) document.getElementById('post_bc').style.border='2px solid #ccc';
pes('bor_wspinner');peh('bor_warrow');
document.getElementById(imgel).src = "/photo/thumbnailmod/" + pid +
	"?op=11&pa=" + document.getElementById('post_bw').value +
	"&pa3=" + document.getElementById('post_bc').value +
	"&pa4=" + tmpt +
	"&pa5=" + (document.getElementById('post_tin').checked ? 1 : 0) +
	"&pa6=" + (document.getElementById('post_dar').checked ? 1 : 0) +
	"&pa7=" + (document.getElementById('post_blr').checked ? 1 : 0) +
	"&pa8=" + document.getElementById('post_bbc').value +
	"&pa9=" + document.getElementById('post_shab').value +
	"&pa10=" + document.getElementById('post_th2').value +
	"&klu=" + String(Math.floor(Math.random()*10001));
}
}
function dynupd_opa(ths, f1, f2) { if(ths.value != '7' && ths.value != '8' && ths.value != '11' && ths.value != '12' && ths.value != '13'){vis(f1);if(f2.length > 0) vis(f2);}else{invis(f1);if(f2.length > 0) invis(f2);}}

var STR_GEN_NO_THUMB = ["Thumbnail not available.","Thumbnail nicht verfügbar.", "Miniatura no disponible.","无法预览。", "無法預覽。", "プレビューを使用できません."];
function addprot(fn) { return (fn.substr(0,4).toLowerCase() == "http") ? fn : "http://"+fn; }
function decturl(url) { return addprot(unescape(url)); }
function deccomm(com) { try { return (com ? decodeURIComponent(com).substr(0,40) + (decodeURIComponent(com).length > 40 ? "..." : "") : "").replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/"/g,'&quot;'); } catch(err) { return "";}}

function dynupd_fb_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 4);}catch(err){}
if(pn && pn[1] && pn[1].length > 0) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[1]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[0]);
} else {document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}
function dynupd_fdown(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 3);}catch(err){}
if(pn && pn[1] && pn[1].length > 0) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[1]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[2]);
} else {document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}
function dynupd_fpn_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 4);}catch(err){}
if(pn && pn[0] != "0") {
if(pn[2] && pn[2].length > 0) {
	document.getElementById(divel).innerHTML='<img src="' + decturl(pn[2]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>';
} else {
	document.getElementById(divel).innerHTML="<br>" + STR_GEN_NO_THUMB[lai]
}
} else {document.getElementById(divel).innerHTML='';}
pes('fdownthumb');
}
function dynupd_ms_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 4);}catch(err){}
if(pn && pn[1] && pn[1].length > 0) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[1]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[0]);
} else {document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}
function dynupd_picasa_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 4);}catch(err){}
if(pn && pn[1] && pn[1].length > 0) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[1]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[0]);
} else {document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}
function dynupd_sm_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 4);}catch(err){}
if(pn && pn[1] && pn[1].length > 0) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[1]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[0]);
} else {document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}
function dynupd_ws_photo(divel,selb, lai) {
try{var pn = document.getElementById(selb).value.split("@+@", 3);}catch(err){}
if(pn && pn[0].length > 1) {
document.getElementById(divel).innerHTML='<img src="' + decturl(pn[0]) + '" alt="' + STR_GEN_NO_THUMB[lai] + '" title="" align="absmiddle" border="0" /><br>' + deccomm(pn[2]);
} else {
document.getElementById(divel).innerHTML=STR_GEN_NO_THUMB[lai]}
}

/* tt */
function getScrollingPosition(){
var position=[0,0];
if (typeof window.pageYOffset != 'undefined') {
position = [window.pageXOffset,window.pageYOffset];
} else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0) {
position = [document.documentElement.scrollLeft,document.documentElement.scrollTop];
} else if (typeof document.body.scrollTop != 'undefined') {
position = [document.body.scrollLeft,document.body.scrollTop];
}
return position;
}
function getViewportSize(){
var size=[0,0];
if (typeof window.innerWidth != 'undefined') {
size = [window.innerWidth,window.innerHeight];
} else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
size = [document.documentElement.clientWidth,document.documentElement.clientHeight];
} else {
size = [document.getElementsByTagName('body')[0].clientWidth,document.getElementsByTagName('body')[0].clientHeight];
}
return size;
}
function ddrivetip(thetext, thecolor, thewidth){
if ((ns6||ie) && thetext.length > 0) {
if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px";
if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor;
tipobj.innerHTML=thetext;
enabletip=true;
return false;
}
}
function positiontip(e){
if (enabletip) {
var viewportSize = getViewportSize();
var scrollPos = getScrollingPosition();
var curPos=[0, 0];
curPos[0]=(ns6) ? e.pageX : event.clientX+scrollPos[0];
curPos[1]=(ns6) ? e.pageY : event.clientY+scrollPos[1];
var leftedge = (offsetxpoint < 0) ? offsetxpoint*(-1) : -1000;
if (curPos[0] - scrollPos[0] + offsetxpoint + tipobj.offsetWidth > viewportSize[0] - 25)
	tipobj.style.left = scrollPos[0] + viewportSize[0] - 25 - tipobj.offsetWidth + "px";
else if (curPos[0]<leftedge)
	tipobj.style.left="5px";
else
	tipobj.style.left=curPos[0]+offsetxpoint+"px";
if (curPos[1] - scrollPos[1] + offsetypoint + tipobj.offsetHeight > viewportSize[1] - 25)
	tipobj.style.top=curPos[1]-tipobj.offsetHeight-offsetypoint+"px";
else
	tipobj.style.top=curPos[1]+offsetypoint+"px";
tipobj.style.visibility="visible";
}
}
function hideddrivetip(){
if (ns6||ie){
enabletip=false;
tipobj.style.visibility="hidden";
tipobj.style.left="-1000px";
tipobj.style.backgroundColor='';
tipobj.style.width='';
}
}
/* Facebook tagger
   (C) 2007-2010 Thomas Winischhofer, Vienna, Austria
*/

var FBTags = {
	fbtgs: [],
	observer: [],

	register: function(fbtaghandler) {
		if(this.fbtgs.length == 0) {
			this.eventMouseUp   = this.endfbtag.bindAsEventListener(this);
			this.eventMouseMove = this.dohandlefbtag.bindAsEventListener(this);
			Event.observe(document, "mouseup", this.eventMouseUp);
			Event.observe(document, "mousemove", this.eventMouseMove);
		}
		this.fbtgs.push(fbtaghandler);
	},

	unregister: function(fbtaghandler) {
		this.fbtgs = this.fbtgs.reject(function(s) { return s==fbtaghandler });
		if(this.fbtgs.length == 0) {
			Event.stopObserving(document, "mouseup", this.eventMouseUp);
			Event.stopObserving(document, "mousemove", this.eventMouseMove);
		}
	},

	activate: function(fbtaghandler) {
		this.activeFBTagHandler = fbtaghandler;
	},

	deactivate: function() {
		this.activeFBTagHandler = null;
	},

	endfbtag: function(event) {
		if(!this.activeFBTagHandler) return;
		this._lastPointer = null;
		this.activeFBTagHandler.endfbtag(event);
		this.activeFBTagHandler = null;
	},

	dohandlefbtag: function(event) {
		if(!this.activeFBTagHandler) return;
		//if (this.activeFBTagHandler.showcoords) {
		//	document.getElementById(this.activeFBTagHandler.showcoords).innerHTML = Event.pointerX(event) + "x" + Event.pointerY(event);
		//}
		var pointer = [Event.pointerX(event), Event.pointerY(event)];
		// 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.activeFBTagHandler.dohandlefbtag(event);
	}
}

var FBTagHandlers = Class.create();

FBTagHandlers.prototype = {

initialize: function(myelementid, containerid, phototags, options) {
	var fbtaghandler = this;

	if(this.initialized) {
		this.dispose();
	}

	this.myelementid = myelementid;

	this.myelement = document.getElementById(myelementid);
	this.container = document.getElementById(containerid);

	this.options = options || {};

	this.imgw = this.options.iwidth || this.myelement.offsetWidth;
	this.imgh = this.options.iheight || this.myelement.offsetHeight;

	this.maskid = this.options.mask || this.myelementid + '_mask';

	this.fbtagimageid = this.options.fbtag || this.myelementid + '_fbtag';

	this.imgsrc = this.myelement.src;
	this.fbtag = null;
	this.curroffsx = 0;
	this.curroffsy = 0;
	this.startcoords = null;
	this.startleft = 0;
	this.starttop = 0;
	this.layercoords = null;
	this.oldabscoords = { x: 0, y: 0 };
	this.newabscoords = null;

	this.pevent = {};

	this.onChange = this.options.onChange || Prototype.emptyFunction;

	this.ns6 = document.getElementById && !document.all;
	this.ie = document.all;

	this.eventMouseDown = this.newfbtag.bindAsEventListener(this);
	this.eventMouseUp   = this.endfbtag.bindAsEventListener(this);
	this.eventMouseDown2 = this.startmovefbtag.bindAsEventListener(this);
	this.eventOnClick = this.updatefbtag.bindAsEventListener(this);
	
	this.ptags = phototags || "";
	
	this.eventMouseOver = this.showtags.bindAsEventListener(this);
	this.eventMouseOut = this.hidetags.bindAsEventListener(this);
	
	this.offsetxpoint=-20;
	this.offsetypoint=25;
	this.enabletip=false;
	if (this.ie || this.ns6) {
		this.tipobj = document.all ? document.all["phototagdiv"] : document.getElementById ? document.getElementById("phototagdiv") : "";
	}

	if(this.imgw > 0) {
		this.initfbtag();
		this.fbtagimage =  document.getElementById(this.fbtagimageid);
		Event.observe(this.fbtagimage, "mousedown", this.eventMouseDown2);

		this.init();
		this.initialized = true;

	} else {
		this.eventOnLoad = this.myonload.bindAsEventListener(this);
		/* Event.observe(window, "load", this.eventOnLoad); */
		Event.observe(document.getElementById(myelementid), "load", this.eventOnLoad);
	}

	Event.observe(this.container, "mousedown", this.eventMouseDown);
	Event.observe(this.container, "mouseup", this.eventMouseUp);
	Event.observe(this.container, "click", this.eventOnClick);
	
	Event.observe(this.myelement, "mousemove", this.eventMouseOver);
	Event.observe(this.myelement, "mouseout", this.eventMouseOut);

	Event.observe(window, 'unload', Event.unloadCache, false);

	FBTags.register(this);
},

myonload: function(event) {
	this.imgw = this.myelement.offsetWidth;
	this.imgh = this.myelement.offsetHeight;

	this.initfbtag();
	this.fbtagimage =  document.getElementById(this.fbtagimageid);
	Event.observe(this.fbtagimage, "mousedown", this.eventMouseDown2);

	this.init();

	this.initialized = true;
},

destroy: function() {
	var fbtaghandler = this;
	Event.stopObserving(this.container, "mousedown", this.eventMouseDown);
	Event.stopObserving(this.container, "mouseup", this.eventMouseUp);
	Event.stopObserving(this.fbtagimage, "mousedown", this.eventMouseDown2);
	Event.stopObserving(this.container, "click", this.eventOnClick);

	Event.stopObserving(this.myelement, "mousemove", this.eventMouseOver);
	Event.stopObserving(this.myelement, "mouseout", this.eventMouseOut);

	Event.stopObserving(window, "unload", Event.unloadCache);
	if(this.eventOnLoad) {
		Event.stopObserving(window, "load", this.eventOnLoad);
	}
	FBTags.unregister(this);
},

iebody: function () {
	return (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body
},

getcoordX: function(event) {
	var clientX;
	if(event.pseudo) {
		clientX = event.clientX;
	} else {
		clientX = (this.ns6) ? event.pageX : event.clientX + this.iebody().scrollLeft;
	}
	return clientX;
},

getcoordY: function(event) {
	var clientY;
	if(event.pseudo) {
		clientY = event.clientY;
	} else {
		clientY = (this.ns6) ? event.pageY : event.clientY + this.iebody().scrollTop;
	}
	return clientY;
},

getScrollingPosition: function() {
	var position=[0,0];
	if (typeof window.pageYOffset != 'undefined') {
		position = [window.pageXOffset,window.pageYOffset];
	} else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0) {
		position = [document.documentElement.scrollLeft,document.documentElement.scrollTop];
	} else if (typeof document.body.scrollTop != 'undefined') {
		position = [document.body.scrollLeft,document.body.scrollTop];
	}
	return position;
},

getViewportSize: function() {
	var size=[0,0];
	if (typeof window.innerWidth != 'undefined') {
		size = [window.innerWidth,window.innerHeight];
	} else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
		size = [document.documentElement.clientWidth,document.documentElement.clientHeight];
	} else {
		size = [document.getElementsByTagName('body')[0].clientWidth,document.getElementsByTagName('body')[0].clientHeight];
	}
	return size;
},

positiontag: function(e) {
	if (this.enabletip) {
		var viewportSize = getViewportSize(); 
		var scrollPos = getScrollingPosition();
		var curPos = [0, 0];
		curPos[0] = (this.ns6) ? e.pageX : event.clientX + scrollPos[0];
		curPos[1] = (this.ns6) ? e.pageY : event.clientY + scrollPos[1];

		var leftedge = (offsetxpoint < 0) ? offsetxpoint*(-1) : -1000;

		if (curPos[0] - scrollPos[0] + offsetxpoint + this.tipobj.offsetWidth > viewportSize[0] - 20)
 			this.tipobj.style.left = scrollPos[0] + viewportSize[0] - 20 - this.tipobj.offsetWidth + "px";
		else if (curPos[0] < leftedge)
 			this.tipobj.style.left = "5px";
		else
 			this.tipobj.style.left = curPos[0]+offsetxpoint+"px";

		if (curPos[1] - scrollPos[1] + offsetypoint + this.tipobj.offsetHeight > viewportSize[1] - 20)
 			this.tipobj.style.top = curPos[1] - this.tipobj.offsetHeight - offsetypoint+"px";
		else
 			this.tipobj.style.top = curPos[1] + offsetypoint+"px";

		this.tipobj.style.visibility="visible";
	}
},

showfbtag: function(mytext) {
	if (this.ns6 || this.ie) {
		this.tipobj.innerHTML = mytext;
		this.enabletip = true;
	}
},

hidefbtag: function() {
	if (this.ns6 || this.ie) {
		this.enabletip = false;
		this.tipobj.style.visibility = "hidden";
		this.tipobj.style.left="-1000px";
		this.tipobj.style.backgroundColor = '';
		this.tipobj.style.width = '';
	}
},

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

newfbtag: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	if(event.stopPropagation) {
		event.stopPropagation();
	} else {
		event.cancelBubble = true;
	}
	
	this.hidefbtag();

	// Prevent caching issues: Re-do the mask in case the image dimensions have changed
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		var themask = document.getElementById(this.maskid);
		if(!themask) {
			// panic --- what happended?? not intialized???
			this.initfbtag();
			this.fbtagimage =  document.getElementById(this.fbtagimageid);
			Event.observe(this.fbtagimage, "mousedown", this.eventMouseDown2);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.fbtagimage.style.width = this.imgw + "px";
		themask.style.height = this.fbtagimage.style.height = this.imgh + "px";
	}

	if(this.fbtag.getvisible() != "visible") {
		var x;
		var y;
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);
		if(!document.all && event.layerX) {
			x = event.layerX;
			y = event.layerY;
		} else {
			x = event.offsetX;
			y = event.offsetY;
		}
		this.oldabscoords.x = clientX;
		this.oldabscoords.y = clientY;
		this.newabscoords = {x: clientX, y: clientY};
		this.layercoords  = {x: x + 1, y: y + 1};
		this.fbtag.draw(x, y, Math.max(this.imgw, this.imgh) / 4, this.imgw, this.imgh);
		
		var themask = document.getElementById(this.maskid);
		themask.style.visibility = "visible";
		
		this.startcoords = {x: clientX, y: clientY};
		this.startleft = this.fbtag.getLeft();
		this.starttop = this.fbtag.getTop();
		this.fbtag.drag = true;
	}

	FBTags.activate(this);

	return false;
},

endfbtag: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	if(event.stopPropagation) {
		event.stopPropagation();
	} else {
		event.cancelBubble = true;
	}
	var themask = document.getElementById(this.maskid);

	if(!document.all) {
		targetid = event.target.id;
	} else {
		targetid = event.srcElement.id;
	}

	if(this.fbtag.track) {
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);
		
		themask.style.visibility = "visible";
		this.fbtag.setcursor("default");

		this.oldabscoords.x = clientX;
		this.oldabscoords.y = clientY;
		
	} else if(this.fbtag.resize) {

	} else if(targetid == this.maskid || targetid == this.myelementid) {
		this.init();
	}

	this.fbtag.drag = false;
	this.fbtag.track = false;
	themask = null;

	this.updatefinished();

	FBTags.deactivate(this);
	
	this.hidefbtag();

	return false;
},

dohandlefbtag: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	if(this.fbtag.track || this.fbtag.drag) {
		if(event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
		this.pevent.clientX = clientX;
		this.pevent.clientY = clientY;
		this.pevent.pseudo = true;
		if(this.fbtag.drag) {
			this.dragfbtag(this.pevent);
		} 
	}
	this.oldabscoords.x = clientX;
	this.oldabscoords.y = clientY;

	return false;
},

startmovefbtag: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	this.startcoords = {x: clientX, y: clientY};
	this.startleft = this.fbtag.getLeft();
	this.starttop = this.fbtag.getTop();
	this.fbtag.drag = true;
	return false;
},

dragfbtag: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	var left = this.startleft + clientX - this.startcoords.x;
	var top = this.starttop + clientY - this.startcoords.y;
	var width = this.fbtag.getWidth();
	var height = this.fbtag.getHeight();

	if(left < (-(width / 2))) left = -(width / 2);

	if(top < -(height / 2)) top = -(height / 2);
	
	var maxright = this.imgw - (width / 2) - left;
	if(maxright < 0) left += maxright;
	
	var maxbottom = this.imgh - (height / 2) - top;
	if(maxbottom < 0) top += maxbottom;

	this.fbtag.dragto(left, top);
},


initfbtag: function() {
	this.fbtag = {
		left:		undefined,
		top:		undefined,
		width: 		undefined,
		height:		undefined,
		idLeft: 	"js_fbtagleft",
		idTop:		"js_fbtagtop",
		idRight:	"js_fbtagright",
		idBottom:	"js_fbtagbottom",
		idMid:	"js_fbtagmiddle",
		visible:	false,
		myparent:	this
	};
	
	this.hidefbtag();

	var left = document.createElement("div");
	var right = document.createElement("div");
	var top = document.createElement("div");
	var bottom = document.createElement("div");
	
	top.className = "fbthor";
	bottom.className = "fbthor";
	left.className = "fbtver";
	right.className = "fbtver";
	
	left.id = this.fbtag.idLeft;
	right.id = this.fbtag.idRight;
	top.id = this.fbtag.idTop;
	bottom.id = this.fbtag.idBottom;

	this.container.appendChild(top);
	this.container.appendChild(bottom);
	this.container.appendChild(left);
	this.container.appendChild(right);
	
	var mid = document.createElement("div");
	mid.className = "fbtmid";
	mid.id = this.fbtag.idMid;
	this.container.appendChild(mid);

	var mask = document.createElement("div");
	mask.id = this.maskid;
	mask.className = "image_fbmask";
	mask.style.width = this.imgw + "px";
	mask.style.height = this.imgh + "px";
	this.container.appendChild(mask);

	var image = document.createElement("img");
	image.id = this.fbtagimageid;
	image.className = "image_fbtag";
	image.src = this.imgsrc;
	image.style.width = this.imgw + "px";
	image.style.height = this.imgh + "px";
	this.container.appendChild(image);

	this.fbtag.reset = function() {
		this.left = undefined;
		this.top = undefined;
		this.width = undefined;
		this.height = undefined;
		this.setvisible("hidden");
		this.setcursor("crosshair");
		this.track = false;
		this.drag = false;
	};

	this.fbtag.draw = function(left, top, imgwidth, imgw, imgh) {
		this.width = width = this.height = height = imgwidth;
		this.left = left = left - (width / 2);
		this.top =  top = top - (height / 2);
		
		var clip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";
		this.myparent.fbtagimage.style.clip = clip;
	
		var dtop = document.getElementById(this.idTop);
		var dbottom = document.getElementById(this.idBottom);
		var dleft = document.getElementById(this.idLeft);
		var dright = document.getElementById(this.idRight);
		
		dleft.style.left = left + "px";
		dright.style.left = (left + width - 1) + "px";
		dtop.style.left = left + "px";
		dbottom.style.left = left + "px";

		dleft.style.top = top + "px";
		dright.style.top = top + "px";
		dtop.style.top = top + "px";
		dbottom.style.top = (top + height - 1) + "px";

		dleft.style.height = height + "px";
		dright.style.height = height + "px";
		dtop.style.width = width + "px";
		dbottom.style.width = width + "px";
		
		var dmid = document.getElementById(this.idMid);
		dmid.style.left = left + "px";
		dmid.style.top = top + "px";
		dmid.style.height = height + "px";
		dmid.style.width = width + "px";
		
		this.setvisible("visible");

		dleft = null;
		dtop = null;
		dright = null;
		dbottom = null;
		dmid = null;

		blkw = 6;
		if(width < 6) blkw = width;
		blkh = 6;
		if(height < 6) blkw = height;

	};

	this.fbtag.dragto = function(left, top) {
		this.left = left;
		this.top = top;
		var width = this.getWidth();
		var height = this.getHeight();

		var dl = document.getElementById(this.idLeft);
		var dr = document.getElementById(this.idRight);
		var dt = document.getElementById(this.idTop);
		var db = document.getElementById(this.idBottom);

		dl.style.left = left + "px";
		dr.style.left = left + width - 1 + "px";
		dt.style.left = left + "px";
		db.style.left = left + "px";

		dl.style.top = top + "px";
		dr.style.top = top + "px";
		dt.style.top = top + "px";
		db.style.top = top + height - 1 + "px";
		
		var dm = document.getElementById(this.idMid);
		dm.style.left = left + "px";
		dm.style.top = top + "px";
		dm = null;
		
		var myclip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";
		this.myparent.fbtagimage.style.clip = myclip;
		
		dl = null;
		dt = null;
		dr = null;
		db = null;
	};

	this.fbtag.setLeft = function(left) {
		this.left = left;
	};
	this.fbtag.getLeft = function() {
		return this.left;
	};

	this.fbtag.setTop = function(top) {
		this.top = top;
	};
	this.fbtag.getTop = function() {
		return this.top;
	};

	this.fbtag.setWidth = function(width) {
		this.width = width;
	};
	this.fbtag.getWidth = function() {
		return this.width;
	};

	this.fbtag.setHeight = function(height) {
		this.height = height;
	};
	this.fbtag.getHeight = function() {
		return this.height;
	};

	this.fbtag.setvisible = function(vis) {
		document.getElementById(this.idTop).style.visibility = vis;
		document.getElementById(this.idLeft).style.visibility = vis;
		document.getElementById(this.idRight).style.visibility = vis;
		document.getElementById(this.idBottom).style.visibility = vis;
		document.getElementById(this.idMid).style.visibility = vis;
		document.getElementById(this.myparent.fbtagimageid).style.visibility = vis;
		this.visibility = vis;
	};
	this.fbtag.getvisible = function() {
		return this.visibility;
	};

	this.fbtag.setcursor = function(cursor) {
		document.getElementById(this.idTop).style.cursor = cursor;
		document.getElementById(this.idLeft).style.cursor = cursor;
		document.getElementById(this.idRight).style.cursor = cursor;
		document.getElementById(this.idBottom).style.cursor = cursor;
		document.getElementById(this.myparent.fbtagimageid).style.cursor = cursor;
	};

},

init: function() {
	themask = document.getElementById(this.maskid);
	if(themask) {
		document.getElementById(this.maskid).style.visibility = "hidden";
	}
	this.layercoords = null;
	this.newabscoords = null;
	if(this.fbtag) {
		this.fbtag.reset();
	}
},

showtags: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	
	if (this.ptags.length == 0) {
		this.hidefbtag();
		return; 
	}
	
	if(!document.all && event.layerX) {
		x = event.layerX;
		y = event.layerY;
	} else {
		x = event.offsetX;
		y = event.offsetY;
	}
	
	tags = "";
	
	for(i=0; i<this.ptags.length; i++) {
		if (x >= this.ptags[i][0] && y >= this.ptags[i][1] && x <= this.ptags[i][2] && y <= this.ptags[i][3]) {
			if (tags.length > 0) tags = tags + "; ";
			tags = tags + this.ptags[i][4];
		}
	}
	
	if (tags.length > 0) {
		this.showfbtag(tags);
	} else {
		this.hidefbtag();
	}
	
	this.positiontag(event);
},

hidetags: function(event) {
	this.hidefbtag();
},

updatefinished: function() {
	if(this.initialized && this.onChange)  {
		tempw = Math.max(this.imgw, this.imgh) / 4;
		myleft = this.fbtag.left + (tempw / 2);
		if (myleft > 0) myleft = myleft / (this.imgw / 100);
	 	mytop = this.fbtag.top + (tempw / 2);
		if (mytop > 0) mytop = mytop / ( this.imgh / 100);
		if (isNaN(myleft) || isNaN(mytop)) { myleft = mytop = -1; }
		this.onChange(myleft, mytop);
	}
	this.event = null;
} 

};






/* Selection handling
   (C) 2006-2010 Thomas Winischhofer, Vienna, Austria
*/

var Selections = {
	sels: [],
	observer: [],

	register: function(selectionhandler) {
		if(this.sels.length == 0) {
			this.eventMouseUp   = this.endselection.bindAsEventListener(this);
			this.eventMouseMove = this.dohandleselection.bindAsEventListener(this);
			this.eventOnKeyDown = this.mykeydown.bindAsEventListener(this);
			this.eventOnKeyUp = this.mykeyup.bindAsEventListener(this);

			Event.observe(document, "mouseup", this.eventMouseUp);
			Event.observe(document, "mousemove", this.eventMouseMove);
			Event.observe(document, "keydown", this.eventOnKeyDown);
			Event.observe(document, "keyup", this.eventOnKeyUp);
		}
		this.sels = this.sels.reject(function(s) { return s.myelementid==selectionhandler.myelementid });
		this.sels.push(selectionhandler);
	},

	unregister: function(selectionhandler) {
		this.sels = this.sels.reject(function(s) { return s==selectionhandler });
		if(this.sels.length == 0) {
			Event.stopObserving(document, "mouseup", this.eventMouseUp);
			Event.stopObserving(document, "mousemove", this.eventMouseMove);
			Event.stopObserving(document, "keydown", this.eventOnKeyDown);
			Event.stopObserving(document, "keyup", this.eventOnKeyUp);
		}
	},

	activate: function(selectionhandler) {
		window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
		this.activeSelectionHandler = selectionhandler;
	},

	deactivate: function() {
		this.activeSelectionHandler = null;
	},

	endselection: function(event) {
		if(!this.activeSelectionHandler) return;
		this._lastPointer = null;
		this.activeSelectionHandler.endselection(event);
		this.activeSelectionHandler = null;
	},

	dohandleselection: function(event) {
		if(!this.activeSelectionHandler) return;
		//if (this.activeSelectionHandler.showcoords) {
		//	document.getElementById(this.activeSelectionHandler.showcoords).innerHTML = Event.pointerX(event) + "x" + Event.pointerY(event);
		//}
		var pointer = [Event.pointerX(event), Event.pointerY(event)];
		// 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.activeSelectionHandler.dohandleselection(event);
	},

	mykeydown: function(event) {
		if(this.activeSelectionHandler)
			this.activeSelectionHandler.mykeydown(event);
	},

	mykeyup: function(event) {
		if(this.activeSelectionHandler)
			this.activeSelectionHandler.mykeyup(event);
	}
}

var SelectionHandlers = Class.create();
SelectionHandlers.prototype = {

initialize: function(myelementid, containerid, clearcontainerid, selallcontainerid, coordscontainerid, options, onchangejs) {
	var selecthandler = this;

	if(this.initialized) {
		this.dispose();
	}

	this.myelementid = myelementid;

	this.myelement = document.getElementById(myelementid);
	this.container = document.getElementById(containerid);
	this.clearcontainer = document.getElementById(clearcontainerid);
	this.selallcontainer = document.getElementById(selallcontainerid);
	this.showcoords = coordscontainerid;

	this.scc = this.container.parentNode;

	this.options = options || {};

	this.imgw = this.options.iwidth || this.myelement.offsetWidth;
	this.imgh = this.options.iheight || this.myelement.offsetHeight;

	this.maskid = this.options.mask || this.myelementid + '_mask';

	this.selectionimageid = this.options.selection || this.myelementid + '_selection';
	this.idtl = "js_tl";	/* TODO: Add rnd number to id */
	this.idtm = "js_tm";
	this.idtr = "js_tr";
	this.idml = "js_ml";
	this.idmr = "js_mr";
	this.idbl = "js_bl";
	this.idbm = "js_bm";
	this.idbr = "js_br";

	this.snap = this.options.snap || 7;

	this.imgsrc = this.myelement.src;
	this.selection = null;
	this.curroffsx = 0;
	this.curroffsy = 0;
	this.startcoords = null;
	this.startleft = 0;
	this.starttop = 0;
	this.layercoords = null;
	this.oldabscoords = { x: 0, y: 0 };
	this.newabscoords = null;
	this.key = 0;
	this.ctrlkey = false;
	this.shiftkey = false;
	this.pevent = {};

	this.onChange = this.options.onChange || Prototype.emptyFunction;
	this.onChangeJS = onchangejs || null;
	this.setCook = this.options.setcook || 0;

	this.pwidth = this.options.pw || 0;
	this.pheight = this.options.ph || 0;
	this.phid = this.options.phid || 0;

	this.lockbutton = this.options.lockcont ? document.getElementById(this.options.lockcont) : null;
	this.locktext = this.options.lockontxt || null;
	this.unlocktext = this.options.lockofftxt || null;
	this.lockbst = this.options.lockonbst || null;
	this.unlockbst = this.options.lockoffbst || null;
	if(this.lockbutton && this.locktext) this.lockbutton.innerHTML = this.locktext;

	this.ns6 = document.getElementById && !document.all;
	this.ie = document.all;

	this.eventMouseDown = this.newselection.bindAsEventListener(this);
	this.eventMouseUp   = this.endselection.bindAsEventListener(this);
	this.eventMouseDown2 = this.startmoveselection.bindAsEventListener(this);
	this.eventOnClick = this.updateselection.bindAsEventListener(this);

	this.eventMouseDownTL = this.startresizeselectionTL.bindAsEventListener(this);
	this.eventMouseDownTM = this.startresizeselectionTM.bindAsEventListener(this);
	this.eventMouseDownTR = this.startresizeselectionTR.bindAsEventListener(this);
	this.eventMouseDownML = this.startresizeselectionML.bindAsEventListener(this);
	this.eventMouseDownMR = this.startresizeselectionMR.bindAsEventListener(this);
	this.eventMouseDownBL = this.startresizeselectionBL.bindAsEventListener(this);
	this.eventMouseDownBM = this.startresizeselectionBM.bindAsEventListener(this);
	this.eventMouseDownBR = this.startresizeselectionBR.bindAsEventListener(this);

	this.eventKeyDown = this.mykeydown.bindAsEventListener(this);
	this.eventKeyUp = this.mykeyup.bindAsEventListener(this);

	if(this.imgw > 0) {
		this.initselection();
		this.selectionimage =  document.getElementById(this.selectionimageid);
		Event.observe(this.selectionimage, "mousedown", this.eventMouseDown2);

		this.tl =  document.getElementById(this.idtl);
		Event.observe(this.tl, "mousedown", this.eventMouseDownTL);
		this.tm =  document.getElementById(this.idtm);
		Event.observe(this.tm, "mousedown", this.eventMouseDownTM);
		this.tr =  document.getElementById(this.idtr);
		Event.observe(this.tr, "mousedown", this.eventMouseDownTR);
		this.ml =  document.getElementById(this.idml);
		Event.observe(this.ml, "mousedown", this.eventMouseDownML);
		this.mr =  document.getElementById(this.idmr);
		Event.observe(this.mr, "mousedown", this.eventMouseDownMR);
		this.bl =  document.getElementById(this.idbl);
		Event.observe(this.bl, "mousedown", this.eventMouseDownBL);
		this.bm =  document.getElementById(this.idbm);
		Event.observe(this.bm, "mousedown", this.eventMouseDownBM);
		this.br =  document.getElementById(this.idbr);
		Event.observe(this.br, "mousedown", this.eventMouseDownBR);

		this.init();
		this.initialized = true;

		if(this.options.rx || this.options.rw) {
			this.seloldselection(this.options.rx, this.options.ry, this.options.rw, this.options.rh);
		}
	} else {
		this.eventOnLoad = this.myonload.bindAsEventListener(this);
		Event.observe(document.getElementById(myelementid), "load", this.eventOnLoad);
	}

	Event.observe(this.container, "mousedown", this.eventMouseDown);
	Event.observe(this.container, "mouseup", this.eventMouseUp);
	Event.observe(this.container, "click", this.eventOnClick);

	this.eventMyMouseDown2 = this.clearselection.bindAsEventListener(this);
	Event.observe(this.clearcontainer, "click", this.eventMyMouseDown2);
	this.eventMyMouseDown3 = this.selallselection.bindAsEventListener(this);
	Event.observe(this.selallcontainer, "click", this.eventMyMouseDown3);

	if(this.lockbutton) {
		this.eventMyMouseDown4 = this.lockselection.bindAsEventListener(this);
		Event.observe(this.lockbutton, "click", this.eventMyMouseDown4);
	}

	Event.observe(this.container, "keydown", this.eventKeyDown);
	Event.observe(this.container, "keyup", this.eventKeyUp);

	Event.observe(window, 'unload', Event.unloadCache, false);

	Selections.register(this);
},

myonload: function(event) {
	this.imgw = this.myelement.offsetWidth;
	this.imgh = this.myelement.offsetHeight;

	this.initselection();
	this.selectionimage =  document.getElementById(this.selectionimageid);
	Event.observe(this.selectionimage, "mousedown", this.eventMouseDown2);

	this.tl =  document.getElementById(this.idtl);
	Event.observe(this.tl, "mousedown", this.eventMouseDownTL);
	this.tm =  document.getElementById(this.idtm);
	Event.observe(this.tm, "mousedown", this.eventMouseDownTM);
	this.tr =  document.getElementById(this.idtr);
	Event.observe(this.tr, "mousedown", this.eventMouseDownTR);
	this.ml =  document.getElementById(this.idml);
	Event.observe(this.ml, "mousedown", this.eventMouseDownML);
	this.mr =  document.getElementById(this.idmr);
	Event.observe(this.mr, "mousedown", this.eventMouseDownMR);
	this.bl =  document.getElementById(this.idbl);
	Event.observe(this.bl, "mousedown", this.eventMouseDownBL);
	this.bm =  document.getElementById(this.idbm);
	Event.observe(this.bm, "mousedown", this.eventMouseDownBM);
	this.br =  document.getElementById(this.idbr);
	Event.observe(this.br, "mousedown", this.eventMouseDownBR);

	this.init();
	this.initialized = true;

	if(this.options.rx || this.options.rw) {
		this.seloldselection(this.options.rx, this.options.ry, this.options.rw, this.options.rh);
	}
},

destroy: function() {
	var selecthandler = this;
	Event.stopObserving(this.container, "mousedown", this.eventMouseDown);
	Event.stopObserving(this.container, "mouseup", this.eventMouseUp);
	Event.stopObserving(this.selectionimage, "mousedown", this.eventMouseDown2);
	Event.stopObserving(this.container, "click", this.eventOnClick);

	Event.stopObserving(this.tl, "mousedown", this.eventMouseDownTL);
	Event.stopObserving(this.tm, "mousedown", this.eventMouseDownTM);
	Event.stopObserving(this.tr, "mousedown", this.eventMouseDownTR);
	Event.stopObserving(this.ml, "mousedown", this.eventMouseDownML);
	Event.stopObserving(this.mr, "mousedown", this.eventMouseDownMR);
	Event.stopObserving(this.bl, "mousedown", this.eventMouseDownBL);
	Event.stopObserving(this.bm, "mousedown", this.eventMouseDownBM);
	Event.stopObserving(this.br, "mousedown", this.eventMouseDownBR);

	Event.stopObserving(this.container, "keydown", this.eventKeyDown);
	Event.stopObserving(this.container, "keyup", this.eventKeyUp);

	Event.stopObserving(this.clearcontainer, "click", this.eventMyMouseDown2);
	Event.stopObserving(this.selallcontainer, "click", this.eventMyMouseDown3);
	if(this.lockbutton) Event.stopObserving(this.lockbutton, "click", this.eventMyMouseDown4);

	Event.stopObserving(window, "unload", Event.unloadCache);
	if(this.eventOnLoad) {
		Event.stopObserving(window, "load", this.eventOnLoad);
	}
	Selections.unregister(this);
},

iebody: function () {
	return (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body
},

getcoordX: function(event) {
	var clientX;
	if(event.pseudo) {
		clientX = event.clientX;
	} else {
		clientX = (this.ns6) ? event.pageX : event.clientX + this.iebody().scrollLeft;
	}
	return clientX;
},

getcoordY: function(event) {
	var clientY;
	if(event.pseudo) {
		clientY = event.clientY;
	} else {
		clientY = (this.ns6) ? event.pageY : event.clientY + this.iebody().scrollTop;
	}
	return clientY;
},

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

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

	// Prevent caching issues: Re-do the mask in case the image dimensions have changed
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		var themask = document.getElementById(this.maskid);
		if(!themask) {
			// panic --- what happended?? not intialized???
			this.initselection();
			this.selectionimage =  document.getElementById(this.selectionimageid);
			Event.observe(this.selectionimage, "mousedown", this.eventMouseDown2);
			this.tl =  document.getElementById(this.idtl);
			Event.observe(this.tl, "mousedown", this.eventMouseDownTL);
			this.tm =  document.getElementById(this.idtm);
			Event.observe(this.tm, "mousedown", this.eventMouseDownTM);
			this.tr =  document.getElementById(this.idtr);
			Event.observe(this.tr, "mousedown", this.eventMouseDownTR);
			this.ml =  document.getElementById(this.idml);
			Event.observe(this.ml, "mousedown", this.eventMouseDownML);
			this.mr =  document.getElementById(this.idmr);
			Event.observe(this.mr, "mousedown", this.eventMouseDownMR);
			this.bl =  document.getElementById(this.idbl);
			Event.observe(this.bl, "mousedown", this.eventMouseDownBL);
			this.bm =  document.getElementById(this.idbm);
			Event.observe(this.bm, "mousedown", this.eventMouseDownBM);
			this.br =  document.getElementById(this.idbr);
			Event.observe(this.br, "mousedown", this.eventMouseDownBR);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.imgw + "px";
		themask.style.height = this.imgh + "px";
		this.selectionimage.style.width = this.imgw + "px";
		this.selectionimage.style.height = this.imgh + "px";
	}

	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	if(this.selection.getvisible() != "visible") {
		var x;
		var y;
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);
		if(!document.all && typeof(event.layerX) != 'undefined') {
			x = event.layerX;
			y = event.layerY;
		} else {
			x = event.offsetX;
			y = event.offsetY;
		}
		this.oldabscoords.x = clientX;
		this.oldabscoords.y = clientY;
		this.newabscoords = {x: clientX, y: clientY};
		this.layercoords  = {x: x + 1, y: y + 1};
		this.selection.draw(x, y, 1, 1);
		this.selection.track = true;
	}

	Selections.activate(this);

	return false;
},

endselection: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	if(event.stopPropagation) {
		event.stopPropagation();
	} else {
		event.cancelBubble = true;
	}
	var themask = document.getElementById(this.maskid);

	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;

	if(!document.all) {
		targetid = event.target.id;
	} else {
		targetid = event.srcElement.id;
	}

	if(this.selection.track) {
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);
		if(this.newabscoords.x == clientX && this.newabscoords.y == clientY) {
			this.init();
		} else {
			this.resizeselection(event);
			themask.style.visibility = "visible";
			Element.show(this.maskid);
			this.selection.setcursor("move");	//default

			this.oldabscoords.x = clientX;
			this.oldabscoords.y = clientY;
		}
	} else if(this.selection.resize) {

	} else if(targetid == this.maskid || targetid == this.myelementid) {
		this.init();
		this.selection.setneswcursor(this.selection.getlockaspect());
		if(a=document.getElementById('post_selunlocktrigger')) {
			if(typeof a.onchange == 'function'){a.onchange();}
		}
	}

	this.selection.drag = false;
	this.selection.track = false;
	this.selection.resize = false;
	themask = null;

	this.updatefinished();

	Selections.deactivate(this);

	return false;
},

dohandleselection: function(event) {
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	if(this.selection.track || this.selection.drag || this.selection.resize) {
		if(event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
		this.pevent.clientX = clientX;
		this.pevent.clientY = clientY;
		this.pevent.pseudo = true;
		if(this.selection.track) {
			this.resizeselection(this.pevent);
		} else if(this.selection.drag) {
			this.dragselection(this.pevent);
		} else if(this.selection.resize) {
			this.resizeselectionafter(this.pevent);
		}
	}
	this.oldabscoords.x = clientX;
	this.oldabscoords.y = clientY;

	return false;
},

startmoveselection: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	this.startcoords = {x: clientX, y: clientY};
	this.startleft = this.selection.getLeft();
	this.starttop = this.selection.getTop();
	this.selection.drag = true;
	return false;
},

startresizeselectionTL: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startleft = this.selection.getLeft();
	this.starttop = this.selection.getTop();
	this.selection.resizepoint = 1;
	this.selection.resize = true;
	return false;
},
startresizeselectionTM: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.starttop = this.selection.getTop();	/* ok, need only top (shift ignored) */
	this.selection.resizepoint = 2;
	this.selection.resize = true;
	return false;
},
startresizeselectionTR: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startleft = this.selection.getLeft();
	this.starttop = this.selection.getTop();
	this.startwidth = this.selection.getWidth();
	this.startheight = this.selection.getHeight();
	this.selection.resizepoint = 3;
	this.selection.resize = true;
	return false;
},
startresizeselectionML: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startleft = this.selection.getLeft();	/* ok, need only left (shift ignored) */
	this.selection.resizepoint = 4;
	this.selection.resize = true;
	return false;
},
startresizeselectionMR: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startwidth = this.selection.getWidth();	/* OK, need only width (shift ignored) */
	this.selection.resizepoint = 5;
	this.selection.resize = true;
	return false;
},
startresizeselectionBL: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startleft = this.selection.getLeft();
	this.starttop = this.selection.getTop();
	this.startwidth = this.selection.getWidth();
	this.startheight = this.selection.getHeight();
	this.selection.resizepoint = 6;
	this.selection.resize = true;
	return false;
},
startresizeselectionBM: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startheight = this.selection.getHeight();	/* ok, need only height (shift ignored) */
	this.selection.resizepoint = 7;
	this.selection.resize = true;
	return false;
},
startresizeselectionBR: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	this.shiftkey = false;
	this.ctrlkey = false;
	if(event.shiftKey) this.shiftkey = event.shiftKey;
	if(event.ctrlKey) this.ctrlkey = event.ctrlKey;
	this.startcoords = {x: this.getcoordX(event), y: this.getcoordY(event)};
	this.startleft = this.selection.getLeft();
	this.starttop = this.selection.getTop();
	this.startwidth = this.selection.getWidth();
	this.startheight = this.selection.getHeight();
	this.selection.resizepoint = 8;
	this.selection.resize = true;
	return false;
},

mykeypress: function(event) {
	this.shiftkey = event.shiftKey;
	this.ctrlkey = event.ctrlKey;
	if(this.selection.track || this.selection.drag || this.selection.resize) {
		this.pevent.preventDefault = function() {};
		this.pevent.shiftKey = event.shiftKey;
		this.pevent.ctrlKey = event.ctrlKey;
		this.pevent.clientX = this.oldabscoords.x;
		this.pevent.clientY = this.oldabscoords.y;
		this.pevent.pseudo = true;
	}
	if(this.selection.track) {
		this.resizeselection(this.pevent);
	} else if(this.selection.drag) {
		this.dohandleselection(this.pevent);
	} else if(this.selection.resize) {
		this.resizeselectionafter(this.pevent);
	}
},

mykeydown: function(event) {
	if(!this.ctrlkey && event.ctrlKey || !this.shiftkey && event.shiftKey) {
		this.mykeypress(event);
	}
},

mykeyup: function(event){
	if(this.ctrlkey && !event.ctrlKey || this.shiftkey && !event.shiftKey) {
		this.mykeypress(event);
	}
},

dragselection: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	var left = this.startleft + clientX - this.startcoords.x;
	var top = this.starttop + clientY - this.startcoords.y;
	var width = this.selection.getWidth();
	var height = this.selection.getHeight();

	var minleft = left;
	if(minleft < 0 || minleft <= this.snap && !this.ctrlkey) left = 0;
	var mintop = top;
	if(mintop < 0 || mintop <= this.snap && !this.ctrlkey) top = 0;
	var maxright = this.imgw - width - left;
	if(maxright < 0 || maxright <= this.snap && !this.ctrlkey) left += maxright;
	var maxbottom = this.imgh - height - top;
	if(maxbottom < 0 || maxbottom <= this.snap && !this.ctrlkey) top += maxbottom;

	this.selection.dragto(left, top);
	//this.updatefinished();
},

resizeselection: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	var left = this.layercoords.x + this.curroffsx;
	var top = this.layercoords.y + this.curroffsy;
	var width = Math.abs(clientX - (this.newabscoords.x + this.curroffsx));
	var height = Math.abs(clientY - (this.newabscoords.y + this.curroffsy));

	var reverseh = (clientX - (this.newabscoords.x + this.curroffsx) >= 0) ? false : true;
	if(reverseh) left -= width;
	var minleft = left;
	if(minleft < 0 || minleft <= this.snap && !this.ctrlkey) {
		width += minleft;
		left = 0;
	}
	var maxright = this.imgw - width - left;
	if(maxright < 0 || maxright <= this.snap && !this.ctrlkey) {
		width += maxright;
	}

	var reversev = (clientY - (this.newabscoords.y + this.curroffsy) >= 0) ? false : true;
	if(reversev) top -= height;
	var mintop = top;
	if(mintop < 0 || mintop <= this.snap && !this.ctrlkey) {
		height += mintop;
		top = 0;
	}
	var maxbottom = this.imgh - height - top;
	if(maxbottom < 0 || maxbottom <= this.snap && !this.ctrlkey) {
		height += maxbottom;
	}

	/* no need to handle aspectlocked here, this is for creating a new selection and there is no aspect yet */
	if(this.shiftkey) {
		if(width > height) {
			if(reverseh) left += width - height;
			width = height;
		}
		if(height > width) {
			if(reversev) top += height - width;
			height = width;
		}
	}

	this.selection.draw(left, top, width, height);
},

resizeselectionafter: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);

	var oldl = this.selection.getLeft();
	var oldt = this.selection.getTop();
	var oldw = this.selection.getWidth();
	var oldh = this.selection.getHeight();

	if(this.selection.aspectratiox <= 0) {
		this.selection.aspectratiox = oldw;
		this.selection.aspectratioy = oldh;
	}
	var as = this.selection.aspectratiox / this.selection.aspectratioy;

	var left = oldl;
	var top = oldt;
	var width = oldw;
	var height = oldh;

	var doresize = true;

	/* NW, W, SW: left edge */
	if (this.selection.resizepoint == 1 || this.selection.resizepoint == 4 || this.selection.resizepoint == 6) {
		left = this.startleft + clientX - this.startcoords.x;
		width = oldw + (oldl - left);
		if (width <= 1) {
			left = (oldl + oldw) - 2;
			width = oldw + (oldl - left);
		}
		if(left < 0 || left <= this.snap && !this.ctrlkey) {
			width += left;
			left = 0;
		}
	}

	/* NE, E, SE: right edge */
	if (this.selection.resizepoint == 3 || this.selection.resizepoint == 5 || this.selection.resizepoint == 8) {
		width = this.startwidth + (clientX - this.startcoords.x);
		if (width <= 1) {
			width = 2;
		}
		var maxright = this.imgw - width - left;
		if(maxright < 0 || maxright <= this.snap && !this.ctrlkey) {
			width += maxright;
		}
	}

	/* NW, N, NE: top edge */
	if (this.selection.resizepoint == 1 || this.selection.resizepoint == 2 || this.selection.resizepoint == 3) {
		top = this.starttop + clientY - this.startcoords.y;
		height = oldh + (oldt - top);
		if(height <= 1) {
			top = (oldt + oldh) - 2;
			height = oldh + (oldt - top);
		}
		if(top < 0 || top <= this.snap && !this.ctrlkey) {
			height += top;
			top = 0;
		}
	}

	/* SW, S, SE: bottom edge */
	if (this.selection.resizepoint == 6 || this.selection.resizepoint == 7 || this.selection.resizepoint == 8) {
		height = this.startheight + (clientY - this.startcoords.y);
		if (height <= 1) {
			height = 2;
		}
		var maxbottom = this.imgh - height - top;
		if(maxbottom < 0 || maxbottom <= this.snap && !this.ctrlkey) {
			height += maxbottom;
		}
	}

	if(this.selection.getlockaspect() > 0) {
		if (this.selection.resizepoint == 8) {
			if(width > Math.round(height * as)) width = Math.round(height * as);
			if(Math.round(height * as) > width) height = Math.round(width / as);
		} else if (this.selection.resizepoint == 3) {
			if(width > Math.round(height * as)) width = Math.round(height * as);
			if(Math.round(height * as) > width) {
				top += (height - Math.round(width / as));
				height = Math.round(width / as);
			}
		} else if (this.selection.resizepoint == 1) {
			if(width > Math.round(height * as)) {
				left += (width - Math.round(height * as));
				width = Math.round(height * as);
			}
			if(Math.round(height * as) > width) {
				top += (height - Math.round(width / as));
				height = Math.round(width / as);
			}
		} else if (this.selection.resizepoint == 6) {
			if(width > Math.round(height * as)) {
				left += (width - Math.round(height * as));
				width = Math.round(height * as);
			}
			if(Math.round(height * as) > width) height = Math.round(width / as);
		//} else if (this.selection.resizepoint == 2) {  /* not nice due to rounding errors */
		//	//top += (height - Math.round(width / as));
		//	//height = Math.round(width / as);
		//	var ow = width; width = Math.round(height * as);
		//	left += Math.round((ow - (height * as)) / 2);
		//	if(left < 0 || left + width > this.imgw || width <= 1) doresize = false;
		} else {
			doresize = false;
		}
	} else if(this.shiftkey) {
		this.selection.aspectratiox = 0;
		if (this.selection.resizepoint == 8) {
			if(width > height) width = height;
			if(height > width) height = width;
		} else if (this.selection.resizepoint == 3) {
			if(width > height) width = height;
			if(height > width) {
				top += (height - width);
				height = width;
			}
		} else if (this.selection.resizepoint == 1) {
			if(width > height) {
				left += (width - height);
				width = height;
			}
			if(height > width) {
				top += (height - width);
				height = width;
			}
		} else if (this.selection.resizepoint == 6) {
			if(width > height) {
				left += (width - height);
				width = height;
			}
			if(height > width) height = width;
		}
	} else {
		this.selection.aspectratiox = 0;
	}

	if(doresize) this.selection.draw(left, top, width, height);
},

initselection: function() {
	this.selection = {
		left:		undefined,
		top:		undefined,
		width: 		undefined,
		height:		undefined,
		idLeft: 	"js_selleft",
		idTop:		"js_seltop",
		idRight:	"js_selright",
		idBottom:	"js_selbottom",
		tl:		undefined,
		tm:		undefined,
		tr:		undefined,
		ml:		undefined,
		mr:		undefined,
		bl:		undefined,
		bm:		undefined,
		br:		undefined,
		visible:	false,
		myparent:	this
	};

	var left = document.createElement("div");
	var right = document.createElement("div");
	var top = document.createElement("div");
	var bottom = document.createElement("div");

	var tl = document.createElement("div");
	var tm = document.createElement("div");
	var tr = document.createElement("div");
	var ml = document.createElement("div");
	var mr = document.createElement("div");
	var bl = document.createElement("div");
	var bm = document.createElement("div");
	var br = document.createElement("div");

	left.className = right.className = "selver";
	top.className = bottom.className = "selhor";

	tl.className = "selblktl";
	tm.className = "selblktm";
	tr.className = "selblktr";
	ml.className = "selblkml";
	mr.className = "selblkmr";
	bl.className = "selblkbl";
	bm.className = "selblkbm";
	br.className = "selblkbr";

	tl.style.cursor = "nw-resize";
	tm.style.cursor = "n-resize";
	tr.style.cursor = "ne-resize";
	ml.style.cursor = "w-resize";
	mr.style.cursor = "e-resize";
	bl.style.cursor = "sw-resize";
	bm.style.cursor = "s-resize";
	br.style.cursor = "se-resize";

	left.id = this.selection.idLeft;
	right.id = this.selection.idRight;
	top.id = this.selection.idTop;
	bottom.id = this.selection.idBottom;

	tl.id = this.idtl
	tm.id = this.idtm
	tr.id = this.idtr
	ml.id = this.idml
	mr.id = this.idmr
	bl.id = this.idbl
	bm.id = this.idbm
	br.id = this.idbr

	this.container.appendChild(bottom);
	this.container.appendChild(top);
	this.container.appendChild(left);
	this.container.appendChild(right);

	this.container.appendChild(tl);
	this.container.appendChild(tm);
	this.container.appendChild(tr);
	this.container.appendChild(ml);
	this.container.appendChild(mr);
	this.container.appendChild(bl);
	this.container.appendChild(bm);
	this.container.appendChild(br);

	var mask = document.createElement("div");
	mask.id = this.maskid;
	mask.className = "image_mask";
	mask.style.width = this.imgw + "px";
	mask.style.height = this.imgh + "px";
	this.container.appendChild(mask);

	var image = document.createElement("img");
	image.id = this.selectionimageid;
	image.className = "image_selection";
	image.src = this.imgsrc;
	image.style.width = this.imgw + "px";
	image.style.height = this.imgh + "px";
	this.container.appendChild(image);

	this.selection.reset = function() {
		this.left = this.top = this.width = this.height = undefined;
		this.setvisible("hidden");
		this.setcursor("crosshair");
		this.track = this.drag = this.resize = this.aspectlocked = false;
		if(this.myparent.lockbutton) {
			if(this.myparent.locktext) this.myparent.lockbutton.innerHTML = this.myparent.locktext;
			if(this.myparent.lockbst) this.myparent.lockbutton.style.border = this.myparent.lockbst;
		}
		this.aspectratiox = 0;	// clear aspect ratio
	};

	this.selection.draw = function(left, top, width, height) {
		if(width == 0) width = 1;
		if(height == 0) height = 1;
		this.left = left;
		this.top = top;
		this.width = width;
		this.height = height;

		left = Math.round(left);
		top = Math.round(top);
		width = Math.round(width);
		height = Math.round(height);

		if (left > this.myparent.imgw - 1) left = this.myparent.imgw - 1;
		if (top > this.myparent.imgh - 1)  top = this.myparent.imgh - 1;
		if (left + width > this.myparent.imgw) width = this.myparent.imgw - left;
		if (top + height > this.myparent.imgh) height = this.myparent.imgh - top;

		var dleft = document.getElementById(this.idLeft);
		var dright = document.getElementById(this.idRight);
		var dtop = document.getElementById(this.idTop);
		var dbottom = document.getElementById(this.idBottom);

		dleft.style.left = dtop.style.left = dbottom.style.left = left + "px";
		dright.style.left = (left + width - 1) + "px";

		dleft.style.top = dright.style.top = dtop.style.top = top + "px";
		dbottom.style.top = (top + height - 1) + "px";

		dleft.style.height = dright.style.height = height + "px";
		dtop.style.width = dbottom.style.width = width + "px";

		var clip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";
		this.myparent.selectionimage.style.clip = clip;

		this.setvisible("visible");

		dleft = dtop = dright = dbottom = null;

		blkw = blkh = 6;

		var tl = document.getElementById(this.myparent.idtl);
		var tm = document.getElementById(this.myparent.idtm);
		var tr = document.getElementById(this.myparent.idtr);
		var ml = document.getElementById(this.myparent.idml);
		var mr = document.getElementById(this.myparent.idmr);
		var bl = document.getElementById(this.myparent.idbl);
		var bm = document.getElementById(this.myparent.idbm);
		var br = document.getElementById(this.myparent.idbr);

		if (width >= 64 && height >= 64) {

			if (tl.className != "selblktl") {
				tl.className = "selblktl";
				tm.className = "selblktm";
				tr.className = "selblktr";
				ml.className = "selblkml";
				mr.className = "selblkmr";
				bl.className = "selblkbl";
				bm.className = "selblkbm";
				br.className = "selblkbr";
			}

			tl.style.left = ml.style.left = bl.style.left = left + "px";
			tm.style.left = bm.style.left = (left + (width / 2) - (blkw / 2) - 1) + "px";
			tr.style.left = mr.style.left = br.style.left = (left + width - blkw - 1) + "px";

			tl.style.top = tm.style.top = tr.style.top = top + "px";
			ml.style.top = mr.style.top = (top + (height / 2) - (blkh / 2)) + "px";
			bl.style.top = bm.style.top = br.style.top = (top + height - blkh - 1) + "px";

			tl.style.width = tm.style.width = tr.style.width = blkw + "px";
			ml.style.width = mr.style.width = blkw + "px";
			bl.style.width = bm.style.width = br.style.width = blkw + "px";

			tl.style.height = tm.style.height = tr.style.height = blkh + "px";
			ml.style.height = mr.style.height = blkh + "px";
			bl.style.height = bm.style.height = br.style.height = blkh + "px";

		} else {

			if (tl.className != "selblkbr") {
				tl.className = "selblkbr";
				tm.className = "selblkbm";
				tr.className = "selblkbl";
				ml.className = "selblkmr";
				mr.className = "selblkml";
				bl.className = "selblktr";
				bm.className = "selblktm";
				br.className = "selblktl";
			}

			var inv = this.myparent.scc ? ((this.myparent.scc.style.overflow == "auto") ? true : false) : false;

			tl.style.width = tm.style.width = tr.style.width = blkw + "px";
			bl.style.width = bm.style.width = br.style.width = blkw + "px";

			tl.style.height = tr.style.height = blkh + "px";
			ml.style.height = mr.style.height = blkh + "px";
			bl.style.height = br.style.height = blkh + "px";

			var temp = left - blkw - 1;
			if(inv && temp < 0) {
				tl.style.left = bl.style.left = "0px";
				ml.style.width = "1px";
				ml.style.left = left + "px";
			} else {
				tl.style.left = bl.style.left = ml.style.left = temp + "px";
				ml.style.width = blkw + "px";
			}

			tm.style.left = bm.style.left = (left + (width / 2) - (blkw / 2) - 1) + "px";

			temp = left + width;
			if(inv && temp + blkw >= this.myparent.imgw) {
				tr.style.left = br.style.left = (this.myparent.imgw - blkw - 1) + "px";
				mr.style.width = "1px";
				mr.style.left = (left + width - 2) + "px";
			} else {
				tr.style.left = br.style.left = mr.style.left = temp + "px";
				mr.style.width = blkw + "px";
			}

			temp = (top - blkh - 1);
			if(inv && temp < 0) {
				tl.style.top = tr.style.top = "0px";
				tm.style.height = "1px";
				tm.style.top = top + "px";
			} else {
				tl.style.top = tr.style.top = tm.style.top = temp + "px";
				tm.style.height = blkh + "px";
			}

			ml.style.top = mr.style.top = (top + (height / 2) - (blkh / 2)) + "px";

			temp = top + height;
			if(inv && temp + blkh >= this.myparent.imgh){
				bl.style.top = br.style.top = (this.myparent.imgh - blkh - 1) + "px";
				bm.style.height = "1px";
				bm.style.top = (top + height - 2) + "px";
			} else {
				bl.style.top = br.style.top = bm.style.top = temp + "px";
				bm.style.height = blkh + "px";
			}
		}

		tl = tm = tr = ml = mr = bl = bm = br = null;
	};

	this.selection.dragto = function(left, top) {
		this.left = left;
		this.top = top;
		var width = this.getWidth();
		var height = this.getHeight();

		var dl = document.getElementById(this.idLeft);
		var dr = document.getElementById(this.idRight);
		var dt = document.getElementById(this.idTop);
		var db = document.getElementById(this.idBottom);

		dl.style.left = dt.style.left = db.style.left = left + "px";
		dr.style.left = left + width - 1 + "px";

		dl.style.top = dr.style.top = dt.style.top = top + "px";
		db.style.top = top + height - 1 + "px";

		this.myparent.selectionimage.style.clip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";

		dl = dt = dr = db = null;

		var tl = document.getElementById(this.myparent.idtl);
		var tm = document.getElementById(this.myparent.idtm);
		var tr = document.getElementById(this.myparent.idtr);
		var ml = document.getElementById(this.myparent.idml);
		var mr = document.getElementById(this.myparent.idmr);
		var bl = document.getElementById(this.myparent.idbl);
		var bm = document.getElementById(this.myparent.idbm);
		var br = document.getElementById(this.myparent.idbr);

		blkw = blkh = 6;

		if (width >= 64 && height >= 64) {

			tl.style.left = ml.style.left = bl.style.left = left + "px";
			tm.style.left = bm.style.left = (left + (width / 2) - (blkw / 2)) + "px";
			tr.style.left = mr.style.left = br.style.left = (left + width - blkw - 1) + "px";

			tl.style.top = tm.style.top = tr.style.top = top + "px";
			ml.style.top = mr.style.top = (top + (height / 2) - (blkh / 2)) + "px";
			bl.style.top = bm.style.top = br.style.top = (top + height - blkh - 1) + "px";

			tl.style.width = tm.style.width = tr.style.width = blkw + "px";
			ml.style.width = mr.style.width = blkw + "px";
			bl.style.width = bm.style.width = br.style.width = blkw + "px";

			tl.style.height = tm.style.height = tr.style.height = blkh + "px";
			ml.style.height = mr.style.height = blkh + "px";
			bl.style.height = bm.style.height = br.style.height = blkh + "px";

		} else {

			var inv = this.myparent.scc ? ((this.myparent.scc.style.overflow == "auto") ? true : false) : false;

			tl.style.width = tm.style.width = tr.style.width = blkw + "px";
			bl.style.width = bm.style.width = br.style.width = blkw + "px";

			tl.style.height = tr.style.height = blkh + "px";
			ml.style.height = mr.style.height = blkh + "px";
			bl.style.height = br.style.height = blkh + "px";

			var temp = left - blkw - 1;
			if(inv && temp < 0) {
				tl.style.left = bl.style.left = "0px";
				ml.style.width = "1px";
				ml.style.left = left + "px";
			} else {
				tl.style.left = bl.style.left = ml.style.left = temp + "px";
				ml.style.width = blkw + "px";
			}

			tm.style.left = bm.style.left = (left + (width / 2) - (blkw / 2) - 1) + "px";

			temp = left + width;
			if(inv && temp + blkw >= this.myparent.imgw) {
				tr.style.left = br.style.left = (this.myparent.imgw - blkw - 1) + "px";
				mr.style.width = "1px";
				mr.style.left = (left + width - 2) + "px";
			} else {
				tr.style.left = br.style.left = mr.style.left = temp + "px";
				mr.style.width = blkw + "px";
			}

			temp = (top - blkh - 1);
			if(inv && temp < 0) {
				tl.style.top = tr.style.top = "0px";
				tm.style.height = "1px";
				tm.style.top = top + "px";
			} else {
				tl.style.top = tr.style.top = tm.style.top = temp + "px";
				tm.style.height = blkh + "px";
			}

			ml.style.top = mr.style.top = (top + (height / 2) - (blkh / 2)) + "px";

			temp = top + height;
			if(inv && temp + blkh >= this.myparent.imgh){
				bl.style.top = br.style.top = (this.myparent.imgh - blkh - 1) + "px";
				bm.style.height = "1px";
				bm.style.top = (top + height - 2) + "px";
			} else {
				bl.style.top = br.style.top = bm.style.top = temp + "px";
				bm.style.height = blkh + "px";
			}
		}

		tl = tm = tr = ml = mr = bl = bm = br = null;
	};

	this.selection.setLeft = function(left) {
		this.left = left;
	};
	this.selection.getLeft = function() {
		return Math.round(this.left);
	};

	this.selection.setTop = function(top) {
		this.top = top;
	};
	this.selection.getTop = function() {
		return Math.round(this.top);
	};

	this.selection.setWidth = function(width) {
		this.width = width;
	};
	this.selection.getWidth = function() {
		return Math.round(this.width);
	};

	this.selection.setHeight = function(height) {
		this.height = height;
	};
	this.selection.getHeight = function() {
		return Math.round(this.height);
	};

	this.selection.setvisible = function(vis) {
		if (vis == "visible") {
			Element.show(this.idLeft);
			Element.show(this.idTop);
			Element.show(this.idRight);
			Element.show(this.idBottom);
			Element.show(this.myparent.idtl);
			Element.show(this.myparent.idtm);
			Element.show(this.myparent.idtr);
			Element.show(this.myparent.idml);
			Element.show(this.myparent.idmr);
			Element.show(this.myparent.idbl);
			Element.show(this.myparent.idbm);
			Element.show(this.myparent.idbr);
			Element.show(this.myparent.selectionimageid);
		} else {
			Element.hide(this.idLeft);
			Element.hide(this.idTop);
			Element.hide(this.idRight);
			Element.hide(this.idBottom);
			Element.hide(this.myparent.idtl);
			Element.hide(this.myparent.idtm);
			Element.hide(this.myparent.idtr);
			Element.hide(this.myparent.idml);
			Element.hide(this.myparent.idmr);
			Element.hide(this.myparent.idbl);
			Element.hide(this.myparent.idbm);
			Element.hide(this.myparent.idbr);
			Element.hide(this.myparent.selectionimageid);
		}
		document.getElementById(this.idLeft).style.visibility = vis;
		document.getElementById(this.idTop).style.visibility = vis;
		document.getElementById(this.idRight).style.visibility = vis;
		document.getElementById(this.idBottom).style.visibility = vis;
		document.getElementById(this.myparent.idtl).style.visibility = vis;
		document.getElementById(this.myparent.idtm).style.visibility = vis;
		document.getElementById(this.myparent.idtr).style.visibility = vis;
		document.getElementById(this.myparent.idml).style.visibility = vis;
		document.getElementById(this.myparent.idmr).style.visibility = vis;
		document.getElementById(this.myparent.idbl).style.visibility = vis;
		document.getElementById(this.myparent.idbm).style.visibility = vis;
		document.getElementById(this.myparent.idbr).style.visibility = vis;
		document.getElementById(this.myparent.selectionimageid).style.visibility = vis;
		this.visibility = vis;
	};
	this.selection.getvisible = function() {
		return this.visibility;
	};

	this.selection.setcursor = function(cursor) {
		document.getElementById(this.myparent.selectionimageid).style.cursor = cursor;
		document.getElementById(this.idLeft).style.cursor =
			document.getElementById(this.idTop).style.cursor =
			document.getElementById(this.idRight).style.cursor =
			document.getElementById(this.idBottom).style.cursor = (cursor == "crosshair" ? cursor : "default");

	};

	this.selection.setneswcursor = function(lockedcursor) {
		var tm = document.getElementById(this.myparent.idtm);
		if(tm) {
			tm.style.cursor = lockedcursor ? "default" : "n-resize";
			document.getElementById(this.myparent.idml).style.cursor = lockedcursor ? "default" : "w-resize";
			document.getElementById(this.myparent.idmr).style.cursor = lockedcursor ? "default" : "e-resize";
			document.getElementById(this.myparent.idbm).style.cursor = lockedcursor ? "default" : "s-resize";;
		}
	};

	this.selection.zoom = function(fa) {
		if(this.left != undefined) {
			var bu1 = this.getlockaspect();	// need to save our lock status & aspect ratio
			var bu2 = this.aspectratiox;
			var fact = this.myparent.myelement.offsetWidth / this.myparent.imgw;
			this.myparent.seloldselection(this.left * fact, this.top * fact, this.width * fact, this.height * fact);
			this.lockaspect(bu1);		// write back lock status & aspect ratio
			this.aspectratiox = bu2;
		} else if(themask = document.getElementById(this.myparent.maskid)) {
			themask.style.width = this.myparent.selectionimage.style.width = this.myparent.myelement.offsetWidth + "px";
			themask.style.height = this.myparent.selectionimage.style.height = this.myparent.myelement.offsetHeight + "px";
		}
	};

	this.selection.lockaspect = function(loc) {
		this.aspectlocked = (parseInt(loc) == 0) ? false : true;
		this.setneswcursor(this.aspectlocked ? 1 : 0);
		if (this.myparent.lockbutton) {
			if(this.myparent.locktext) {
				this.myparent.lockbutton.innerHTML = this.aspectlocked ? this.myparent.unlocktext : this.myparent.locktext;
			}
			if(this.myparent.lockbst) {
				this.myparent.lockbutton.style.border = this.aspectlocked ? this.myparent.unlockbst : this.myparent.lockbst;
			}
		}
	};

	this.selection.getlockaspect = function() {
		return this.aspectlocked ? 1 : 0;
	};

	this.selection.setmaxwithaspect = function(ax, ay) {
		this.aspectratiox = ax;
		this.aspectratioy = ay;
		if(ax >= ay) {
			nw = this.myparent.imgw;
			nh = nw * ay / ax;
			if (nh > this.myparent.imgh) {
				nh = this.myparent.imgh;
				nw = nh * ax / ay;
			}
		} else {
			nh = this.myparent.imgh;
			nw = nh * ax / ay;
			if (nw > this.myparent.imgw) {
				nw = this.myparent.imgw;
				nh = nw * ay / ax;
			}
		}
		this.myparent.seloldselection((this.myparent.imgw - nw) / 2, (this.myparent.imgh - nh) / 2, nw, nh);
	};
},

init: function() {
	if(themask = document.getElementById(this.maskid)) {
		themask.style.visibility = "hidden";
		Element.hide(this.maskid);
	}
	this.layercoords = this.newabscoords = null;
	this.shiftkey = this.ctrlkey = false;
	if(this.selection) this.selection.reset();
},

clearselection: function(event) {
	this.init();
	this.updatefinished();
	this.selection.setneswcursor(this.selection.getlockaspect());
	if(a=document.getElementById('post_selunlocktrigger')) {
		if(typeof a.onchange == 'function'){a.onchange();}
	}
},

selallselection: function(event) {
	var themask;
	this.init();
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		if(!(themask = document.getElementById(this.maskid))) {
			// panic --- what happended?? not intialized???
			this.initselection();
			this.selectionimage =  document.getElementById(this.selectionimageid);
			Event.observe(this.selectionimage, "mousedown", this.eventMouseDown2);
			this.tl =  document.getElementById(this.idtl);
			Event.observe(this.tl, "mousedown", this.eventMouseDownTL);
			this.tm =  document.getElementById(this.idtm);
			Event.observe(this.tm, "mousedown", this.eventMouseDownTM);
			this.tr =  document.getElementById(this.idtr);
			Event.observe(this.tr, "mousedown", this.eventMouseDownTR);
			this.ml =  document.getElementById(this.idml);
			Event.observe(this.ml, "mousedown", this.eventMouseDownML);
			this.mr =  document.getElementById(this.idmr);
			Event.observe(this.mr, "mousedown", this.eventMouseDownMR);
			this.bl =  document.getElementById(this.idbl);
			Event.observe(this.bl, "mousedown", this.eventMouseDownBL);
			this.bm =  document.getElementById(this.idbm);
			Event.observe(this.bm, "mousedown", this.eventMouseDownBM);
			this.br =  document.getElementById(this.idbr);
			Event.observe(this.br, "mousedown", this.eventMouseDownBR);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.selectionimage.style.width = this.imgw + "px";
		themask.style.height = this.selectionimage.style.height = this.imgh + "px";
	}
	this.selection.draw(0, 0, this.imgw, this.imgh);
	if(themask = document.getElementById(this.maskid)) {
		Element.show(this.maskid);
		themask.style.visibility = "visible";
	}

	this.selection.setcursor("move"); //default

	this.updatefinished();

	this.selection.setneswcursor(this.selection.getlockaspect());
	if(a=document.getElementById('post_selunlocktrigger')) {
		if(typeof a.onchange == 'function'){a.onchange();}
	}
},

seloldselection: function(x, y, w, h) {
	var themask;
	this.init();
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		if(!(themask = document.getElementById(this.maskid))) {
			// panic --- what happended?? not intialized???
			this.initselection();
			this.selectionimage =  document.getElementById(this.selectionimageid);
			Event.observe(this.selectionimage, "mousedown", this.eventMouseDown2);
			this.tl =  document.getElementById(this.idtl);
			Event.observe(this.tl, "mousedown", this.eventMouseDownTL);
			this.tm =  document.getElementById(this.idtm);
			Event.observe(this.tm, "mousedown", this.eventMouseDownTM);
			this.tr =  document.getElementById(this.idtr);
			Event.observe(this.tr, "mousedown", this.eventMouseDownTR);
			this.ml =  document.getElementById(this.idml);
			Event.observe(this.ml, "mousedown", this.eventMouseDownML);
			this.mr =  document.getElementById(this.idmr);
			Event.observe(this.mr, "mousedown", this.eventMouseDownMR);
			this.bl =  document.getElementById(this.idbl);
			Event.observe(this.bl, "mousedown", this.eventMouseDownBL);
			this.bm =  document.getElementById(this.idbm);
			Event.observe(this.bm, "mousedown", this.eventMouseDownBM);
			this.br =  document.getElementById(this.idbr);
			Event.observe(this.br, "mousedown", this.eventMouseDownBR);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.selectionimage.style.width = this.imgw + "px";
		themask.style.height = this.selectionimage.style.height = this.imgh + "px";
	}
	this.selection.draw(x, y, w, h);
	if(themask = document.getElementById(this.maskid)) {
		Element.show(this.maskid);
		themask.style.visibility = "visible";
	}

	this.selection.setcursor("move"); // default

	this.updatefinished();
},

lockselection: function(event) {
	this.selection.lockaspect(this.selection.getlockaspect() ^ 1);
	if(this.selection.getlockaspect() == 0) {
		if(a=document.getElementById('post_selunlocktrigger')) {
			if(typeof a.onchange == 'function'){a.onchange();}
		}
	} else {
		if(a=document.getElementById('post_sellocktrigger')) {
			if(typeof a.onchange == 'function'){a.onchange();}
		}
	}
},

updatefinished: function() {
	if(this.initialized) {
		var l = Math.round(this.selection.left);
		var t = Math.round(this.selection.top);
		var w = Math.round(this.selection.width);
		var h = Math.round(this.selection.height);
		if (l > this.imgw - 1) l = this.imgw - 1;
		if (t > this.imgh - 1) t = this.imgh - 1;
		if (l + w > this.imgw) w = this.imgw - l;
		if (t + h > this.imgh) h = this.imgh - t;
		if(this.setCook) {
			var temp = this.imgw + 'X' + this.imgh + 'X' + l + 'X' + t + 'X' + w + 'X' + h + 'X' + this.phid;
			if(temp.indexOf('undefined') != -1 || temp.indexOf('NaN') != -1) {
				if(document.cookie.indexOf('pselection') != -1) document.cookie="pselection=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT";
			} else {
				document.cookie = "pselection=" + temp + ";path=/";
			}
		}
	 	if (this.onChange) {
			this.onChange(this.imgw + ',' + this.imgh + ',' + l + ',' + t + ',' + w + ',' + h + ',' + this.phid);
		}
		if (this.onChangeJS) {
			this.onChangeJS(this.pwidth,this.pheight,this.imgw,this.imgh,l,t,w,h);
		}
	}
	this.event = null;
}

};





// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007

// Copyright (c) 2005, 2006 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 = {};
Control.Slider = Class.create();

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

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

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

    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;
      if(window.opera) Element.makePositioned(h); // fix Opera
      slider.setValue(parseFloat(
       	(slider.options.sliderValue instanceof Array ? 
          slider.options.sliderValue[i] : slider.options.sliderValue) || 
       	 slider.range.start), i);
      if(!window.opera) Element.makePositioned(h); // fix IE
      Event.observe(h, "mousedown", slider.eventMouseDown);
    });
    
    Event.observe(this.track, "mousedown", this.eventMouseDown);
    Event.observe(document, "mouseup", this.eventMouseUp);
    Event.observe(document, "mousemove", this.eventMouseMove);
    
    this.initialized = true;
  },
  dispose: function() {
    var slider = this;    
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },  
  getNearestValue: function(value){
    if(this.allowedValues){
      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
      if(value <= this.allowedValues.min()) return(this.allowedValues.min());
      
      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if(currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        } 
      });
      return newValue;
    }
    if(value > this.range.end) return this.range.end;
    if(value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if(!this.active) {
      this.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] + this.restrlimit;
      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1] - this.restrlimit;
    }
    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.alignY);
  },  
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if(this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if(this.options.startSpan) 
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if(this.options.endSpan) 
      this.setSpan(this.options.endSpan, 
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if(this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if(Event.isLeftClick(event)) {
      if(!this.disabled){
        this.active = true;
        
        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if(track==this.track) {
          var offsets  = Position.cumulativeOffset(this.track); 
          this.event = event;
          this.setValue(this.translateToValue( 
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
            handle = handle.parentNode;
            
          if(this.handles.indexOf(handle)!=-1) {
            this.activeHandle    = handle;
            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
            this.updateStyles();
            
            var offsets  = Position.cumulativeOffset(this.activeHandle);
            this.offsetX = (pointer[0] - offsets[0]);
            this.offsetY = (pointer[1] - offsets[1]);
          }
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if(this.active) {
      if(!this.dragging) this.dragging = true;
      this.draw(event);
      // fix AppleWebKit rendering
      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = Position.cumulativeOffset(this.track);
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
    if(this.initialized && this.options.onSlide)
      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  },
  endDrag: function(event) {
    if(this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
  },  
  finishDrag: function(event, success) {
    this.active = false;
    this.dragging = false;
    this.updateFinished();
  },
  updateFinished: function() {
    if(this.initialized && this.options.onChange) 
      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
    this.event = null;
  }
}// hor/ver hvslider element
// Copyright (c) 2010 Thomas Winischhofer

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

Control.HVSlider.prototype = {
  initialize: function(handle, track, options) {
    var hvslider = this;
    
    this.handles = [$(handle)];
    
    this.track   = $(track);
    this.options = options || {};

    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.rangeh    = this.options.rangeh || $R(0,1);
    this.rangev    = this.options.rangev || $R(0,1);
    
    this.values    = this.handles.map( function() { return 0 });

    this.restricted = false;

    this.maximumh   = this.options.maximumh || this.rangeh.end;
    this.minimumh   = this.options.minimumh || this.rangeh.start;
    this.maximumv   = this.options.maximumv || this.rangev.end;
    this.minimumv   = this.options.minimumv || this.rangev.start;
    
    this.calch = this.options.calcH;
    this.calcv = this.options.calcV;

    this.alignX = '0';
    this.alignY = '0';
    
    this.trackLengthH = this.maximumOffsetH() - this.minimumOffsetH();
    this.trackLengthV = this.maximumOffsetV() - this.minimumOffsetV();

    this.handleLengthV = (this.handles[0].offsetHeight != 0 ? 
		        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,""))
    this.handleLengthH =  (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();

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

    if(window.opera) Element.makePositioned(this.handles[0]); // fix Opera
    hvslider.setValue(parseFloat((hvslider.options.sliderValueH) || hvslider.rangeh.start), 	
    			parseFloat((hvslider.options.sliderValueV) || hvslider.rangev.start) );
    if(!window.opera) Element.makePositioned(this.handles[0]); // fix IE
    Event.observe(this.handles[0], "mousedown", hvslider.eventMouseDown);
    
    Event.observe(this.track, "mousedown", this.eventMouseDown);
    Event.observe(document, "mouseup", this.eventMouseUp);
    Event.observe(document, "mousemove", this.eventMouseMove);
    
    this.ns6 = document.getElementById && !document.all;
    this.ie = document.all;
    this.oxp=-20;
    this.oyp=25;
    this.enabletip=false;
    if (this.ie || this.ns6) {
	this.tipobjh = document.all ? document.all["hvsliddivh"] : document.getElementById ? document.getElementById("hvsliddivh") : "";
	this.tipobjv = document.all ? document.all["hvsliddivv"] : document.getElementById ? document.getElementById("hvsliddivv") : "";
    }
    
    this.initialized = true;
  },
  dispose: function() {
    var hvslider = 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", hvslider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },  
  getNearestValueH: function(value){
    if(value > this.rangeh.end) return this.rangeh.end;
    if(value < this.rangeh.start) return this.rangeh.start;
    return value;
  },
  getNearestValueV: function(value){
    if(value > this.rangev.end) return this.rangev.end;
    if(value < this.rangev.start) return this.rangev.start;
    return value;
  },
  setValue: function(hvsliderValueH, hvsliderValueV){
    if(!this.active) {
      this.activeHandleIdx = 0;
      this.activeHandle    = this.handles[this.activeHandleIdx];
      this.updateStyles();
    }
    handleIdx = this.activeHandleIdx || 0;
    
    hvsliderValue = this.getNearestValueH(hvsliderValueH);
    this.values[0] = hvsliderValue;
    this.handles[0].style['left'] = this.translateToPxH(hvsliderValue);
    hvsliderValue = this.getNearestValueV(hvsliderValueV);
    this.values[1] = hvsliderValue;
    this.handles[0].style['top'] = this.translateToPxV(hvsliderValue);
    
    if(!this.dragging || !this.event) this.updateFinished();
  },
  translateToPxH: function(value) {
    return Math.round(
      ((this.trackLengthH-this.handleLengthH)/(this.rangeh.end-this.rangeh.start)) * 
      (value - this.rangeh.start)) + "px";
  },
  translateToPxV: function(value) {
    return Math.round(
      ((this.trackLengthV-this.handleLengthV)/(this.rangev.end-this.rangev.start)) * 
      (value - this.rangev.start)) + "px";
  },
  translateToValueH: function(offset) {
    return ((offset/(this.trackLengthH-this.handleLengthH) * 
      (this.rangeh.end-this.rangeh.start)) + this.rangeh.start);
  },
  translateToValueV: function(offset) {
    return ((offset/(this.trackLengthV-this.handleLengthV) * 
      (this.rangev.end-this.rangev.start)) + this.rangev.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K); 
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffsetV: function(){
    return(this.alignY);
  },
  minimumOffsetH: function(){
    return(this.alignX);
  },
  maximumOffsetV: function(){
    return(this.track.offsetHeight != 0 ? this.track.offsetHeight : this.track.style.height.replace(/px$/,"")) - this.alignY;
  },  
  maximumOffsetH: function(){
    return(this.track.offsetWidth != 0 ? this.track.offsetWidth : this.track.style.width.replace(/px$/,"")) - this.alignY;
  },  
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if(Event.isLeftClick(event)) {
      if(!this.disabled){
        this.active = true;
        
        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if(track==this.track) {
          var offsets  = Position.cumulativeOffset(this.track); 
          this.event = event;
          this.setValue(this.translateToValueH(pointer[0]-offsets[0]-(this.handleLengthH/2)),
          		this.translateToValueV(pointer[1]-offsets[1]-(this.handleLengthV/2)));
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
            handle = handle.parentNode;
            
          if(this.handles.indexOf(handle)!=-1) {
            this.activeHandle    = handle;
            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
            this.updateStyles();
            
            var offsets  = Position.cumulativeOffset(this.activeHandle);
            this.offsetX = (pointer[0] - offsets[0]);
            this.offsetY = (pointer[1] - offsets[1]);
            this.activeHandle.style.cursor = "move";
          }
        }
        this.showcotag(this.values[0],this.values[1]);
        this.positiontag(event);
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if(this.active) {
      if(!this.dragging) this.dragging = true;
      this.draw(event);
      // fix AppleWebKit rendering
      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
      this.showcotag(this.values[0],this.values[1]);
      this.positiontag(event);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = Position.cumulativeOffset(this.track);
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValueH(pointer[0]), this.translateToValueV(pointer[1]));
    this.showcotag(this.values[0],this.values[1]);
    this.positiontag(event);
    if(this.initialized && this.options.onSlide)
      this.options.onSlide(this.values, this);
  },
  endDrag: function(event) {
    if(this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
    this.activeHandle.style.cursor = "pointer";
    this.hidecotag();
  },  
  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, this);
    this.event = null;
    this.hidecotag();
  },
  getScrollingPosition: function() {
	var position=[0,0];
	if (typeof window.pageYOffset != 'undefined') {
		position = [window.pageXOffset,window.pageYOffset];
	} else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0) {
		position = [document.documentElement.scrollLeft,document.documentElement.scrollTop];
	} else if (typeof document.body.scrollTop != 'undefined') {
		position = [document.body.scrollLeft,document.body.scrollTop];
	}
	return position;
  },
  getViewportSize: function() {
	var size=[0,0];
	if (typeof window.innerWidth != 'undefined') {
		size = [window.innerWidth,window.innerHeight];
	} else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
		size = [document.documentElement.clientWidth,document.documentElement.clientHeight];
	} else {
		size = [document.getElementsByTagName('body')[0].clientWidth,document.getElementsByTagName('body')[0].clientHeight];
	}
	return size;
  },
  positiontag: function(e) {
	if (this.enabletip) {
		var viewportSize = getViewportSize(); 
		var scrollPos = getScrollingPosition();
		var curPos = [0, 0];
		curPos[0] = (this.ns6) ? e.pageX : event.clientX + scrollPos[0];
		curPos[1] = (this.ns6) ? e.pageY : event.clientY + scrollPos[1];
		
		var oxp = 20
		var oyp = -5

		this.tipobjh.innerHTML = this.tipobjh.innerHTML;  // This for some stupid reason works around a bug in Opera

		var leftedge = (oxp < 0) ? oxp*(-1) : -1000;
		if (curPos[0] - scrollPos[0] + oxp + this.tipobjh.offsetWidth > viewportSize[0] - 20)
 			this.tipobjh.style.left = scrollPos[0] + viewportSize[0] - 20 - this.tipobjh.offsetWidth + "px";
		else if (curPos[0] < leftedge)
 			this.tipobjh.style.left = "5px";
		else
 			this.tipobjh.style.left = curPos[0] + oxp + "px";
		if (curPos[1] - scrollPos[1] + oyp + this.tipobjh.offsetHeight > viewportSize[1] - 20)
 			this.tipobjh.style.top = curPos[1] - this.tipobjh.offsetHeight - oyp+"px";
		else
 			this.tipobjh.style.top = curPos[1] + oyp+"px";
 			
 		oxp = -5
		oyp = 20

		var leftedge = (oxp < 0) ? oxp*(-1) : -1000;
		if (curPos[0] - scrollPos[0] + oxp + this.tipobjv.offsetWidth > viewportSize[0] - 20)
 			this.tipobjv.style.left = scrollPos[0] + viewportSize[0] - 20 - this.tipobjv.offsetWidth + "px";
		else if (curPos[0] < leftedge)
 			this.tipobjv.style.left = "5px";
		else
 			this.tipobjv.style.left = curPos[0]+oxp+"px";
		if (curPos[1] - scrollPos[1] + oyp + this.tipobjv.offsetHeight > viewportSize[1] - 20)
 			this.tipobjv.style.top = curPos[1] - this.tipobjv.offsetHeight - oyp+"px";
		else
 			this.tipobjv.style.top = curPos[1] + oyp+"px";

		this.tipobjh.style.visibility = this.tipobjv.style.visibility = "visible";
	}
  },
  showcotag: function(v1,v2) {
	if (this.ns6 || this.ie) {
		if(this.calch) v1 = this.calch(v1);
		if(this.calcv) v2 = this.calcv(v2);
		this.tipobjh.innerHTML = (v1 == 0 ? "" : ((v1 < 0) ? "←" : "→")) + String(Math.abs(v1));
		this.tipobjv.innerHTML = (v2 == 0 ? "" : ((v2 < 0) ? "↑" : "↓")) + String(Math.abs(v2));
		this.enabletip = true;
	}
  },
  hidecotag: function() {
	if (this.ns6 || this.ie) {
		this.enabletip = false;
		this.tipobjh.style.visibility = this.tipobjv.style.visibility = "hidden";
		this.tipobjh.style.left = this.tipobjv.style.left= "-1000px";
		this.tipobjh.style.backgroundColor = this.tipobjv.style.backgroundColor = '';
		this.tipobjh.style.width = this.tipobjv.style.width = '';
	}
  }
}/* Visual cropper
   (C) 2010 Thomas Winischhofer, Vienna, Austria
*/

var PShrinks = {
	shrnks: [],
	observer: [],

	register: function(pshrinkhandler) {
		if(this.shrnks.length == 0) {
			this.eventMouseUp   = this.endpshrink.bindAsEventListener(this);
			this.eventMouseMove = this.dohandlepshrink.bindAsEventListener(this);
			Event.observe(document, "mouseup", this.eventMouseUp);
			Event.observe(document, "mousemove", this.eventMouseMove);
		}
		this.shrnks.push(pshrinkhandler);
	},

	unregister: function(pshrinkhandler) {
		this.shrnks = this.shrnks.reject(function(s) { return s==pshrinkhandler });
		if(this.shrnks.length == 0) {
			Event.stopObserving(document, "mouseup", this.eventMouseUp);
			Event.stopObserving(document, "mousemove", this.eventMouseMove);
		}
	},

	activate: function(pshrinkhandler) {
		this.activeShrinkHandler = pshrinkhandler;
	},

	deactivate: function() {
		this.activeShrinkHandler = null;
	},

	endpshrink: function(event) {
		if(!this.activeShrinkHandler) return;
		this._lastPointer = null;
		this.activeShrinkHandler.endpshrink(event);
		this.activeShrinkHandler = null;
	},

	dohandlepshrink: function(event) {
		if(!this.activeShrinkHandler) return;
		var pointer = [Event.pointerX(event), Event.pointerY(event)];
		// 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.activeShrinkHandler.dohandlepshrink(event);
	}
}

var PShrinkHandlers = Class.create();

PShrinkHandlers.prototype = {

initialize: function(myelementid, containerid, options) {
	var pshrinkhandler = this;

	if(this.initialized) {
		this.dispose();
	}

	this.myelementid = myelementid;

	this.myelement = document.getElementById(myelementid);
	this.container = document.getElementById(containerid);

	this.options = options || {};

	this.imgw = this.options.iwidth || this.myelement.offsetWidth;
	this.imgh = this.options.iheight || this.myelement.offsetHeight;

	if(this.options.imgsarr) {
	   this.imgwharr = this.options.imgsarr;
	} else {
 	   this.imgwharr = [ [this.options.imgpwidth || 10, this.options.imgpheight || 10],
	  	 	     [this.options.imglwidth || 10, this.options.imglheight || 10],
			     [this.options.imgswidth || 10, this.options.imgswidth || 10] ];
	}

	this.myshape = 1;	/* 0=portrait, 1=landscape, 2=square */

	this.disabled = 1;

	this.maskid = this.options.mask || this.myelementid + '_mask';

	this.pshrinkimageid = this.options.shrtag || this.myelementid + '_pshrink';

	this.imgsrc = this.myelement.src;
	this.pshrink = this.startcoords = null;
	this.startleft = this.starttop = 0;
	this.layercoords = null;
	this.oldabscoords = { x: 0, y: 0 };
	this.newabscoords = null;

	this.pevent = {};

	this.onChange = this.options.onChange || Prototype.emptyFunction;

	this.ns6 = document.getElementById && !document.all;
	this.ie = document.all;

	this.eventMouseDown = this.newpshrink.bindAsEventListener(this);
	this.eventMouseUp   = this.endpshrink.bindAsEventListener(this);
	this.eventMouseDown2 = this.startmovepshrink.bindAsEventListener(this);
	this.eventOnClick = this.updatepshrink.bindAsEventListener(this);

	if(this.imgw > 0) {
		this.initpshrink();
		this.pshrinkimage =  document.getElementById(this.pshrinkimageid);
		Event.observe(this.pshrinkimage, "mousedown", this.eventMouseDown2);

		this.init();
		this.initialized = true;
	} else {
		this.eventOnLoad = this.myonload.bindAsEventListener(this);
		Event.observe(document.getElementById(myelementid), "load", this.eventOnLoad);
	}

	Event.observe(this.container, "mousedown", this.eventMouseDown);
	Event.observe(this.container, "mouseup", this.eventMouseUp);
	Event.observe(this.container, "click", this.eventOnClick);

	Event.observe(window, 'unload', Event.unloadCache, false);

	PShrinks.register(this);
},

myonload: function(event) {
	this.imgw = this.myelement.offsetWidth;
	this.imgh = this.myelement.offsetHeight;

	this.initpshrink();
	this.pshrinkimage =  document.getElementById(this.pshrinkimageid);
	Event.observe(this.pshrinkimage, "mousedown", this.eventMouseDown2);

	this.init();
	this.initialized = true;
},

destroy: function() {
	var pshrinkhandler = this;
	Event.stopObserving(this.container, "mousedown", this.eventMouseDown);
	Event.stopObserving(this.container, "mouseup", this.eventMouseUp);
	Event.stopObserving(this.pshrinkimage, "mousedown", this.eventMouseDown2);
	Event.stopObserving(this.container, "click", this.eventOnClick);

	Event.stopObserving(this.myelement, "mousemove", this.eventMouseOver);
	Event.stopObserving(this.myelement, "mouseout", this.eventMouseOut);

	Event.stopObserving(window, "unload", Event.unloadCache);
	if(this.eventOnLoad) {
		Event.stopObserving(window, "load", this.eventOnLoad);
	}
	PShrinks.unregister(this);
},

iebody: function () {
	return (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body
},

getcoordX: function(event) {
	if(event.pseudo) {
		return event.clientX;
	} else {
		return (this.ns6) ? event.pageX : event.clientX + this.iebody().scrollLeft;
	}
},

getcoordY: function(event) {
	if(event.pseudo) {
		return event.clientY;
	} else {
		return (this.ns6) ? event.pageY : event.clientY + this.iebody().scrollTop;
	}
},

getScrollingPosition: function() {
	var position=[0,0];
	if (typeof window.pageYOffset != 'undefined') {
		position = [window.pageXOffset,window.pageYOffset];
	} else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0) {
		position = [document.documentElement.scrollLeft,document.documentElement.scrollTop];
	} else if (typeof document.body.scrollTop != 'undefined') {
		position = [document.body.scrollLeft,document.body.scrollTop];
	}
	return position;
},

getViewportSize: function() {
	var size=[0,0];
	if (typeof window.innerWidth != 'undefined') {
		size = [window.innerWidth,window.innerHeight];
	} else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0){
		size = [document.documentElement.clientWidth,document.documentElement.clientHeight];
	} else {
		size = [document.getElementsByTagName('body')[0].clientWidth,document.getElementsByTagName('body')[0].clientHeight];
	}
	return size;
},

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

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

	if (this.disabled == 1) return false;

	// Prevent caching issues: Re-do the mask in case the image dimensions have changed
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		var themask = document.getElementById(this.maskid);
		if(!themask) {
			// panic --- what happended?? not intialized???
			this.initpshrink();
			this.pshrinkimage =  document.getElementById(this.pshrinkimageid);
			Event.observe(this.pshrinkimage, "mousedown", this.eventMouseDown2);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.pshrinkimage.style.width = this.imgw + "px";
		themask.style.height = this.pshrinkimage.style.height = this.imgh + "px";
	}

	if(this.pshrink.getvisible() != "visible") {
		var x,y;
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);
		if(!document.all && event.layerX) {
			x = event.layerX;
			y = event.layerY;
		} else {
			x = event.offsetX;
			y = event.offsetY;
		}
		this.oldabscoords.x = clientX;
		this.oldabscoords.y = clientY;
		this.newabscoords = {x: clientX, y: clientY};
		this.layercoords  = {x: x + 1, y: y + 1};
		this.pshrink.draw(x, y,
				this.imgwharr[this.myshape][0], this.imgwharr[this.myshape][1],
				this.imgw, this.imgh);

		var themask = document.getElementById(this.maskid);
		themask.style.visibility = "visible";

		this.startcoords = {x: clientX, y: clientY};
		this.startleft = this.pshrink.getLeft();
		this.starttop = this.pshrink.getTop();
		this.pshrink.drag = true;
	}

	PShrinks.activate(this);

	return false;
},

endpshrink: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	if(event.stopPropagation) {
		event.stopPropagation();
	} else {
		event.cancelBubble = true;
	}
	var themask = document.getElementById(this.maskid);

	if(!document.all) {
		targetid = event.target.id;
	} else {
		targetid = event.srcElement.id;
	}

	if(this.pshrink.track) {
		var clientX = this.getcoordX(event);
		var clientY = this.getcoordY(event);

		themask.style.visibility = "visible";
		this.pshrink.setcursor("default");

		this.oldabscoords.x = clientX;
		this.oldabscoords.y = clientY;
	}

	this.pshrink.drag = false;
	this.pshrink.track = false;
	themask = null;

	this.updatefinished();

	PShrinks.deactivate(this);

	return false;
},

dohandlepshrink: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	if(this.pshrink.track || this.pshrink.drag) {
		if(event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
		this.pevent.clientX = clientX;
		this.pevent.clientY = clientY;
		this.pevent.pseudo = true;
		if(this.pshrink.drag) {
			this.dragpshrink(this.pevent);
		}
	}
	this.oldabscoords.x = clientX;
	this.oldabscoords.y = clientY;

	return false;
},

startmovepshrink: function(event) {
	if(event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	this.startcoords = {x: clientX, y: clientY};
	this.startleft = this.pshrink.getLeft();
	this.starttop = this.pshrink.getTop();
	this.pshrink.drag = true;
	return false;
},

dragpshrink: function(event) {
	var clientX = this.getcoordX(event);
	var clientY = this.getcoordY(event);
	var left = this.startleft + clientX - this.startcoords.x;
	var top = this.starttop + clientY - this.startcoords.y;
	var width = this.pshrink.getWidth();
	var height = this.pshrink.getHeight();

	if(left < 0) left = 0;
	if(top < 0) top = 0;

	var maxright = this.imgw - width - left;
	if(maxright < 0) left += maxright;

	var maxbottom = this.imgh - height - top;
	if(maxbottom < 0) top += maxbottom;

	this.pshrink.dragto(left, top);
},


initpshrink: function() {
	this.pshrink = {
		left:		undefined,
		top:		undefined,
		width: 		undefined,
		height:		undefined,
		idLeft: 	"js_pshrinkleft",
		idTop:		"js_pshrinktop",
		idRight:	"js_pshrinkright",
		idBottom:	"js_pshrinkbottom",
		idMid:		"js_pshrinkmiddle",
		visible:	false,
		myparent:	this
	};

	var left = document.createElement("div");
	var right = document.createElement("div");
	var top = document.createElement("div");
	var bottom = document.createElement("div");

	top.className = "fbthor";
	bottom.className = "fbthor";
	left.className = "fbtver";
	right.className = "fbtver";

	left.id = this.pshrink.idLeft;
	right.id = this.pshrink.idRight;
	top.id = this.pshrink.idTop;
	bottom.id = this.pshrink.idBottom;

	this.container.appendChild(top);
	this.container.appendChild(bottom);
	this.container.appendChild(left);
	this.container.appendChild(right);

	var mid = document.createElement("div");
	mid.className = "fbtmid";
	mid.id = this.pshrink.idMid;
	this.container.appendChild(mid);

	var mask = document.createElement("div");
	mask.id = this.maskid;
	mask.className = "image_fbmask";
	mask.style.width = this.imgw + "px";
	mask.style.height = this.imgh + "px";
	this.container.appendChild(mask);

	var image = document.createElement("img");
	image.id = this.pshrinkimageid;
	image.className = "image_fbtag";
	image.src = this.imgsrc;
	image.style.width = this.imgw + "px";
	image.style.height = this.imgh + "px";
	this.container.appendChild(image);

	this.pshrink.reset = function() {
		this.left = undefined;
		this.top = undefined;
		this.width = undefined;
		this.height = undefined;
		this.setvisible("hidden");
		this.setcursor("move");
		this.track = false;
		this.drag = false;
	};

	this.pshrink.draw = function(left, top, imgwidth, imgheight, imgw, imgh) {
		this.width = width = imgwidth;
		this.height = height = imgheight;
		left = left - (width / 2);
		if(left < 0) left = 0;
		if(left + width > imgw) left = imgw - width;
		top = top - (height / 2);
		if(top < 0) top = 0;
		if(top + height > imgh) top = imgh - height;

		this.left = left
		this.top =  top

		var clip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";
		this.myparent.pshrinkimage.style.clip = clip;

		var dtop = document.getElementById(this.idTop);
		var dbottom = document.getElementById(this.idBottom);
		var dleft = document.getElementById(this.idLeft);
		var dright = document.getElementById(this.idRight);

		dleft.style.left = left + "px";
		dright.style.left = (left + width - 1) + "px";
		dtop.style.left = left + "px";
		dbottom.style.left = left + "px";

		dleft.style.top = top + "px";
		dright.style.top = top + "px";
		dtop.style.top = top + "px";
		dbottom.style.top = (top + height - 1) + "px";

		dleft.style.height = height + "px";
		dright.style.height = height + "px";
		dtop.style.width = width + "px";
		dbottom.style.width = width + "px";

		var dmid = document.getElementById(this.idMid);
		dmid.style.left = left + "px";
		dmid.style.top = top + "px";
		dmid.style.height = height + "px";
		dmid.style.width = width + "px";

		this.setvisible("visible");

		dleft = null;
		dtop = null;
		dright = null;
		dbottom = null;
		dmid = null;
	};

	this.pshrink.dragto = function(left, top) {
		this.left = left;
		this.top = top;
		var width = this.getWidth();
		var height = this.getHeight();

		var dl = document.getElementById(this.idLeft);
		var dr = document.getElementById(this.idRight);
		var dt = document.getElementById(this.idTop);
		var db = document.getElementById(this.idBottom);

		dl.style.left = left + "px";
		dr.style.left = left + width - 1 + "px";
		dt.style.left = left + "px";
		db.style.left = left + "px";

		dl.style.top = top + "px";
		dr.style.top = top + "px";
		dt.style.top = top + "px";
		db.style.top = top + height - 1 + "px";

		var dm = document.getElementById(this.idMid);
		dm.style.left = left + "px";
		dm.style.top = top + "px";
		dm = null;

		var myclip = "rect(" + top + "px, " + (left + width) + "px, " + (top + height) + "px, " + left + "px)";
		this.myparent.pshrinkimage.style.clip = myclip;

		dl = null;
		dt = null;
		dr = null;
		db = null;
	};

	this.pshrink.setLeft = function(left) {
		this.left = left;
	};
	this.pshrink.getLeft = function() {
		return this.left;
	};

	this.pshrink.setTop = function(top) {
		this.top = top;
	};
	this.pshrink.getTop = function() {
		return this.top;
	};

	this.pshrink.setWidth = function(width) {
		this.width = width;
	};
	this.pshrink.getWidth = function() {
		return this.width;
	};

	this.pshrink.setHeight = function(height) {
		this.height = height;
	};
	this.pshrink.getHeight = function() {
		return this.height;
	};

	this.pshrink.setvisible = function(vis) {
		document.getElementById(this.idTop).style.visibility = vis;
		document.getElementById(this.idLeft).style.visibility = vis;
		document.getElementById(this.idRight).style.visibility = vis;
		document.getElementById(this.idBottom).style.visibility = vis;
		document.getElementById(this.idMid).style.visibility = vis;
		document.getElementById(this.myparent.pshrinkimageid).style.visibility = vis;
		this.visibility = vis;
	};
	this.pshrink.getvisible = function() {
		return this.visibility;
	};

	this.pshrink.setcursor = function(cursor) {
		document.getElementById(this.idTop).style.cursor = cursor;
		document.getElementById(this.idLeft).style.cursor = cursor;
		document.getElementById(this.idRight).style.cursor = cursor;
		document.getElementById(this.idBottom).style.cursor = cursor;
		document.getElementById(this.myparent.pshrinkimageid).style.cursor = cursor;
	};

	this.pshrink.setlandscape = function(ls) {
		this.myparent.myshape = ls;
		this.myparent.init();
		this.myparent.updatefinished();
	};
},

init: function() {
	if(themask = document.getElementById(this.maskid)) {
		document.getElementById(this.maskid).style.visibility = "hidden";
	}
	this.layercoords = this.newabscoords = null;
	if(this.pshrink) this.pshrink.reset();
},

setdefault: function(ls) {
	var themask;
	this.myshape = ls;
	this.disabled = 0;
	this.init();
	if(this.imgw != this.myelement.offsetWidth || this.imgh != this.myelement.offsetHeight) {
		this.imgw = this.myelement.offsetWidth;
		this.imgh = this.myelement.offsetHeight;
		this.imgsrc = this.myelement.src;
		if(!(themask = document.getElementById(this.maskid))) {
			// panic --- what happended?? not intialized???
			this.initpshrink();
			this.pshrinkimage =  document.getElementById(this.pshrinkimageid);
			Event.observe(this.pshrinkimage, "mousedown", this.eventMouseDown2);
			this.init();
			this.initialized = true;
			themask = document.getElementById(this.maskid);
		}
		themask.style.width = this.pshrinkimage.style.width = this.imgw + "px";
		themask.style.height = this.pshrinkimage.style.height = this.imgh + "px";
	}

	var pw = this.imgwharr[this.myshape][0];
	var ph = this.imgwharr[this.myshape][1];
	this.pshrink.draw(((this.imgw - pw) / 2) + (pw/2), ((this.imgh - ph) / 2) + (ph/2), pw, ph, this.imgw, this.imgh);

	if(themask = document.getElementById(this.maskid)) {
		Element.show(this.maskid);
		themask.style.visibility = "visible";
	}

	this.pshrink.setcursor("move");

	this.updatefinished();
},

disable: function() {
	this.disabled = 1;
	this.init();
	this.updatefinished();
},

updatefinished: function() {
	if(this.initialized && this.onChange)  {
		myleft = this.pshrink.left;
	 	mytop = this.pshrink.top;
		if (isNaN(myleft) || isNaN(mytop)) { myleft = mytop = -1; }
		var pw = this.imgwharr[this.myshape][0];
		var ph = this.imgwharr[this.myshape][1];
		this.onChange(myleft, mytop, pw, ph, this.imgw, this.imgh);
	}
	this.event = null;
}

};





