

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

var Prototype = {
  Version: '1.5.0_rc1',
  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; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

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

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

    this.registerCallback();
  },

  registerCallback: function() {
    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;
      }
    }
  }
}
Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return camelizedString;
  },

  inspect: function(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 + (object[match[3]] || '').toString();
    });
  }
}

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

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

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

  any: function(iterator) {
    var result = 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(value, index));
    });
    return results;
  },

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

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

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

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

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

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

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

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

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

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

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

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

  toArray: function() {
    return this.collect(Prototype.K);
  },

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

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

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

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

Object.extend(Array.prototype, Enumerable);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  _each: function(iterator) {
    var value = this.start;
    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(responderToAdd) {
    if (!this.include(responderToAdd))
      this.responders.push(responderToAdd);
  },

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

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

Object.extend(Ajax.Responders, Enumerable);

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

  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

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

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

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

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

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

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

    /* Simulate other verbs over post */
    if (this.options.method != 'get' && this.options.method != 'post') {
      parameters += (parameters.length > 0 ? '&' : '') + '_method=' + this.options.method;
      this.options.method = 'post';
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ajax.Updater = Class.create();

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

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

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

    this.request(url);
  },

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

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

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

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

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

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

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

    this.start();
  },

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

  stop: function() {
    this.updater.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 $() {
  var results = [], element;
  for (var i = 0; i < arguments.length; i++) {
    element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);
    results.push(Element.extend(element));
  }
  return results.reduce();
}

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

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

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

Element.extend = function(element) {
  if (!element) return;
  if (_nativeExtensions || 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);

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

  element._extended = true;
  return element;
}

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

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

  toggle: function(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) {
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
    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) {
    element = $(element);
    return $A(element.getElementsByTagName('*'));
  },

  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) {
    element = $(element);
    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) {
    element = $(element);
    return document.getElementsByClassName(className, element);
  },

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

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

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

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

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(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*$/);
  },

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

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

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

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

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

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

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

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

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    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._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.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  }
}

// IE is missing .innerHTML support for TABLE-related elements
if(document.all){
  Element.Methods.update = function(element, html) {
    element = $(element);
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].indexOf(tagName) > -1) {
      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 (!window.HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  /* Emulate HTMLElement, HTMLFormElement, HTMLInputElement, HTMLTextAreaElement,
     and HTMLSelectElement in Safari */
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
    var klass = window['HTML' + tag + 'Element'] = {};
    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
  });
}

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

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

  if (typeof HTMLElement != 'undefined') {
    copy(Element.Methods, HTMLElement.prototype);
    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.toLowerCase();
        if (tagName == 'tbody' || tagName == 'tr') {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

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

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

var Insertion = new Object();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  findElements: function(scope) {
    var element;

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

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

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

    return results;
  },

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

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

  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.strip().split(/\s+/).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;
  }
};

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

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

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

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

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

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

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

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

    return matchingInputs;
  },

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

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

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

  focusFirstElement: function(form) {
    form = $(form);
    Field.activate(Form.findFirstElement(form));
    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);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

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

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

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

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

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

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

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

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

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

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

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

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

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);
    }
    return false;
  },

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

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

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

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

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

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

var $F = Form.Element.getValue;

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

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

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

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

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

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

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

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

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

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

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

  registerFormCallbacks: function() {
    var elements = Form.getElements(this.element);
    for (var i = 0; i < elements.length; i++)
      this.registerCallback(elements[i]);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        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; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    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) {
        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();

/*  i-TV-T framework
 *  (c) 2007 i-TV-T AG
/*--------------------------------------------------------------------------*/

   var RClient = Class.create();
   var globalbehavior = [];

   RClient.ElementComponent = Class.create();
   RClient.ElementComponent.prototype = {
          
     initialize : function() {},
     
     _destroy : function() {
       // Override
     },
     
     destroy : function() {
       document.itvtActive--;
       this._destroy();
       if (this.subcomponents) this.subcomponents.each(function(elem) { elem.destroy(); });
       if (this.events) {       
         for (var i = 0; i < this.events.length; i++) {
           Event.stopObserving.apply(this, this.events[i]);
           this.events[i] = null;
         }
         this.events = null;
       }
       this.subcomponents = null;
       Event.observers = null;
     },
     
     addSub : function(child) {
       if (!this.subcomponents) this.subcomponents = new Array();
       this.subcomponents[this.subcomponents.length] = child;
     },
     
     observe: function(element, name, observer, useCapture) {
       if (!this.events) this.events = new Array();
       this.events.push(arguments);
       
       if (typeof element == 'string') element = document.getElementById(element);

       useCapture = useCapture || false;

       if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent)) name = 'keydown';
        
       if (element.addEventListener) {
         element.addEventListener(name, observer, useCapture);
       } else if (element.attachEvent) {
         element.attachEvent('on' + name, observer);
       }
                    
     },
     
     stopObservingAll : function() {
       if (this.events) {       
         for (var i = 0; i < this.events.length; i++) {
           Event.stopObserving.apply(this, this.events[i]);
           this.events[i] = null;
         }
         this.events = null;
       }
     },
     
     getSubcomponents : function() {
       if (this.subcomponents) return this.subcomponents; else return [];
     },
     
     debug : function(out) {
       for (var eig in this) {
         if (!this[eig] || !this[eig].apply) out.writeln(eig+" = "+this[eig]+"<br>");
       }
       if (this.subcomponents) {
         out.writeln("<ul>");
         for (var i=0;i<this.subcomponents.length;i++) {
           out.writeln("<li>");
           this.subcomponents[i].debug(out);
         }
         out.writeln("</ul>");
       }
       if (this.targets) {
         out.writeln("<ul>");
         for (var i=0;i<this.targets.length;i++) {
         if (this.targets[i].node && $(this.targets[i].node)==null) {
           out.writeln("<li><b>");
           this.targets[i].debug(out);
           out.writeln("<li></b>");
         }
         }
         out.writeln("</ul>");
       }
     }
                                   
   }
   
   RClient.Group = Class.create();
   RClient.Group.prototype = {
   
     initialize : function() {
       this.size = 0;
     },
   
     activate : function(elem) {
       if (this.active) {
         if (this.active == elem) return;
         this.active.deactivate(elem);
       }
       elem.activate(this.active);
       this.active = elem;
     },
     
     join : function(elem) {
       this.size++;
       if (!this.active) this.activate(elem);
     },
     
     leave : function(elem) {
       this.size--;       
     }
     
   };
   
   var NodeService = {    
     attach : function(node,name,obj) {
       $(node)[name] = obj;       
     },
   
     detach : function(node,name) {
       $(node)[name] = null;
     },
   
     get : function(node,name) {
       return $(node)[name];
     },
     
     trigger : function() {      
       var args = $A(arguments);    
       var node = args.shift();   
       var hname = "itvton"+args.shift();
       var events = $(node)[hname];     
       if (!events) { return;}
       for (var i=0;i<events.length;i++) { events[i].apply(this,args); }
     },
     
     createaohandler : function(node,type,script,path) {
       return function() { 
        var ae = new AjaxObjects.AjaxEvent(type,$(node).itvtobj);
        var ah = new AjaxObjects.AjaxEventHandler(script,path);
        ae.trigger(ah);
       };
     },
     
     createhandler : function(script) { 
       return function() { eval(script); }
     },
   
     connect : function(node,event,handler) {
       var hname = "itvton"+event;
       var events = $(node)[hname];
       if (!events) events = $(node)[hname] = [];
       events.push(handler);
       return handler;
     },
   
     deconnect : function(node,event,handler) {
       var hname = "itvton"+event;
       var events = $(node)[hname];
       if (!events) return;
       
       for (var i=0;i<events.length;i++) if (events[i]==handler) {
        events.splice(i,1);
        break;
       }  
       
       if (events.length==0) $(node)[hname] = null;
     }
   };
   



 function rootinit(win) {
   win.ismainwindow = true;
   win.appcontrol = new RClient.AppControl(win);
   frameinit(win,"root");
 }
 
 function frameinit(win,name) {
   if (!win.framecontrol) {
     win.framecontrol = new RClient.FrameControl(win,root(win).appcontrol,name);
   }
 }

 RClient.AppControl = Class.create();
 RClient.AppControl.prototype = {
 
   initialize : function(rootwin) {
     this.rootwindow = rootwin;
     this.loadcount = 0;
     this.preloadcount = 0;
     this.loaddone = 0;
     this.globalversion = 0;
     this.maxtime = 60;
     this.lastclick = new Date().getTime();
     this.lastaction = null;
     rootwin.storage = []; 
     this.locked = [];
     this.checkthread = null;    
     if (debugmode) this.opendebug();
   },
   
   opendebug : function() {   
     try {
       this.debugwin = window.open("about:blank","debugwindow","width=600,height=400,scrollbars=yes,resizable=yes");
       this.debugwin.document.open();
     } catch (e) { this.debugwin = null; }
   },
   
   closedebug : function() {
     if (this.debugwin) { 
       try {
         if (this.debugwin.document) this.debugwin.document.close();
         if (this.debugwin) this.debugwin.close();
       } catch (e) {}
       this.debugwin = null;
     }
   },
   
   debug : function(msg) {
     try {
      if (this.debugwin) this.debugwin.document.writeln(msg+"<br>");
     } catch (e) {}
   },
   
   startaction : function(mt) {
     if (mt) this.maxtime = mt; else this.maxtime=60;
     this.debug("startaction: "+this.globalversion);
     this.globalversion++;
     this.lastclick = new Date().getTime();
     this.lastaction = this.lastclick;
     if (!this.checkthread) this.checkthread = this.rootwindow.setInterval(this.checker.bind(this),1000);     
     this.loaddone = 0;
     try { clstore(this.rootwindow); } catch(e) {}
   },
   
   startload : function() {
     this.preloadcount++;
     this.lastclick = new Date().getTime();
     if (!this.checkthread) this.checkthread = this.rootwindow.setInterval(this.checker.bind(this),1000);  
     dbg("startload:"+this.loadcount+" / "+this.preloadcount);     
   },
         
   pageload : function() {
     if (this.preloadcount>0) this.preloadcount--;
     this.loadcount++;
     this.lastclick = new Date().getTime();
     if (!this.checkthread) this.checkthread = this.rootwindow.setInterval(this.checker.bind(this),1000);       
     dbg("pageload:"+this.loadcount+" / "+this.preloadcount);
     //this.showloadstatus("Please wait ... ("+(this.loaddone/(this.loaddone+this.preloadcount*2+this.loadcount)*100)+" %)");       
   },
   
   endload : function() {
     if (this.loadcount>0) this.loadcount--;
     else if (this.preloadcount>0) this.preloadcount--;
     this.loaddone++;
     this.lastclick = new Date().getTime();     
     this.lastaction = null;
     dbg("endload:"+this.loadcount+" / "+this.preloadcount);
     if (this.loadcount+this.preloadcount<=0) {
       this.clearlocks();
     } else {
       //this.showloadstatus("Please wait ... ("+(this.loaddone/(this.loaddone+this.preloadcount*2+this.loadcount)*100)+" %)");       
     }    
   },
   
   showloadstatus :function(txt) {
     if (this.locked) {
       for (var i=0;i<this.locked.length;i++) {
         try { 
           this.locked[i].showloadstatus(txt);
         } catch (e) {}
       }
     }
   },
   
   addlocked : function(what) {
     this.locked[this.locked.length] = what;
   },
   
   clearlocks : function() {
     if (this.checkthread) {
       this.rootwindow.clearInterval(this.checkthread);
       this.checkthread = null;
     }
     for (var i=0;i<this.locked.length;i++) {
       try { this.locked[i].loadunlock(); } catch(e) {}
     }
     this.locked = [];
   },
   
   errorstate : function() {
     dbg("errorstate");
     this.clearlocks();
     this.loadcount = 0;
     this.preloadcount = 0;   
   },
   
   checkidle : function(fromwin) {
     if (this.loadcount+this.preloadcount>0) {
       fromwin.loadlock(0);
       return false;
     }
     var ct = new Date().getTime();
     if (this.lastaction && ct-this.lastaction<1000) return false;
     return true;
   },
   
   checker : function() {
     dbg("anybusy");
     var rt = this.maxtime - Math.round(((new Date().getTime()) - this.lastclick) / 1000);
     if (rt<50) this.showloadstatus("Waiting... ("+rt+" sec left)");       
     if (rt<0) this.errorstate();
   },
   
   anybusy : function() {
     dbg("anybusy");
     for (frn in this.rootwindow.mywins) {
      try {
       var fr = this.rootwindow.mywins[frn];
       if (!fr) dbg("status: empty");
       else dbg("status: doc="+(fr.document!=null)+" status="+(fr.document!=null ? fr.document.readyState : "null"));
      } catch (e) {
       dbg("status: no access");
      }
     }
     for (var i=0;i<this.rootwindow.frames.length;i++) {
      try {
       var fr = this.rootwindow.frames[i];
       if (!fr) dbg("frame="+i+" status: empty");
       else dbg("frame="+i+" status: doc="+(fr.document!=null)+" status="+(fr.document!=null ? fr.document.readyState : "null"));
      } catch (e) {
       dbg("frame="+i+" status: no access");
      }
     }
   },
   
   onunload : function() {
     this.closedebug();
     for (var eig in this.rootwindow.mywins) {
        if (this.rootwindow.mywins[eig] && !this.rootwindow.mywins[eig].closed==true) { this.rootwindow.mywins[eig].close(); }
     }
   }
        
 }
 
 RClient.FrameControl = Class.create();
 RClient.FrameControl.prototype = {
 
   initialize : function(win,ac,name) {
     this.mywin = win;
     this.appcontrol = ac;
     this.appcontrol.pageload();
     this.name = name;
     this.state = "initialized";
     if (!win.onload) win.onload = pageLoad;
     dbg("FrameControl.initialize: "+name);
   },
 
   onload : function() {
     this.mywin.onerror=errorhandler;  
     this.mywin.itvtloadstore = new Object();
     this.mywin.itvtautoexec = new Object();
     this.mywin.itvtloadframe = new Object();
     this.mywin.execArray=execArrayImpl;   
     this.mywin.onbeforeunload=this.onbeforeunload.bindAsEventListener(this);
     this.mywin.onunload=this.onunload.bindAsEventListener(this);
     this.mywin.onload=null;
     this.mywin.document.itvtActive = 0;
     this.mywin.document.onkeydown = this.nobackspace.bindAsEventListener(this);
     this.mywin.document.onkeypress = this.mywin.document.onkeydown;
     this.mywin.desktop = new RClient.Desktop();
     
     var pview = [this.mywin.desktop];   
     var dp = new DP();
     for (var i=0;i<loads.length;i++) {dbg(loads[i]);eval(loads[i]);}
     pview[0].doInit();
     checkIEscrollbarbug();
     this.state = "loaded";
     this.appcontrol.endload();
     dbg("FrameControl.onload: "+this.name);
   },
   
   onbeforeunload : function() {
     dbg("FrameControl.onbeforeunload: "+this.name);     
     if (this.mywin.appcontrol) this.appcontrol.closedebug();
     try {
       storewindow(this.appcontrol.rootwindow,this.mywin);
     } catch (e) {}
   },
   
   onunload : function() {  
     if (this.mywin.appcontrol) this.appcontrol.onunload();      
     if (this.locktimer) {      
       this.mywin.clearInterval(this.locktimer);
       this.locktimer = null;
     }       
     if (this.mywin.desktop) {
       try { this.mywin.desktop.destroy(); } catch(e) {}
       this.mywin.onbeforeunload = null;
       this.mywin.onunload = null;
       this.mywin.desktop = null;
       try {
         this.mywin.document.onkeydown = null;
         this.mywin.document.onkeypress = null;      
       } catch (e) {}
     }
   },
   
   nobackspace : function(event) {
     var src = event.srcElement ? event.srcElement : event.target;
     if (event.keyCode==8 && src && (src.nodeName!="INPUT" || src.type=="checkbox" || src.type=="radio") && (src.nodeName!="TEXTAREA")) {     
      return false;
     }
     return true;     
   },
   
   close : function() {   
     if (this.mywin.desktop) this.mywin.desktop.destroy();
     this.mywin.onbeforeunload = null;
     this.mywin.onunload = null;
     this.mywin.desktop = null;
     this.appcontrol.pageload();
     this.appcontrol.endload();
     this.mywin.close();
   },
 
   gourl : function(url) {
     dbg("FrameControl.gourl: "+this.name);
     if (!this.appcontrol.checkidle(this)) return;
     this.appcontrol.startaction();
     this.appcontrol.startload();
     this.state="request";
     this.loadlock(500);
     
     if (url[0]=="/") {
       var loc = this.mywin.document.location;
       var curl = loc.protocol+"//"+loc.host+url;  
       loc.href = curl;
       //loc.replace(curl);
     } else {
       this.mywin.document.location.href = url;
       //this.mywin.document.location.replace(url);
     }
   }, 
                     
   ajax : function(url,data,noasync) {
     dbg("FrameControl.ajax2: "+this.name);
     if (!this.appcontrol.checkidle(this)) return;
     var url2 = url.split("?");
     if (url2.length>1) data = data+"&"+url2[1];
     url = url2[0];
     this.loadlock(2000);
     this.appcontrol.startload();     
     var async = true;
     if (noasync) async = false;
     new Ajax.Request(url, { 
       onSuccess: function(req,header) {
         if (req.responseText.substring(0,8)=="<SCRIPT>") {
           var scripts = req.responseText.extractScripts();
           var content = req.responseText.stripScripts();  
           //dbg(scripts);
           try { eval(scripts[0]); } catch(e) { dbg("ERROR in Ajax.Request:"+e);}
         } else {
           dbg(req.responseText);
           eval(req.responseText);
         }
         root(window).appcontrol.endload();       
         dbg("ajax success");
       },
       onFailure: function(req,header) {
         root(window).appcontrol.endload();       
       },
       method:"post",
       asynchronous:async,
       parameters:data,
       contentType:"application/x-www-form-urlencoded; charset=UTF-8"     
     });            
   },
   
   submit : function(form,hide,acstr,bean,ext) {
     dbg("FrameControl.submit: "+this.name);
     if (!this.appcontrol.checkidle(this)) return;
     if (ext) this.loadlock(0);
     else if (hide) this.loadlock(500);
     if (acstr) form.action.value=acstr;
     if (bean) form.bean.value=bean;
     if (ext) {
       this.appcontrol.startaction(3600);
       this.appcontrol.showloadstatus("Please wait! Action may take serveral minutes");
     } else this.appcontrol.startaction();
     if (hide) this.appcontrol.startload();
     form.submit();
   },
   
   deltaload : function(url,fromwin) {   
     dbg("FrameControl.deltaload: "+this.name);
     storewindow(this.appcontrol.rootwindow,this.mywin);
     this.appcontrol.startload();
     this.loadlock(500);
     var async = true;
     if (fromwin && fromwin.opener && fromwin.opener==root(window)) async=false;
     new Ajax.Request(url, { 
       onSuccess: function(req,header) {
         var scripts = req.responseText.extractScripts();
         var content = req.responseText.stripScripts();       
         try { eval(scripts[0]); } catch(e) { dbg("ERROR:"+scripts[0]); }
         root(window).appcontrol.endload();       
         dbg("delta success");
       },
       onFailure: function(req,header) {
         root(window).appcontrol.endload();
       },
       method:"get",
       asynchronous:async,
       contentType:"application/x-www-form-urlencoded; charset=UTF-8"
     });
   },
   
   showlock : function() {
     if (this.locktimer) {
       this.mywin.clearInterval(this.locktimer);
       this.locktimer = null;
     }
     var frame = this.mywin;
     var l0 = frame.document.getElementById("content");
     var l = frame.document.getElementById("content2");
     var l2 = frame.document.getElementById("content3");
        
     if (l!=null && l2!=null) {
       var height1=l0.offsetHeight;
       var height2=frame.document.getElementsByTagName("body")[0].offsetHeight;
       if (height2>height1) height1 = height2;
       l.style.height=height1+"px";        
       l.style.backgroundColor="#505050";
  
       l.style.filter="alpha(opacity="+30+")";
       l.style.MozOpacity=""+0.3;
       l.style.KhtmlOpacity=""+0.3;
       l.style.opacity=""+0.3;      
  
       //if (navigator.userAgent.toLowerCase().indexOf("msie")==-1 || window.opera) {
       // l.style.backgroundImage="url("+baseurl+"/img/darker.png)";
       //} else {
       // 
       // l.style.filter="Alpha(Opacity=30)";     
       //}    
       l.style.display="block";
       l2.style.display="block";
       switchAllSelects(false); // l2
       this.showloadstatus("Please wait...");
     }
   },
   
   showloadstatus : function(text) {
     var h3 = this.mywin.document.getElementById("wprompt");
     if (h3) h3.firstChild.data = text;
   },
   
   unlockframe : function() { 
     this.locked = false;
     var frame = this.mywin;
     if (!frame.document) return;
     var l = frame.document.getElementById("content2");
     var l2 = frame.document.getElementById("content3");
     var needunlock = false;
     if (l!=null && l.style.display=="block") { l.style.display="none";needunlock = true; }
     if (l2!=null) {
       l2.style.display="none";
       if (needunlock) switchAllSelects(true); // l2
     }     
   },
   
   loadlock : function(delay) {
     if (this.locked) return;
     this.appcontrol.addlocked(this);
     var r = this.mywin;
     if (delay==0) this.showlock();
     else {      
      if (this.locktimer==null) this.locktimer=r.setInterval(this.showlock.bind(this),delay);
     }
   },
   
   loadunlock : function() {         
      var r = this.mywin;
      if (this.locktimer!=null) { r.clearInterval(this.locktimer);this.locktimer=null; }
      this.unlockframe();
   }
  
}
   

 RClient.MoveEffect = Class.create();
 RClient.MoveEffect.prototype = {
  
    initialize : function(node,targetx,targety,steps) {
      this.node = node;
      this.targetx=targetx;
      this.targety=targety;
      this.steps = steps;
      this.stepno = 0;
      this.startx = this.node.offsetLeft;
      this.starty = this.node.offsetTop;
      
      this.dx = (this.targetx - this.startx) / steps;
      this.dy = (this.targety - this.starty) / steps;
      this.currentx = this.startx;
      this.currenty = this.starty;
      this.handler = null;
    },
    
    begin : function() {
      this.handler = window.setInterval(this.animate.bind(this),100);
    },
    
    abort : function() {
     if (this.handler) window.clearInterval(this.handler);
     this.handler = null;
    },
            
    animate : function() {   
      this.currentx += this.dx;
      this.currenty += this.dy;   
      this.stepno++;
      this.node.style.left = this.currentx+"px";
      this.node.style.top = this.currenty+"px";
      if (this.stepno>=this.steps) this.abort();
    }
  };
  
 RClient.AnimationThread = Class.create();
 RClient.AnimationThread.prototype = {
    
    initialize : function(ani,node) {
      dbg("AnimationThread: init");
      if (node) {
        ani = ani.copy();
        ani.node = $(node);
      }
      if (ani) {
        this.play(ani);
        this.run();
      }
    },
    
    run : function() {           
      this.handler = window.setInterval(this.animate.bind(this),50); 
      dbg("AnimationThread: run:"+this.handler);
    },
    
    play : function(animation) {
      dbg("AnimationThread: play");
      if (this.current) {
        var c = this.current;
        this.current = null;
        c.abort();
      }
      animation.begin();
      this.current = animation;       
    },
    
    animate : function() {  
    try {
      if (this.current!=null) {
        this.current.animate();
        if (this.current.finished) this.destroy();
      }
     } catch (e) { window.status = "ERROR";this.destroy(); }
    },
    
    destroy : function() {
      dbg("AnimationEffekt: destroy");
      if (this.handler) window.clearInterval(this.handler);
      this.handler = null;
      var c = this.current;
      this.current = null;
      if (c) c.abort();
    }
 }
 
  
 RClient.DestinationEffect= Class.create();
 RClient.DestinationEffect.prototype = {
  
    initialize : function(startx,starty,steps,mode,lock) {
      dbg("DestinationEffekt: init/"+startx+"/"+starty+"/"+steps+"/"+mode);
      this.steps = steps;
      this.stepno = 0;
      if (mode==1) { // accelerate
        this.targetx = startx;
        this.targety = starty;
        this.startx=0;
        this.starty=0;      
        this.ax = -2 * (this.targetx - this.startx) / (steps * steps); 
        this.ay = -2 * (this.targety - this.starty) / (steps * steps);
        this.dx = this.ax / 2;
        this.dy = this.ay / 2;                
      } else if (mode==2) { //deaccelerate
        this.startx = startx;
        this.starty = starty;
        this.targetx=0;
        this.targety=0;
        this.ax = 2 * (this.targetx - this.startx) / (steps * steps); 
        this.ay = 2 * (this.targety - this.starty) / (steps * steps);
        this.dx = this.ax * steps - this.ax / 2;
        this.dy = this.ay * steps - this.ay / 2;        
      } else {
        this.startx = 0;
        this.starty = 0;
        this.targetx = startx;
        this.targety = starty;
        this.ax = 0; 
        this.ay = 0;
        this.dx = -(this.startx - this.targetx)/steps;
        this.dy = -(this.starty - this.targety)/steps;
      }
      this.lock = lock;
      this.mode = mode;
      this.currentx = this.startx;
      this.currenty = this.starty;
      this.handler = null;           
    },
    
    begin : function() {
     dbg("DestinationEffekt: begin");
     if (this.lock) {
        this.mover = Element.down(this.node,"div");
        if (this.mover) {
         this.node.style.width = this.mover.offsetWidth+"px";
         this.node.style.height = this.mover.offsetHeight+"px";
         this.mover.style.position="relative"; 
         this.mover.style.left=this.startx+"px";
         this.mover.style.top=this.starty+"px";
         this.node.style.visibility="visible";    
        } else {
         this.node.style.visibility="visible";    
         this.finished = true;
         this.node = null;
        } 
      } else {
        this.mover = this.node;
        this.mover.style.left=this.startx+"px";
        this.mover.style.top=this.starty+"px";
      }
    },
    
    abort : function() {
     var n = this.node;
     this.node = null;
     if (n) {
       if (this.lock) {
         n.style.height = null;
         n.style.width = null;     
         if (this.mode==1) n.style.visibility = "hidden";
         this.mover.style.position="static";
         this.mover.style.left = null;
         this.mover.style.top = null;         
       }
       this.handler = null;       
       this.mover = null;
     }
    },
            
    animate : function() {  
     if (this.node) { 
      this.currentx += this.dx;
      this.currenty += this.dy;   
      this.dx -= this.ax;
      this.dy -= this.ay;
      this.stepno++;
      this.mover.style.left = this.currentx+"px";
      this.mover.style.top = this.currenty+"px";
      if (this.stepno>=this.steps-1) this.finished = true;
     }
    },
    
    copy : function() { return Object.clone(this); }
  };
  
  RClient.SerialAnimation = Class.create();
  RClient.SerialAnimation.prototype = {
  
    initialize : function() {
      this.animations = [];
      this.step = 0;
    },
    
    add : function(animation) {
      this.animations.push(animation);
    },
    
    begin : function() {
      var n = this.node;
      if (n) this.animations.each(function f(x) { if (!x.node) x.node = n });
      this.step = 0;
      this.animations.first().begin();
    },
    
    animate : function() {
     if (!this.finished) {
       var ani = this.animations[this.step];
       ani.animate();
       if (ani.finished) this.next();
     }
    },
    
    next : function() {
      this.animations[this.step].abort();
      this.step++;
      if (this.step>=this.animations.length) {
        this.finished = true;
      } else {
        this.animations[this.step].begin();
      }
    },
    
    abort : function() {
      if (this.step<this.animations.length) this.animations[this.step].abort(); 
    },
    
    copy : function() { 
     var r = Object.clone(this); 
     r.animations = [];
     for (var i = 0;i<this.animations.length;i++) r.animations[i] = this.animations[i].copy();
     return r;
    }
    
  };
  
  RClient.ParallelAnimation = Class.create();
  RClient.ParallelAnimation.prototype = {
  
    initialize : function() {
      this.animations = [];    
    },
    
    add : function(animation) {
      this.animations.push(animation);
    },
    
    begin : function() {
      var n = this.node;
      if (n) this.animations.each(function f(x) { if (!x.node) x.node = n });
      this.animations.each(function f(x) { x.begin(); });
    },
    
    animate : function() {
      var alldone = true;
      this.animations.each(function f(x) { if (!x.finished) {x.animate();alldone=false;}});
      if (alldone) this.finished = true;
    },
        
    abort : function() {
      this.animations.each(function f(x) { x.abort(); });
    },
    
    copy : function() { 
     var r = Object.clone(this); 
     r.animations = [];
     for (var i = 0;i<this.animations.length;i++) r.animations[i] = this.animations[i].copy();
     return r;
    }
    
  };
  
  RClient.ColorAnimation = Class.create();
  RClient.ColorAnimation.prototype = {
  
    initialize : function(whichcss,r1,g1,b1,r2,g2,b2,steps) {    
      this.whichcss = whichcss;
      this.r1 = r1;
      this.g1 = g1;
      this.b1 = b1;
      this.r2 = r2;
      this.g2 = g2;
      this.b2 = b2;
      this.steps = steps;
    },
    
    begin : function() {
      this.step = 0;
    },
    
    animate : function() {
      var f = this.step / this.steps;
      var f2 = 1-f;
      var r = Math.round(f2 * this.r1 + f * this.r2);
      var g = Math.round(f2 * this.g1 + f * this.g2);
      var b = Math.round(f2 * this.b1 + f * this.b2);
      var col = "#"+r.toColorPart()+g.toColorPart()+b.toColorPart();
      this.node.style[this.whichcss] = col;
      this.step++;
      if (this.step>=this.steps) this.finished = true;
    },
    
    abort : function() {
      if (this.node) this.node.style[this.whichcss] = "#"+this.r2.toColorPart()+this.g2.toColorPart()+this.b2.toColorPart();
    },
    
    copy : function() { return Object.clone(this); }
        
  };
  
  RClient.WaitAnimation = Class.create();
  RClient.WaitAnimation.prototype = {
  
    initialize : function(steps) {    
      this.steps = steps;
    },
    
    begin : function() {
      this.step = 0;
    },
    
    animate : function() {
      this.step++;
      if (this.step>=this.steps) this.finished = true;
    },
    
    abort : function() {      
    },
    
    copy : function() { return Object.clone(this); }
        
  };
  
  RClient.TriggerAnimation = Class.create();
  RClient.TriggerAnimation.prototype = {
  
    initialize : function() {    
    },
    
    begin : function() {
    },
    
    animate : function() {      
      tr_trigger(this.node.id);
      this.finished = true;
    },
    
    abort : function() {      
    },
    
    copy : function() { return Object.clone(this); }
        
  };
  
 RClient.FadeEffect= Class.create();
 RClient.FadeEffect.prototype = {
  
    initialize : function(start,target,steps) {
      dbg("FadeEffekt: init/"+start+"/"+target+"/"+steps);
      this.steps = steps;
      this.stepno = 0;
      this.start = start;
      this.target = target;
    },
    
    begin : function() {
     dbg("FadeEffekt: begin");
     if (this.node) {
      this.node.style.filter="alpha(opacity="+this.start*100+")";
      this.node.style.MozOpacity=""+this.start;
      this.node.style.KhtmlOpacity=""+this.start;
      this.node.style.opacity=""+this.start;
      this.node.style.display='block';
     }
    },
    
    abort : function() {
     this.stepno = this.steps;
     this.animate();
     this.node = null;
    },
                
    animate : function() {  
     if (this.node) {     
      var f = 1.0 * this.stepno / this.steps;
      var cv = this.start * (1-f) + this.target * f;
      this.stepno++;      
      this.node.style.filter="alpha(opacity="+cv*100+")";
      this.node.style.MozOpacity=""+cv;
      this.node.style.KhtmlOpacity=""+cv;
      this.node.style.opacity=""+cv;      
      if (this.stepno>=this.steps-1) {
        this.finished = true;
        if (this.target==0) {
          this.node.style.display="none";
        }
        if (this.target==0 || this.target==1) {
          this.node.style.filter="";
          this.node.style.MozOpacity="";
          this.node.style.Opacity="";
          this.node.style.KhtmlOpacity="";
        }        
      }
     }
    },
    
    copy : function() { return Object.clone(this); }
  };
  
  RClient.ShrinkEffect= Class.create();
  RClient.ShrinkEffect.prototype = {
  
    initialize : function(steps) {
      dbg("ShrinkEffekt: init/"+steps);
      this.steps = steps;
      this.stepno = 0;
    },
    
    begin : function() { 
     dbg("FadeEffekt: begin");
     if (this.node) {
      this.starty = this.node.offsetTop;
      this.startx = this.node.offsetLeft;
      this.xs = this.node.offsetWidth + this.startx*2;
      this.ys = this.node.offsetHeight + this.starty*2;       
      this.stepno = 0;
     }
    },
    
    abort : function() {
     this.stepno = this.steps;
     this.animate();
     this.node.style.display="none";
     this.node = null;
    },
                
    animate : function() {  
     if (this.node) {     
      this.stepno++;
      var f = this.stepno / this.steps;
      var xt = this.xs * (1 - f);
      var yt = this.ys * (1 - f);
      if (xt>0 && yt>0) {
        this.node.style.width = xt+"px";
        this.node.style.height = yt+"px";
        this.node.style.left=this.startx + (this.xs * f /2)+"px";
        this.node.style.top=this.starty + (this.ys * f /2)+"px";
      }
      //this.node.style.clip="rect(auto,"+xt+"px,auto,"+yt+"px)";
      if (this.stepno>=this.steps-1) {
        this.finished = true;
        this.node.style.display="none";
      }
        
     }
    },
    
    copy : function() { return Object.clone(this); }
  };
  

  RClient.FormElement = Class.create();
  RClient.FormElement.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(node,isoptional,errkey) {     
      this.node = $(node);
      this.isoptional = isoptional;
      //this.rx = rx;
      //this.errclass = errclass;
      this.errkey = errkey;
      this.errmsg = null;
      this.observe(this.node,"blur",this.valid.bindAsEventListener(this));
      if (window.currentform) window.currentform.elements[this.errkey] = this;
    },
    
    setError : function(msg) {
      dbg("setError");
      if (!this.errmsg) {
        this.errmsg = new RClient.Tooltip(this.node,false,true,false,msg);
        this.node.addClassName("fielderror");
        this.keyhandler = this.observe(this.node,"keypress",this.errorfree.bindAsEventListener(this));
      }
    },
    
    valid : function(ev) {
      var v = this.node.value;
      if (!this.isoptional && (!v || v.length==0)) {
        this.setError("Please fill out this entry field");
      }
      else if (this.rx) {
        if (v.search(this.rx)!=1) this.setError("Junk content");
      } else this.errorfree();
    },
     
    
    errorfree : function() {  
      dbg("errorfree");  
      if (this.errmsg) {
        this.node.removeClassName("fielderror");
        this.errmsg.destroy();
        this.errmsg = null;
      }
      if (this.keyhandler) this.stopObserving(this.keyhandler);
    },
       
    _destroy : function() {
      this.errorfree();
    }
          
  });
  
  RClient.InfoWindow = Class.create();
  RClient.InfoWindow = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(node,text) {
      this.node = node;
      this.text = text;
    },
    
    setText : function(text) {
      this.text = text;
      this.node.innerHTML = text;
    },
    
    setVisible : function(vis) {
      this.node.style.display = vis ? "block" : "none";
    }
        
  });
  
  RClient.Form = Class.create();
  RClient.Form.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(form) {
      this.form = $(form);
      this.form.itvtform = this;
      this.elements = [];
      window.currentform = this;
    },
    
    setError : function(key,errmsg) {
      var elem = this.elements[key];
      if (elem) elem.setError(errmsg);
    },
    
    _destroy : function() {
      this.form.itvtform = null;
    }
    
  });


  RClient.Tooltip = Class.create();
  RClient.Tooltip.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(node,showonover,showonfocus,autofollow,text) {
      this.node = $(node);
      this.bubble = null;
      this.text = text ? text : "";
      this.autofollow = autofollow;
      if (showonover) {
        this.h1 = this.observe(this.node,"mouseover",this.mouseover.bindAsEventListener(this));
        this.h2 = this.observe(this.node,"mouseout",this.mouseout.bindAsEventListener(this));
      }
      if (showonfocus) {
        this.h3 = this.observe(this.node,"focus",this.focus.bindAsEventListener(this));
        this.h4 = this.observe(this.node,"blur",this.mouseout.bindAsEventListener(this));
      }
    },
    
    create : function() {
      var old = this.node.style.position;
      this.node.style.position = "relative";     
      this.bubble = quickcreate("div","bubble","<span>"+this.text+"</span>");
      this.bubble.style.left = xc(this.node)+"px";     
      document.getElementsByTagName('body')[0].appendChild(this.bubble);     
      this.bubble.style.top = (yc(this.node)-this.bubble.offsetHeight)+"px";
      this.node.style.position = old;
    },
    
    setText : function(text) {
      this.text = text;    
      if (this.bubble) this.bubble.firstChild.innerHTML = this.text;
    },
    
    setVisible : function(vis) {
      if (this.visible == vis) return;
      this.visible = vis;
      if (!this.bubble) this.create();
      if (vis) this.bubble.style.display="block";
      else this.bubble.style.display="none";
    },
       
        
    dispose : function() {
      if (this.bubble) {
       document.getElementsByTagName('body')[0].removeChild(this.bubble);
       this.bubble = null;
      }
      if (this.h1) {
        this.stopObserving(this.h1);this.h1 = null;
      }
      if (this.h2) {
        this.stopObserving(this.h2);this.h2 = null;
      }
      if (this.h3) {
        this.stopObserving(this.h3);this.h3 = null;
      }
      if (this.h4) {
        this.stopObserving(this.h4);this.h4 = null;
      }
    },
    
    mouseover : function(ev) {
      if (!this.over && this.text!="") {
       if (this.autofollow && window.itvtdnd && window.itvtdnd.move==null) {
         this.moveenabled = true;
         window.itvtdnd.move = this.follow.bind(this);
       }
       this.over = true;
       this.setVisible(true);        
      }      
    },
    
    mouseout : function(ev) {
      if (this.over) {
        if (this.moveenabled) {
          this.moveenabled = false;
          window.itvtdnd.move = null;
        }
        this.over = false;      
        this.setVisible(false);
      }
    },
    
    focus : function(ev) {
      if (!this.over && this.text!="") {
        this.over = true;
        this.setVisible(true);
      }      
    },
      
    
    follow : function(ev) {
      this.bubble.style.top = (Event.pointerY(ev)-this.bubble.offsetHeight-10)+"px";
      this.bubble.style.left = Event.pointerX(ev)+"px";
    },
        
        
    _destroy : function() {
      this.dispose();
    }
     
  });
  

 
  RClient.HybridTagBase = Class.create();
  RClient.HybridTagBase.prototype = Object.extend(new RClient.ElementComponent(),{
   
    initialize : function() {
      document.itvtActive++;
    },
  
    keypress : function(ev) {     
      if (ev.keyCode==40) {
        if (this.openend) this.down(); else this.open();
      }
      else if (ev.keyCode==38) this.up();
      else if (ev.keyCode==13 && this.openend) this.select();
      else {
        if (this.openend) this.close();
        return true;
      } 
      Event.stop(ev);
    },
    
    outsideclick : function(ev) {
      if (this.openend) this.close();
    },
    
    makediv : function() {
      this.optiondiv = document.createElement("div");
      this.showdiv = this.optiondiv;
      this.optiondiv.className = "optionsinner optionsouter";
      this.optiondiv.style.width=(this.field.offsetWidth-2)+"px";    
      this.optiondiv.style.top=(yc(this.field)+this.field.offsetHeight)+"px";
      this.optiondiv.style.left=xc(this.field,"makediv")+"px";
      document.getElementsByTagName("body")[0].appendChild(this.optiondiv);    
    },
    
    open : function() {
      if (!this.optiondiv) {
        this.makediv();
      }      
      
      this.optiondiv.innerHTML="Please wait...";
      this.footer();
              
      Element.show(this.showdiv);            
      this.docclick = this.outsideclick.bindAsEventListener(this);
      Element.observe(document,"click",this.docclick);
                  
      this.openend = true;
      switchSelects(this.showdiv,false);
      this.load();
    },
    
    footer : function() {},
        
    clear : function() {
       this.options.each(function(elem) { elem.destroy(); });
       this.options.clear();
       this.cursor = 0;
       this.optiondiv.innerHTML="";
    },   
     
    add : function(val,txt,sel) {      
      if (sel) this.cursor = this.options.length;
      this.options[this.options.length] = new RClient.HybridOption(val,txt,this);
    },
    
    addmore : function(txt) {
      //this.optiondiv.innerHTML = this.optiondiv.innerHTML + txt;
    },
        
    finish : function() {    
      if (this.options.length==0) {      
        this.nomatch();
      } else {
        this.footer();
        this.options[this.cursor].setSelected(true);
        if (this.optiondiv.offsetHeight>=200) this.optiondiv.style.height="200px";
        else this.optiondiv.style.height = null;
        dbg(this.optiondiv.offsetWidth+"/"+this.optiondiv.offsetHeight+"/"+this.optiondiv.scrollWidth+"/"+this.optiondiv.scrollHeight);
        if (this.optiondiv.scrollWidth>this.optiondiv.offsetWidth && this.optiondiv.offsetWidth<300) {
         this.optiondiv.style.width = (this.optiondiv.scrollWidth<300 ? this.optiondiv.scrollWidth : 300)+"px";
        }        
        if (this.openend) switchSelects(this.showdiv,false);
      }
    },
    
    nomatch : function() {
      this.optiondiv.innerHTML="No matches";
      this.footer();
    },
    
    load : function() {      
       var elem = this;
       new Ajax.Request(this.url, { 
         onSuccess: function(req,header) { if (elem.openend) eval(req.responseText); },
         method:"post",
         contentType:"application/x-www-form-urlencoded; charset=UTF-8",
         parameters:"elem="+this.name+"&"+this.name+"="+encodeURIComponent(this.field.value)+"*" });
    },
    
    close : function() {      
      if (this.showdiv) {
        switchSelects(this.showdiv,true);
        Element.hide(this.showdiv);
        this.optiondiv.innerHTML = "";
        this.options.each(function(elem) { elem.destroy(); });
        this.options.clear();        
      }
      this.cursor = 0;
      this.openend = false;          
      if (this.docclick) {
        Element.stopObserving(this.docclick);
        this.docclick = null;
      }
    },
           
    select : function() {
      if (this.cursor<this.options.length) this.field.value = this.options[this.cursor].val;
      this.close();
    },
    
    selectOption : function(option) {
      this.field.value = option.val;
      this.close();
    },
    
    up : function() {
     if (this.cursor>0) {
        this.options[this.cursor].setSelected(false);
        this.cursor--;
        this.options[this.cursor].setSelected(true);
        if (this.options[this.cursor].mydiv.offsetTop>190) {
          this.optiondiv.scrollTop = this.options[this.cursor].mydiv.offsetTop - 100;
        } else {
          this.optiondiv.scrollTop = 0;
        }
      } else this.close();   
    },
    
    down : function() {
      if (this.cursor<this.options.length-1) {
        this.options[this.cursor].setSelected(false);
        this.cursor++;
        this.options[this.cursor].setSelected(true);
        if (this.options[this.cursor].mydiv.offsetTop>190) {
          this.optiondiv.scrollTop = this.options[this.cursor].mydiv.offsetTop - 100;
        } else {
          this.optiondiv.scrollTop = 0;
        }
      }      
    },
    
    _destroy : function() {
      this.alive = false;
      this.close();
    }
  
  });
  
  RClient.HybridOption = Class.create();
  RClient.HybridOption.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(val,text,parent) {
      document.itvtActive++;
      this.val = val;
      this.text = text;
      this.selected = false;
      this.parent = parent;
      this.mydiv = document.createElement("div");
      this.mydiv.innerHTML = text;
      this.mydiv.className="optionoff";
      parent.optiondiv.appendChild(this.mydiv);      
      this.mydiv.onclick  = this.click.bindAsEventListener(this);
    },
        
    setSelected : function(sel) {
      if (sel) {
        this.mydiv.className="optionon";
      } else {
        this.mydiv.className="optionoff";
      }
      this.selected = sel;
    },
    
    click : function(ev) {
      //alert("click!");
      this.parent.selectOption(this);
      this.parent.field.focus();
    },
    
    _destroy : function() {
      this.mydiv.onclick = null;
    }
                
  });

  RClient.HybridTag = Class.create();
  RClient.HybridTag.prototype = Object.extend(new RClient.HybridTagBase(),{
    
    initialize : function(id,url) {
      document.itvtActive++;
      this.field = document.getElementById(id);
      this.optiondiv = null;  
      this.options = [];
      this.cursor = 0;
      this.url = url;    
      this.opened = false;
      this.name = this.field.name;
      this.alive = true;
      this.observe(this.field,"keypress",this.keypress.bindAsEventListener(this));    
    }
           
  });


  RClient.DoubleHybridField = Class.create();
  RClient.DoubleHybridField.prototype = Object.extend(new RClient.HybridTagBase(),{
  
    initialize : function(id,url) {  
      document.itvtActive++;  
      this.field = $(id);
      this.optiondiv = null;  
      this.options = [];
      this.cursor = 0;
      this.url = url;    
      this.opened = false;
      this.complete = true;
      this.name = this.field.name+"_a";
      this.altMode = false;
      this.alive = true;
      this.retest = false;
      this.observe(this.field,"keypress",this.keypress.bindAsEventListener(this));
      this.observe(this.field,"blur",this.blur.bindAsEventListener(this));
      this.observe(this.field,"click",this.click.bindAsEventListener(this));
    },
    
    makediv : function() {
      this.optiondiv = document.createElement("div");
      this.optiondiv.className = "optionsinner";      
      this.footerdiv = document.createElement("div");
      this.footerdiv.innerHTML = "TEST";
      this.footerdiv.className = "optionswitch";
      this.showdiv = document.createElement("div");
      this.showdiv.className = "optionsouter";
      this.showdiv.appendChild(this.optiondiv);
      this.showdiv.appendChild(this.footerdiv);
      this.optiondiv.style.width=(this.field.offsetWidth-2)+"px";    
      this.showdiv.style.width=(this.field.offsetWidth-2)+"px";    
      this.showdiv.style.top=(yc(this.field)+this.field.offsetHeight)+"px";
      this.showdiv.style.left=xc(this.field,"makediv2")+"px";
      document.getElementsByTagName("body")[0].appendChild(this.showdiv);    
    },
    
    keypress : function(ev) {  
      if (this.complete && !(ev.keyCode==9)) this.shorten();
      if (ev.keyCode==40) {
        if (this.openend) this.down(); else { this.retest = true; this.open();}
      }
      else if (ev.keyCode==38) this.up();
      else if (ev.keyCode==37 && this.openend) this.codeMode();
      else if (ev.keyCode==39 && this.openend) this.nameMode();
      else if (ev.keyCode==13 && this.openend) this.select();
      else {
        if (this.openend) this.close();
        return true;
      } 
      Event.stop(ev);
    },
    
    click : function(ev) {
      if (this.complete) this.shorten();
      if (this.openend) this.close();
    },
    
    set : function(val) {
      this.field.value = val;      
      this.complete = true;
    },
    
    
    shorten : function() {
      var v = this.field.value.split(" (");     
      if (v.length==2) this.field.value = v[0];
      else if (v.length>2) {
        var r = v[0];
        for (var i=1;i<v.length-1;i++) {
          var pc = v[i].lastIndexOf(")");
          if (pc>=0) r+=v[i].substring(pc+1);
        }
        this.field.value = r;
      }
      this.field.select();
      this.complete = false;      
    },
        
    
    selectOption : function(option) {
      this.field.value = option.val;
      this.complete = false;
      this.close();
    },
    
    codeMode : function() {
      this.altMode = false;
      this.name = this.field.name+"_a";
      this.load();
    },
    
    nameMode : function() {
      this.altMode = true;
      this.name = this.field.name+"_b";
      this.load();
    },
    
    footer : function() {      
      this.footerdiv.style.width = "100%";
      this.footerdiv.style.height = "20px";
      this.footerdiv.style.border="1px solid black";
      if (this.altMode) {
        this.footerdiv.innerHTML="<div style='float:right'><b>name</b> --&gt;&nbsp;</div><div>&nbsp;&lt;-- code</div><div style='clear:both'></div>";
      } else {
        this.footerdiv.innerHTML="<div style='float:right'>name --&gt;&nbsp;</div><div>&nbsp;&lt;-- <b>code</b></div><div style='clear:both'></div>";
      }
    },
    
    blur : function(ev) {    
      if (this.openend) {
        //window.setTimeout(this.close.bind(this),1000);
      } else if (!this.complete) {
        var elem = this;
      
         if (elem.alive) 
           new Ajax.Request(elem.url, { 
             onSuccess: function(req,header) { if (!elem.openend) eval(req.responseText); },
             method:"post",
             asynchronous:false,
             contentType:"application/x-www-form-urlencoded; charset=UTF-8",
             parameters:"elem="+elem.field.name+"&"+elem.field.name+"="+encodeURIComponent(elem.field.value) });         
       
      }
    },
    
    nomatch : function() {
      if (!this.altMode && this.retest) { this.retest = false; this.nameMode();}
      else if (this.altMode && this.retest) { this.retest = false; this.codeMode();}     
      else {      
        this.optiondiv.innerHTML="No matches";
        this.footer();
      }
    }
    
                  
  });
  
  RClient.Selectable = Class.create();
  RClient.Selectable.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function() {document.itvtActive++;}
    
  });
  
  RClient.SelectionGroup = Class.create();
  RClient.SelectionGroup.prototype = {
  
    initialize : function() {}
    
  }
  
  RClient.DragServer = Class.create();
  RClient.DragServer.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function() {
      document.itvtActive++;
      this.targets = [];
      
    },
    
    gc : function() {
      var olds = this.targets.length;
      this.targets = this.targets.findAll(function(elem) { return elem.active; });           
    },
    
    addTarget : function(target) {      
      this.targets[this.targets.length] = target;
    },
    
    getTargetsOfType : function(type) {
      return this.targets.findAll(function(elem) { return elem.type == type; });
    }
    
        
  });
  
  RClient.DragItem = Class.create();
  RClient.DragItem.prototype = Object.extend(new RClient.ElementComponent(),{
  
    initialize : function(node, dragname, sourceid, itemid, type) {
      document.itvtActive++;
      this.node = node;
      this.dragname = dragname;
      this.triggernode = dragname;
      this.sourceid = sourceid;
      this.itemid = itemid;
      this.type = type;
    },
    
    enable : function() {
      var mytrigger = $(this.dragname);
      mytrigger.style.cursor="move";
      this.observe(mytrigger,"mousedown",this.beginmove.bindAsEventListener(this));
    },
    
    disable : function() {
      this.stopObservingAll();
      mytrigger.style.cursor = null;
    },
    
    beginmove : function(ev) {
      if (ev.button && ev.button!=1) return true;
      //ev.cancelBubble = true;      
      var ac = new RClient.DragAction(Event.pointerX(ev),Event.pointerY(ev), this);
      return false;
    },
    
    cloneto : function(target) {
      var r = new RClient.DragItem($(target.key),$(target.key),target.key,"",this.type);
      r.enable();
      return r;
    }
                 
    
  });
  
  RClient.DragTarget = Class.create();
  RClient.DragTarget.prototype = Object.extend(new RClient.ElementComponent(),{
  
     initialize : function(node,id,type,url,code,highlight,preview) {
       document.itvtActive++;
       this.node = node;
       this.id = id;
       this.type = type;
       this.url = url;
       this.active = true;
       this.highlight = highlight;
       this.preview = preview;    
       if (!code) this.code = "ev.action()"; else this.code = code;
     },
     
     _destroy : function() {
       this.active = false;
     },
     
     cloneto : function(target) {
       var r = new RClient.DragTarget($(target.key),target.key,this.type,this.url,this.code);
       r.isclone = "ISCLONE";
       window.desktop.dragserver.addTarget(r);
       return r;
     },
     
     dopreview : function() {
       if (this.preview) {
         this.preveffect = Effects.run(this.node,this.preview);
       }
     },
     
     unpreview : function() {
       if (this.preveffect) {
         this.preveffect.end();
         this.preveffect = null;
       }
     }
                    
  });
  
  RClient.DragAction = Class.create();
  RClient.DragAction.prototype = {
  
     initialize : function(x,y,trigger_item) {
       this.items = [];
       this.mouse_x = x;
       this.mouse_y = y;
       this.trigger_item = trigger_item;
       this.active = false;
       this.targets = null;
       this.type = trigger_item.type;
       this.moved = true;
       this.previewed = null;
       
       var dnd = window.itvtdnd;
       dnd.up = this.end.bindAsEventListener(this);
       dnd.move = this.move.bindAsEventListener(this);          
     },

     begin : function() {
       var f = new RClient.DragForm(this.trigger_item);
       f.create();
       this.items[0] = f;       
       this.targets = window.desktop.dragserver.getTargetsOfType(this.type);
       this.targets.each(function(elem) { if (elem.highlight) Effects.run(elem.node, elem.highlight); });   
       this.targetchecker = new PeriodicalExecuter(this.preview.bind(this),0.3);
     },
           
     move : function(ev) {       
       var dx = Event.pointerX(ev) - this.mouse_x;
       var dy = Event.pointerY(ev) - this.mouse_y;
       if (!this.active) {   
         if (Math.abs(dx)>5) this.active = true;
         if (Math.abs(dy)>5) this.active = true;
         if (!this.active) return;
         this.begin();
       }
       this.items.each(function(elem) { elem.move(dx,dy); });
       this.moved = true;
       if (this.previewed) {
         this.previewed.unpreview();
         this.previewed = null;
       }
     },
     
     preview : function() {
        if (!this.moved) {
          var div = this.items.first().divplane;
          var x = xc(div,"preview");
          var wx = div.offsetWidth;
          var y = yc(div);
          var wy = div.offsetHeight;             
          var target = this.findtarget(this.type,x,y,wx,wy);            
          if (target) {
            if (target!=this.previewed) {
              if (this.previewed) this.previewed.unpreview();
              this.previewed = target;            
              this.previewed.dopreview();
            }            
          } else if (this.previewed) {
            this.previewed.unpreview();
            this.previewed = null;
          }    
          this.moved = true;      
        } else this.moved = false;
     },
     
     end : function(ev) {      
       var dnd = window.itvtdnd;
       dnd.up = null;
       dnd.move = null;
       if (!this.active) return;
       if (this.targetchecker) {
         this.targetchecker.stop();
         this.targetchecker = null;
       }
       var aobj = aocall(this.trigger_item.node);
       var div = this.items.first().divplane;
       var x = xc(div,"end");
       var wx = div.offsetWidth;
       var y = yc(div);
       var wy = div.offsetHeight;
             
       var target = this.findtarget(this.type,x,y,wx,wy);    
      
       this.items.each(function(elem) { elem.dispose(); });
      
       if (target!=null) {
         Effects.endAll();
         var extramsg="";
         var tnode = $(target.node);
         var container = null;
         if (aocall(tnode.id)) container = aocall(tnode.id).itvtcontainer;   
         if (container==null) container = aobj.itvtcontainer;   
         if (container) {
           var celem = $(container);       
           var xc1 = xc(celem,"end2");
           var yc1 = yc(celem);
           extramsg="&x="+(x-xc1)+"&y="+(y-yc1);
         }
         
         for (var i=0;i<this.items.length;i++) {
           var di = this.items[i].item;
           var de = new AjaxObjects.DragEvent(aocall(tnode.id),target.url,"source="+di.sourceid+"&item="+di.itemid+"&target="+target.id+"&type="+di.type+"&event=dragdrop"+extramsg);
           de.trigger(target.code);
         }
    
       } else Effects.endAll();
       
       this.items.clear();
     },
     
     
     findtarget : function(t,x,y,xs,ys) {
        var targets = window.desktop.dragserver.getTargetsOfType(this.type);
        var score = 50000000;
        var r = null;
        var xm = x+xs/2;
        var ym = y+ys/2;
        for (var i=targets.length-1;i>=0;i--) {
          if (targets[i].active) {
           var elem = $(targets[i].node);      
           // if (!elem) debugwin(targets[i]);
           var x2 = xc(elem,"findtarget");
           var y2 = yc(elem);           
           if (x+xs>=x2 && y+ys>=y2 && x<=x2 + elem.offsetWidth && y<=y2 + elem.offsetHeight) {                
             var deltaX = Math.abs(xm-x2-elem.offsetWidth/2)/(elem.offsetWidth+xs);
             var deltaY = Math.abs(ym-y2-elem.offsetHeight/2)/(elem.offsetHeight+ys);           
             var newscore = elem.offsetHeight * elem.offsetWidth + 100000 * deltaX * deltaY;
             if (newscore<score) {
               score = newscore;
               r = targets[i];
             }
           }
          }
        }
        return r;        
    }
            
  }
  
  RClient.DragForm = Class.create();
  RClient.DragForm.prototype = {
  
    initialize : function(item) {
      this.item = item;
      this.divplane = null;
    },
    
    create : function() {
      var mycontainer = $(this.item.node);
      this.xpos = xc(mycontainer,"create");
      this.ypos = yc(mycontainer);
      
      var divplane = document.createElement("div");
      divplane.innerHTML = "<div>"+mycontainer.innerHTML+"</div>";   
      //divplane.className=mycontainer.className;
      divplane.style.width=(2+mycontainer.offsetWidth)+"px";
      divplane.style.height=(2+mycontainer.offsetHeight)+"px";     
      divplane.style.position='absolute';
      divplane.style.zIndex = 100;
      divplane.style.left=this.xpos+"px";
      divplane.style.top=this.ypos+"px";
      divplane.style.border="1px solid black";
      divplane.style.padding="3px 3px 3px 3px";
      divplane.style.backgroundColor="#A0A0A0";
      divplane.style.filter="alpha(opacity=70)";
      divplane.style.MozOpacity=0.7;
      divplane.style.KhtmlOpacity=0.7;
      divplane.style.opacity=0.7;
      this.divplane = divplane;
      document.getElementsByTagName('body')[0].appendChild(divplane);
    },
    
    dispose : function() {
      if (!this.divplane) return;
      this.divplane.display='none';
      document.getElementsByTagName("body")[0].removeChild(this.divplane);            
      this.divplane = null;    
    },
    
    move : function(dx,dy) {
       this.divplane.style.left = (this.xpos + dx)+"px";
       this.divplane.style.top = (this.ypos + dy)+"px";    
    }
    
  }
  
  RClient.Effect = Class.create();
  RClient.Effect.prototype = {
  
    initialize : function() {},
    
    begin : function() {},
    
    abort : function() {}
            
  }
  
  RClient.StyleEffect = Class.create();
  RClient.StyleEffect.prototype = {
  
    initialize : function(cssstyle) {     
      this.cssstyle = cssstyle;      
    },
    
    begin : function() {
      Element.addClassName(this.node,this.cssstyle);
    },
    
    end : function() { this.abort(); },
    
    abort : function() {
      Element.removeClassName(this.node,this.cssstyle);
    },
  
    copy : function() { return Object.clone(this); }
  }
  
  RClient.CSSChangeEffect = Class.create();
  RClient.CSSChangeEffect.prototype = {
  
    initialize : function(css,target) {     
      this.css  = css;      
      this.target = target;
    },
    
    begin : function() {   
      if (this.target=='') this.node.style.removeAttribute(this.css,false);
      else this.node.style[this.css] = this.target;
      this.finished = true;
    },
    
    end : function() { this.abort(); },
    
    animate : function() {},
    
    abort : function() {},
  
    copy : function() { return Object.clone(this); }
  }
  
  RClient.HighlightEffect = Class.create();
  RClient.HighlightEffect.prototype = {
  
    initialize : function(tstyle) {     
      this.tstyle  = tstyle;      
    },
    
    begin : function() {   
      this.node = $(this.node);
      if (this.node) {
      if (this.node.itvtobj) this.pview = this.node.itvtobj.pview;
      if (this.node.nodeName=="SPAN" || this.node.style.display=='inline' || this.node.className=='inline') this.node = findParent(this.node,"DIV");
      var neu1 = document.createElement("div");
      neu1.style.position="relative";
      var neu = document.createElement("div");
      neu.className=this.tstyle;
      neu.style.height=(this.node.offsetHeight)+"px";
      neu.style.width=(this.node.offsetWidth)+"px";
      neu.style.position="absolute";
      neu1.appendChild(neu);
      if (this.node.firstChild) this.node.insertBefore(neu1,this.node.firstChild);  
      else this.node.appendChild(neu1);
      this.mynode=neu1;
      }
      this.finished = true;
    },
    
    animate : function() {},
    
    end : function() { 
      if (this.pview) {
        var ani = new RClient.ShrinkEffect(10);
        ani.node = this.mynode.firstChild;  
        this.pview.addSub(new RClient.AnimationThread(ani));          
      } else this.abort();
    },
    
    abort : function() {
     if (this.node && this.mynode) {
        this.node.removeChild(this.mynode);
        this.mynode = null;
     }
    },
  
    copy : function() { return Object.clone(this); }
  }

  Effects = {
 
     running : [],
     
     ended : [],
     
     effect : {},
     
     run : function(node,effectid) {
       var ef = Effects.effect[effectid].copy();
       ef.node = node;
       ef.begin();
       this.running[this.running.length] = ef;
       return ef;
     },
 
     cancelAll : function() {
       this.ended.each(function(elem) { elem.abort(); });
       this.running.each(function(elem) { elem.abort(); });
       this.running.clear();
     },   
     
     endAll : function() {
       this.ended.each(function(elem) { elem.abort(); });
       this.ended.clear();
       this.ended = this.running;
       this.ended.each(function(elem) { elem.end(); });       
       this.running = [];
     }  

  }  
  

  Effects.effect['highlight'] = new RClient.HighlightEffect('nhighlight');  
  Effects.effect['hlinline'] = new RClient.StyleEffect('hlinline');
  Effects.effect['preview'] = new RClient.HighlightEffect('npreview');
  Effects.effect['previewframe'] = new RClient.StyleEffect('previewframe');
  Effects.effect['highlightframe'] = new RClient.StyleEffect('highlightframe');
  
 function makeTarget(divname, id, types, url,pview) {
   if (!window.itvtdnd) dragdropinit();
   var aobj = aocall(divname);
   if (aobj == null) aobj = check_object(divname,null,pview);
   
   var mynode = document.getElementById(divname);
   var dnd = window.itvtdnd;
   var t = types.split(",");
   for (var i=0;i<t.length;i++) {      
     if (!mynode.id) mynode.id="id"+(globid++);
     var target = new RClient.DragTarget(mynode.id,id,t[i],url);
     aobj.addSub(target);
     if (!aobj.isbehavior) window.desktop.dragserver.addTarget(target);
   }
 }
 
 
 function makeItem(divname, dragname, sourceid, itemid, type,pview) {
   if (!window.itvtdnd) dragdropinit();
   
   var aobj = aocall(divname);
   if (aobj == null) aobj = check_object(divname,null,pview);
   var di = new RClient.DragItem(divname,dragname,sourceid,itemid,type);
   aobj.addSub(di);

   if (!aobj.isbehavior) { di.enable(); }
      
 }
 

  
  
      

   RClient.View = Class.create();
   RClient.View.prototype = Object.extend(new RClient.ElementComponent(), {
     
     initialize : function() {                     
        this.inits = [];
        this.groups = [];
        this.named = {};
        this.cs = [];
        this.ca = null;     
        this.inited = false;
        this.debuginfo="VIEW";
     },
     
     add : function(elem) { this.addSub(elem); },
     
     addInit : function(key) {    
       if (this.inited) tr_init(key); else {
         this.inits[this.inits.length] = function() { tr_init(key); };
       }
     },
     
     addGroup : function(key,elem) {     
       if (!this.groups[key]) this.groups[key] = [];
       this.groups[key].push(elem);
     },
     
     forgroup : function(key,f) {
       this.groups[key].each(f);
     },
     
     doInit : function() {           
       document.itvtActive++;
       this.inited = true;
       this.inits.each(function(elem) { elem(); });       
       this.inits.clear();
     },
     
     mapput : function(key,obj) {    
       this.named[key] = obj;
     },
     
     mapget : function(key) {    
       return this.named[key];
     },
          
     adds : function(elem) {
      this.cs.push(elem);
      this.ca = elem;
      return elem;
     },
     
     rems : function() {
      this.cs.pop();
      this.ca = this.cs.length > 0 ? this.cs.last() : null;
     },
     
     _destroy : function() {
       // debugwin(this);
       Effects.cancelAll();
       window.desktop.dragserver.gc();
       this.inited = false;
       this.groups = [];
       this.named = {};
       
       this.cs = [];
       this.ca = null;     
     }
     
   });
   
   RClient.Desktop = Class.create();
   RClient.Desktop.prototype = Object.extend(new RClient.View(), {
   
      initialize : function() {
        document.itvtActive++;
        this.inits = [];
        this.debuginfo="Desktop";
        this.windowgroup = new RClient.Group();
        this.addSub(this.dragserver = new RClient.DragServer(this));
      },
      
      makeView : function(pview,divid) {
        var v = new RClient.View();
        $(divid).view = v;
        pview.last().addSub(v);
      },
      
      createWindow : function(x,y,w,h) {
        var whtml = document.createElement("div");        
        whtml.innerHTML = '<table class="win titlebar" cellspacing=0 cellpadding=0><tr><td colspan="3"></td></tr><tr><td></td><td class="content"><div class="winhead">Title 1</div><div class="wincontent"></div></td><td></td></tr><tr><td colspan="2"></td><td></td></tr></table>';
        document.getElementsByTagName("body")[0].appendChild(whtml);
        whtml.className="win";
        var win = new RClient.VWindow(whtml,this);
        this.addSub(win);
        win.setPos(x,y);
        win.setSize(w,h);
        win.setTitle("Hello world");
        win.load("/erfx/test/dom.jsp");
        return win;
      },
      
      relayout : function() {
        this.layoutroot.layout(this.layoutroot.fetch());
      }
   });
    

 var AjaxObjects = Class.create();
 
 AjaxObjects.TransactionStep = Class.create();
 AjaxObjects.TransactionStep.prototype = {
 
   initialize : function(node,code) { 
     this.node = node;
     this.code = code;
   },
      
   exec : function() { 
     var node = this.node;
     eval(this.code); 
   }
   
 }
 
 AjaxObjects.Transaction = Class.create();
 AjaxObjects.Transaction.prototype = {
 
   initialize : function() {
     this.rollbacks = [];
     this.rbcount = 0;
   },
    
   addRB : function(n,c) { 
     this.rollbacks[this.rbcount] = new AjaxObjects.TransactionStep(n,c);
     this.rbcount++;
   },
   
   rollback : function() { 
     for (var i=this.rbcount-1;i>=0;i--) this.rollbacks[i].exec(); 
   },
   
   commit : function() { 
     this.rollbacks = [];
     rbcount=0; 
   }
 
 }
 
 
 AjaxObjects.AjaxObject = Class.create();
 AjaxObjects.AjaxObject.prototype = Object.extend(new RClient.ElementComponent(), {
 
   initialize : function(htmlnode,viewer,pview) {
     document.itvtActive++;
     this.key = htmlnode;
     this.viewer = viewer;     
     this.pview = pview;
   },
 
   obj : function() { 
     return document.getElementById(this.key); 
   },
   
   ao : function() {
     return this;
   },
 
   setContent : function(c,t) { 
    if (t) t.addRB(this,"node.obj().innerHTML=\""+this.obj().innerHTML+"\";");
    this.obj().innerHTML = c; 
   },
 
   setStyle : function(s,t) {
    if (t) t.addRB(this,"node.obj().className=\""+this.obj().className+"\";");
    this.obj().className = s;
   },
   
   addStyle : function(s,t) {
    if (t) t.addRB(this,"node.obj().removeClassName(\""+s+"\");");
    this.obj().addClassName(s);
   },
   
   removeStyle : function(s,t) {
     if (t) t.addRB(this,"node.obj().addClassName(\""+s+"\");");
     this.obj().removeClassName(s);
   },
 
   setVisible :function(s,t) {   
    if (t) t.addRB(this,"node.obj().style.display=\""+this.obj().style.display+"\";");
    if (s) {
      if (this.obj().type=='input') this.obj().style.display='inline';
      else if (this.obj().nodeName=='TBODY') {this.obj().style.display='';} else this.obj().style.display='block';
    } else this.obj().style.display = 'none';
   },
 
   setFormValue : function(v,t) {
    var elem = Element.down(this.obj(),"input");
    if (elem) {
      if (t) t.addRB(this,"Element.down(node.obj(),'input').value='"+elem.value+"';");
      elem.value = v;
    }
   },
 
   setValue : function(v,t) {
    if (this.obj().nodeName=='SPAN') {
      if (t) t.addRB(this,"this.obj().innerHTML='"+this.obj().innerHTML+"';");    
      this.obj().innerHTML = v;
    } else {
      if (t) t.addRB(this,"this.obj().value='"+this.obj().value+"';");
      this.obj().value = v;
    }
  },
  
  clearValue : function(t) {
    if (this.obj().nodeName=='SPAN') {
      if (t) t.addRB(this,"this.obj().innerHTML='"+this.obj().innerHTML+"';");    
      this.obj().innerHTML = '';
    } else if (this.obj().nodeName=='SELECT') {     
      if (t) t.addRB(this,"this.obj().selectedIndex='"+this.obj().selectedIndex+"';");
      this.obj().selectedIndex = 0;
      if (this.obj().onchange) this.obj().onchange();
    } else {
      if (t) t.addRB(this,"this.obj().value='"+this.obj().value+"';");
      this.obj().value = '';
    }
  
  },
 
  setDisabled : function(b,t) {
   if (t) t.addRB(this,"node.obj().disabled="+this.obj.disabled+";");
   this.obj().disabled = b;
   this.disabled = b;
  },
 
  getValue : function() {
   if (this.obj().nodeName=='SPAN') { 
     if (this.obj().val) return this.obj().val;
     return this.obj().innerHTML; 
   }
   return this.obj().value;
  },
 
  setSelected : function(s,t) {
    if (t) t.addRB(this,"node.obj().selectedIndex="+this.obj().selectedIndex+";");
    this.obj().selectedIndex = s;
  },
  
  click : function() {
    this.obj().click();
  },
  
  trigger : function() {
    tr_trigger(this.obj().id);
  },
   
  moveInto : function(cntid,t) {
     this.container_delete(this.itvtcontainer);
     this.container_create(cntid);  
  },
 
  swapWith : function(obj2,t) {
    if (obj2==this) return;
    if (this.itvtcontainer == obj2.itvtcontainer) {
       aocall(this.itvtcontainer).container_swap(this,obj2);
    } else {
       var cnt1 = aocall(this.itvtcontainer);
       var cnt2 = aocall(obj2.itvtcontainer);
       cnt1.container_delete(this);
       cnt2.container_delete(obj2);
       cnt1.container_create(obj2);
       cnt2.container_create(this);
    } 
  },
 
   
  setLeft : function(x) {
   this.obj().style.left = x+"px";
  },
 
  setTop : function(y) {
   this.obj().style.top = y+"px";
  },
 
  openMenu : function(itemid) {
    var menuname = this.obj().id+"m";
    ctxMenu(menuname,this.obj().id,itemid);               
    if (window.itvtdnd.menuOpen!=null) menuclose();
    ctxshow(document.getElementById(menuname),this.obj());
    this.obj().itvtctxmenu = document.getElementById(menuname);
    window.itvtdnd.menuOpen=this.obj();
   },
 
   setBehavior : function(n,t) {
     var behav = null;
     if (globalbehavior) behav = globalbehavior[n];
     if (!behav) behav = this.find("behavior",n);
   if (t) t.addRB(this,"node.behavior='"+node.behavior+"';handlers();");
   if (behav) {
     this.behavior = behav;
     this.handlers();
   }
  },
 
  setRowVisibility : function(n,t) {
   var canSeeTR = (navigator.appName.indexOf("Microsoft")>-1) ? "block" : "table-row";
   var tr = findParent(this.obj(),"TR");
   if (tr) tr.style.display = n ? canSeeTR : "none";
  },
  
  setRowStyle : function(s,t) {
   var tr = findParent(this.obj(),"TR");
   if (tr) tr.className = s;
  },
 
  cancel : function() {
   throw "cancel";
  },
 
 handlers : function() {
   if (this.onclick_code || this.onclick_path || (this.behavior && (this.behavior.onclick_code || this.behavior.onclick_path))) {
     this.obj().onclick = tr_click;
   } else {
     this.obj().onclick = null;
   }
   
   if (this.ondblclick_code || this.ondblclick_path || (this.behavior && (this.behavior.ondblclick_code || this.behavior.ondblclick_path))) {
     this.obj().ondblclick = tr_dblclick;
   } else {
     this.obj().ondblclick = null;
   }
   
   var h = null;
   if (this.obj().onchange && this.obj().onchange!=tr_onchange) {
     h = this.obj().onchange_old = this.obj().onchange;
   }
   if (this.onchange_code || this.onchange_path || (this.behavior && (this.behavior.onchange_code || this.behavior.onchange_path))) {
     this.obj().onchange = tr_onchange;
   } else {
     this.obj().onchange = h;
   }

   h = null;
   if (this.obj().onkeyup && this.obj().onkeyup!=tr_onkeyup) {
     h = this.obj().onkeyup_old = this.obj().onkeyup;
   }
   if (this.onkeyup_code || this.onkeyup_path || (this.behavior && (this.behavior.onkeyup_code || this.behavior.onkeyup_path))) {
     this.obj().onkeyup = tr_onkeyup;
   } else {
     this.obj().onkeyup = h;
   }

   h = null;
   if (this.obj().onfocus && this.obj().onfocus!=tr_onfocus) {
     h = this.obj().onfocus_old = this.obj().onfocus;
   }
   if (this.onfocus_code || this.onfocus_path || (this.behavior && (this.behavior.onfocus_code || this.behavior.onfocus_path))) {
     this.obj().onfocus = tr_onfocus;
   } else {
     this.obj().onfocus = h;
   }
   
   h = null;
   if (this.obj().onblur && this.obj().onblur!=tr_onblur) {
     h = this.obj().onblur_old = this.obj().onblur;
   }
   if (this.onblur_code || this.onblur_path || (this.behavior && (this.behavior.onblur_code || this.behavior.onblur_path))) {
     this.obj().onblur = tr_onblur;
   } else {
     this.obj().onblur = h;
   }

   
   /*if (this.dragitem_type || (this.behavior && this.behavior.dragitem_type)) {
      this.obj().style.cursor="move";
      if (!this.dragitem_sourceid) {
        this.dragitem_sourceid = this.key;
        this.dragitem_itemid = "";
      }
      this.obj().onmousedown=dndbegin_bridge;     
   } else {
      this.obj().onmousedown=null;
   }*/
   
   if (this.onctxmenu_path || (this.behavior && this.behavior.onctxmenu_path)) {
      this.obj().oncontextmenu = openctxfunc;
   } else {
      this.obj().oncontextmenu = null;
   }
   
   /*if (this.behavior && this.behavior.targets) {
     if (!window.itvtdnd) dragdropinit();
     var dnd = window.itvtdnd;
     for (var i=0;i<dnd.targets.length;i++) {
       if (dnd.targets[i].frombehavior && dnd.targets[i].node == this.key) {
         dnd.targets[i] = null;
       }
     }   
       
     for (var i=0;i<this.behavior.targets.length;i++) {
       var target = this.behavior.targets[i];
       mk_target(this.key,target.types,target.itvtcode,target.url);
     }
   }*/
   
   if (this.behavior && this.behavior.oninit_code) {
     this.pview.addInit(this.key);
   }
   
   if (this.behavior) {
     if (this.behavior.onpreinit_code) {
       tr_preinit(this.key);
     }
     var subs = this.behavior.getSubcomponents();
     var that = this;
     subs.each(function(elem) { if (elem.cloneto) that.addSub(elem.cloneto(that)); });
   }
  },
  
    
   find : function(a,b) { 
     if (!b) b="";
     var ob = document.getElementById("o"+this.viewer+"_"+a+"_"+b);
     if (ob!=null) return ob.itvtobj; else alert("not found:"+a+"_"+b);
   },
 
   findrel : function(a,b) { 
     var idx = Number(this.subid());
     var ob = document.getElementById("o"+this.viewer+"_"+a+"_"+(idx+b));
     if (ob!=null) return ob.itvtobj; else return null;
   },

   subid : function() { 
     var parts = this.key.split("_");
     var r = parts[parts.length-1];  
     return r;
   },
   
   join : function(group) {
     this.pview.addGroup(group,this);
   },
   
   forall : function(group,func) {
     this.pview.forgroup(group,func);
   },
   
   play : function(effectname) {
     var effect = this.pview.mapget(effectname);
     if (!effect) {    
      Effects.run(this.obj(),effectname);
     } else {    
      effect = effect.copy();
      effect.node = this.obj();     
      this.addSub(new RClient.AnimationThread(effect));
     }
   },
   
   playOnID : function(effectname,divid) {
     var effect = this.pview.mapget(effectname);
     if (!effect) {    
      Effects.run($(divid),effectname);
     } else {    
      effect = effect.copy();
      effect.node = $(divid);     
      this.addSub(new RClient.AnimationThread(effect));
     }
   },
   
   moveTo : function(divid) {
     var div = $(divid);
     if (div) {
       this.obj().parentNode.removeChild(this.obj());
       div.appendChild(this.obj());
     }
   },
   
   _destroy : function() {
     var o = this.obj();
     if (o) {
       o.onclick = null;
       o.onmousedown = null;
       o.onmouseup = null;
       o.onchange = null;
       o.onfocus = null;
       o.onblur = null;
       o.onkeyup = null;
       o.oncontextmenu = null;
       o.itvtobj = null;
     }     
   }
 });

 function FarbButtondisable(b,t) {
    var el = this.obj();  
    el.className=el.className.substr(0,el.className.length-1)+(b?"0":"1");    
    this.disabled = b;
 }

 function checkbox_setValue(v,t) {
    if (t) t.addRB(this,"node.obj().checked="+this.obj().checked+";");
    this.obj().checked = v;
 }
 
 function checkbox_getValue() { 
    return this.obj().checked;
 }
 
 
 function AjaxObjectList() {
 }
 
 AjaxObjects.AjaxEventHandler = Class.create();
 AjaxObjects.AjaxEventHandler.prototype = {
   
   initialize : function(code,path) {
     this.code = code;
     this.path = path;
   }
   
 };
 
 AjaxObjects.AjaxEvent = Class.create();
 AjaxObjects.AjaxEvent.prototype = {
 
   initialize : function (type,source) {
      this.event = type;
      this.source = source;
      this.path = null;
   },
  
   action : function(param) {
     ajax(this.path,"source="+this.source.key+"&event="+this.event+(param!=null ? "&"+param : ""));  
   },      
  
   ajaxsubmit : function() {
     var formname = "form"+this.source.viewer;
     document.forms[formname].action.value = null;   
     ajax(this.path,"formdata=true&source="+this.source.key+"&event="+this.event+"&"+postform(document.forms[formname]));
   },
 
   trigger : function(handler) {
     this.path = handler.path;
     with (this.source) {
       var ev = this;    
       var source = this.source;
       try { eval(handler.code); } catch(e) { dbg("Error in AjaxEvent.trigger:"+e); }
     }
   }
   
 }
 
 AjaxObjects.DragEvent = Class.create();
 AjaxObjects.DragEvent.prototype = {
 
   initialize : function(source,path,pathparam) {
     this.event = "dragdrop";
     this.source = source;
     this.path = path;
     this.pathparam = pathparam;
   },
  
   action : function() {  
     ajax(this.path,this.pathparam);  
   },
   
   ajaxsubmit : function() {
     var formname = "form"+this.source.viewer;
     document.forms[formname].action.value = null;   
     ajax(this.path,this.pathparam+"&formdata=true&"+postform(document.forms[formname]));
   },
   
   trigger : function(code) {  
     with (this.source) {
       var ev = this;    
       var source = this.source;   
       eval(code);
     }
   }
 }
  

 function DP() {
 
 }
 
 DP.prototype = {

  tracking : function(elem,startchanged,pview) {
    elem = document.getElementById(elem);
    pview.last().observe(elem,"keyup",this.tracking_keypress.bindAsEventListener(elem));
    pview.last().observe(elem,"change",this.tracking_keypress.bindAsEventListener(elem));
    if (startchanged) elem.className = "changed"; else elem.className="unchanged";
  },
  
  tracking_keypress : function(ev) {
     if (ev.keyCode!=9 && this.className=="unchanged") this.className = "changed";
  },
  
  vg : function(elem,value,pview) {
    elem = document.getElementById(elem);
    pview.last().observe(elem,"focus",(function(ev) {
      if (this.value=='') { this.value=value;this.select(); }
    }).bindAsEventListener(elem));
  },
  
  vgs : function(elem,value,pview) {
    elem = document.getElementById(elem);
    pview.last().observe(elem,"mousedown",(function(ev) {
      if (this.selectedIndex==0) guesspick(this,value);
    }).bindAsEventListener(elem));
  },
  
  hybrid : function(elem,url,pview) {
    var ht = new RClient.HybridTag(elem,url);
    pview.last().addSub(ht);
  },
  
  codename : function(elem,url,pview) {
    var ht = new RClient.DoubleHybridField(elem,url);
    pview.last().addSub(ht);
  },
  
  check : function(elem,isoptional,errkey,pview)  {
    try {
    var x = new RClient.FormElement(elem,isoptional,errkey);
    pview.last().addSub(x);
    } catch (e) { dbg("Error in DP.check:"+e.message); }
  },
  
  showerr : function(f,key,msg) {
    $(f).itvtform.setError(key,msg);
  },
  
  regform : function(xform,pview) {
    var x = new RClient.Form(xform);
    pview.last().addSub(x);
  },
    
  autosubmit : function(elem,pview) {
    elem = $(elem);
    pview.last().observe(elem,"change",(function(ev) {
       this.form["action"].value="_autosubmit";
       this.form.submit();
    }).bindAsEventListener(elem));
  },
  
  extselect : function(elem,mode,trigger,pview) {
    elem = $(elem);
    pview.last().observe(elem,"change",(function(ev) {
      seltrigger(this,mode,trigger);
    }).bindAsEventListener(elem));
  },
  
  animate : function(elem,effect,pview) {   
   var ef = pview.last().mapget(effect);
   if (!ef) ef = Effects.effect[effect]; 
   ef = ef.copy();
   ef.node = $(elem);
   pview.last().addSub(new RClient.AnimationThread(ef));
  },
  
  fadeout : function(elem,pview) {
    var ani = new RClient.FadeEffect(1,0,5);
    ani.node = $(elem);  
    pview.addSub(new RClient.AnimationThread(ani));    
  }
   
    
};
  

 var globid = new Date().getTime();

 function root(x) {
   var r = root2(x);
   return r!=null ? r : x.top;
 }
 
 function dbg(x) {
   try {
    root(window).appcontrol.debug(x);
   } catch (e) {}
 }
 
 var loads = new Array();
 var refreshes = new Array();

 function pageLoad() { 
   window.framecontrol.onload();   
 }  
 
 function execArrayImpl(a,divid) {      
   var pview = [$(divid).view];    
   var dp = new DP();
   for (var i=0;i<a.length;i++) {dbg(a[i]);eval(a[i]);}
   pview[0].doInit();
   checkIEscrollbarbug();
 }
 
 function checkIEscrollbarbug() {
    var b = document.getElementsByTagName("body")[0];
    var d = document.getElementsByTagName("html")[0];
    if (!b || !d) return;
    if (b.offsetHeight > d.offsetHeight) {     
     d.style.overflowY = 'scroll';
    } else {     
     d.style.overflowY = 'auto';
    }
 }

 var duringresize = false;
 
 function refreshAll() {     
    // debugwin();
    if (!duringresize) {
      duringresize = true;
      window.setTimeout("refreshAll2()",100); 
    }
 }
 
 function refreshAll2() { 
   for (var i=0;i<refreshes.length;i++) eval(refreshes[i]);   
   duringresize = false;
 }
 
 function afterLoad(x) { loads[loads.length] = x; }
 function afterResize(x) { refreshes[refreshes.length] = x; }

 function root2(x) {  
     if (x.ismainwindow) return x;
     try {
       if (x.parent && x.parent!=x) return root2(x.parent);
     } catch(e) {}       
     try {
       if (x.opener) { 
         return root2(x.opener);    
       }
     } catch(e) { return x.top; }       
     return null;  
  }
  
  function ismain(x) {
    if (x.ismainwindow) return true;
    try {
      if (x.parent && x.parent!=x) return ismain(x.parent);
    } catch (e) { return false; }
    return false;
  }

function clstore(x) { 
  var storewin = root(x); 
  storewin.storage = new Object(); 
  // while (!ismain(x) && x.opener) { storewindow(storewin,x); x = x.opener; } 
  // storerec(storewin,storewin);
}

function storerec(storewin,win) { 
  storewindow(storewin,win);
  if (win && win.frames) {
    for (var fr=0;fr<win.frames.length;fr++) {
      if (win.frames[fr]) storerec(storewin,win.frames[fr]);
    }
  }
}

function storewindow(storewin,win) {   
  if (win && win.document && win.document.forms) {  
    for (var f=0;f<win.document.forms.length;f++) {   
      storeform(storewin,win.document.forms[f]);
    }
  }  
}

function storeform(storewin,x) {
 var keyname;
 if (x.clkfrm && x.clkfrm.value) {
   keyname = x.clkfrm.value;
 } else {
   //confirm("Debug:storeform bad form");
   return;
 }
  //confirm("Debug: storeing "+keyname);
  storewin.storage[keyname] = new Object();
  var st = storewin.storage[keyname];
  if (x.elements.length < 500) {
  for (var i=0;i<x.elements.length;i++) {
    if (x.elements[i]) { 
      var ce = x.elements[i];
      if (!st[ce.name]) {st[ce.name] = new Object();}
      st[ce.name].type=ce.type;
      if (ce.type=="text" || ce.type=="hidden" || ce.type=="textarea") {   
          st[ce.name].value=x.elements[i].value;    
      } else if (x.elements[i].type=="select-one") { 
          st[ce.name].selectedIndex=ce.selectedIndex;       
      } else if (x.elements[i].type=="radio" || ce.type=="checkbox") {
          st[ce.name][ce.value]=ce.checked;
      }
    }
  }
 }
 //confirm("Debug:storeing done");
}

function recallwin(win,filterkey) {
  //confirm("Debug:Recalling user data for "+filterkey);
  if (win.document.forms) {
    for (var fr=0;fr<win.document.forms.length;fr++) {
      if (win.document.forms[fr].clkfrm) {
        var keyname = win.document.forms[fr].clkfrm.value;
        if (keyname==filterkey) {recallform(win,win.document.forms[fr],keyname);}
      }
    }
  }
 //confirm("Debug:Recalling done for "+filterkey);
}

function recallform(win,x,keyname) { 
  var storewin = root(win); 
  try { 
     
  if (storewin && storewin.storage && storewin.storage[keyname]) {     
    var st = storewin.storage[keyname];  
    if (x.elements.length >= 500) { return; }
    for (var i=0;i<x.elements.length;i++) {
      if (x.elements[i]) {
        var ce = x.elements[i];
        var name = ce.name;
        if (name!="clkpos" && name!="clkfrm" && name!="clkrev" && storewin.storage[keyname][name]) {
           var dat = st[name];
           if (dat.type=="text" || dat.type=="hidden" || dat.type=="textarea") {            
             if (ce.value!=dat.value && ce.className=="unchanged") ce.className="changed";
             ce.value = dat.value;
           } else if (dat.type=="select-one") {                   
             if (ce.selectedIndex!=dat.selectedIndex && ce.className=="unchanged") ce.className="changed";
             ce.selectedIndex = dat.selectedIndex; 
           } else if (dat.type=="checkbox" || dat.type=="radio") {                       
             ce.checked=dat[ce.value];
           }
         }
      }
    }
  }
  } catch (e) { return; }
}

  function sp(win,limit,pos,max) {        
    if (limit==3) {          
          win.document.getElementById("content2").style.display="none";        
          win.document.getElementById("content").style.display="block"; 
       
          if  (root(win)["sp_lim"+pos]) {           
            limit = (root(win)["sp_lim"+pos])-1;           
          } else { limit = 1; }
          
          pageLoad();
    }   
    if (win.document.body.itvtScrollLock) limit = 0;
    if (limit==2) {        
      limit=1-((root(win)["sp_lim"+pos])-1);      
    }    
       if (max>0) {     
         var m = max;
         var h1 = win.document.getElementById("content");
         var h = h1.offsetHeight;
         var w = h1.offsetWidth;        
         if (w>parent.document.getElementById(pos).width) h = h + 20;           
         if (h==0) { win.setTimeout("spx(3)",100); }      
         if (h>m && limit==1) { h=m; }       
         parent.document.getElementById(pos).setAttribute("height",h);
       }
       root(win)["sp_lim"+pos]=(limit+1);     
    
  }
  
  function spnr(win) {  
          win.document.getElementById("content2").style.display="none";        
          win.document.getElementById("content").style.display="block";           
          pageLoad();    
  }

  function rehide(frame) {  
    frame.framecontrol.lockwindow(0);
    frame.framecontrol.showloadstatus("Contacting server...");
  }
  
  function rehideform(win,target) {  
  }

  function percent(win,msg) {
    var h1 = win.document.getElementById("wprompt");
    if (h1) {
      h1.firstChild.data = "please wait... ("+msg+")";
    }
  }

  function fp(d,s) {
     var p = d.indexOf('value="'+s+'"');
     if (p>0) d = d.substring(0,p)+" selected "+d.substring(p);
     else if (s!=null && s.length>0 && s!="null") d = d+"<option selected value='"+s+"'>"+s+"</option>";
     document.write(d);
  }

 
 function cbs(objn,url) {  
   try {
     document.images[objn].src = url;
   } catch(e) {}
 }
 
 function butenabled(el) {
   return el.className.substr(el.className.length-1)!="0";
 }
 
 function lov(el) {
  try {
    if (butenabled(el)) el.className=el.className.substr(0,el.className.length-1)+"2";
  } catch(e) {}
 }
 
 function lno(el) {  
  try {
    if (butenabled(el)) el.className=el.className.substr(0,el.className.length-1)+"1";
  } catch(e) {}
 }
 
 function lcl(el) { 
  try {
    if (butenabled(el)) el.className=el.className.substr(0,el.className.length-1)+"3";
  } catch(e) {}
 }
 

 function crbutton(txt,col,script) {    
   var id = "button"+globid; globid++;
   var o = "<div id='"+id+"' class='"  
   if (col.substr(0,1)=="l") {
     o+="button"+col+"1'";
   } else {
     o+="button"+col+"1'";
   }
   o+=" onMouseOver=\"lov('"+id+"');\" onMouseOut=\"lno('"+id+"');\" onMouseDown=\"lcl('"+id+"');\" onMouseUp=\""+script+"\">"+txt+"</div>";  
   document.write(o);
 }

 function crbuttonnoani(txt,col,script) {  
   var id = "button"+globid; globid++;
   var o = "<span id='"+id+"' class='"  
   if (col.substr(0,1)=="l") {
     o+="newbutton'";
   } else {
     o+="newbutton2'";
   }
   o+=" onClick=\""+script+"\"><img name='"+id+"' src='"+baseurl+"/img/icons/"+col+"normal.jpg' border=0 class='butgraphic'><span class='inbut'>"+txt+"</span><img src='"+baseurl+"/img/space.gif' width=102 height=1 border=0></span>";
   document.write(o);
 }

 function dcrbutton(txt,col) {
   if (col.substr(0,1)=="l") {
      document.write("<span class='disabled'><img src='"+baseurl+"/img/icons/"+col+"inactive.jpg' border=0 class='butgraphic'><span class='inbut'>"+txt+"</span><img src='"+baseurl+"/img/space.gif' width=102 height=1 border=0></span>");
   } else {
      document.write("<span class='disabled2'><img src='"+baseurl+"/img/icons/"+col+"inactive.jpg' border=0 class='butgraphic'><span class='inbut'>"+txt+"</span><img src='"+baseurl+"/img/space.gif' width=102 height=1 border=0></span>");
   }
 }

 function ed(e,prmt,val,url) {
   if (!e) e = event;
   if (e && (e.ctrlKey || e.shiftKey)) { 
   var w = open("/buttontest.html","editor","height=400, width=600, menubar=no"); 
   w.document.open();  
   w.document.writeln("<html><body><form method=post action=\""+url+"\">"); 
   w.document.writeln("<p>"+prmt+"</p><input type=hidden name=key value='"+prmt+"'><textarea cols=60 rows=18 name='val'>"+val+"</textarea>");
   w.document.writeln("<br><input type=submit value=submit> or close window");
   w.document.writeln("</form></body></html>");
   w.document.close();
   }
 }
 
function spcclk(url,where,event) {
  var nurl = url;
  if (event.altKey) nurl = url+"&altKey=true";
  eval(where).document.location.href = nurl;
}

function subpageclick(elem) {
  var e = document.getElementById("x"+elem);
  if (!e) { 
     var el = document.getElementsByName(elem)[0];
     el.value="true";
     el.form["action"].value = "subpagecmp._subpage";
     el.form.submit();
  } else {
    if (e.style.display=="none") {
       e.style.display = "block";
       document.getElementsByName(elem)[0].value="true";
    } else { 
       e.style.display = "none";
       document.getElementsByName(elem)[0].value="false";
    }
  }
}

function subpageclick2(elem,show) {
  var e = document.getElementById("x"+elem);
  if (!e) { 
     if (!show) return;
     var el = document.getElementsByName(elem)[0];
     el.value="true";
     el.form["action"].value = "_subpage";
     el.form.submit();
  } else {
    if (show) {
       e.style.display = "block";
       document.getElementsByName(elem)[0].value="true";
    } else { 
       e.style.display = "none";
       document.getElementsByName(elem)[0].value="false";
    }
  }
}

function guesspick(elem,value) {
  for (var i=0;i<elem.options.length;i++) if (elem.options[i].value==value) {elem.selectedIndex = i;chfield(elem);}
}

function seltrigger(elem,mode,trigger) {
  if (elem.selectedIndex == elem.options.length-1) {
    if (!elem.itvt_alreadyTriggered) {
      elem.itvt_alreadyTriggered = true;
      if (mode==1) subpageclick2(trigger,true);
      if (mode==2) { elem.form["action"].value="_extselect:"+elem.name;elem.form.submit(); }
    }
  } else {
    if (elem.itvt_alreadyTriggered) {
      elem.itvt_alreadyTriggered = false;
      if (mode==1) subpageclick2(trigger,false);
      if (mode==2) { elem.form["action"].value="_extselect:"+elem.name;elem.form.submit(); }
    }
  }
}


 function syncTable(name) { 
   var anchor = document.getElementById(name);
   var headdiv = findPrev(anchor,"DIV");
   var rowdiv = findNext(headdiv,"DIV");
   var headtable = findChild(headdiv,"TABLE");
   var rowtable = findChild(rowdiv,"TABLE");
   var cellspace = headtable.cellPadding;
   var cellpadding = headtable.cellSpacing;
   var xspace = cellpadding * 2;

   var maxHeight = 0.4 * screen.availHeight;
   var maxWidth = screen.availWidth-30;

   if (!headdiv.itvtOriginalWidth) {
      headdiv.itvtOriginalWidth = headdiv.offsetWidth;
      headdiv.itvtOriginalHeight = headdiv.offsetHeight;
   }

   headtable.style.width="1px";
   rowtable.style.width=headdiv.itvtOriginalWidth-18;
  
   rowdiv.style.overflow="scroll";
   headdiv.style.overflow="hidden";

   if (rowdiv.offsetHeight>maxHeight) {
     rowdiv.style.height=maxHeight;
     document.body.itvtScrollLock = true;
   }
  
   var r1 = headtable.tBodies[0].rows[0];
   var r2 = rowtable.tBodies[0].rows[0];
   if (r2.cells.length < r1.cells.length) r2 = rowtable.tBodies[0].rows[1];

   for (var i=0;i<r1.cells.length;i++) {
      var h = r1.cells[i].offsetWidth - xspace - 2;
      var h2 = r2.cells[i].offsetWidth - xspace -2;
      if (h>h2) {
        r2.cells[i].style.width = h;     
        var d2 = wrap(r2.cells[i]);
        d2.style.width = h;
      }
   }   
      
   for (var i=0;i<r1.cells.length;i++) {
      var h = r1.cells[i].offsetWidth - xspace - 2;
      var h2 = r2.cells[i].offsetWidth - xspace -2;
      if (h2>h) h = h2;
      r2.cells[i].style.width = h;
      r1.cells[i].style.width = h;
     
      var d2 = wrap(r2.cells[i]);
      d2.style.width = h;

      var d1 = wrap(r1.cells[i]);
      d1.style.width = h;

      //alert(r1.cells[i].offsetWidth+" vs "+r2.cells[i].offsetWidth+" : "+d1.style.width+" : "+d2.style.width);

   }   
   
   
   if (r2.cells.length>0) {
     r2.cells[r2.cells.length-1].style.width = "100%";
     r1.cells[r1.cells.length-1].style.width = "100%";
   }

   var calcWidth = headtable.offsetWidth;
   if (rowtable.offsetWidth < calcWidth) calcWidth = rowtable.offsetWidth;  
   if (calcWidth < headdiv.itvtOriginalWidth-18) calcWidth = headdiv.itvtOriginalWidth-18; 
     
   headtable.style.width = calcWidth;
   rowtable.style.width= calcWidth;   
     
   if (!(headdiv.itvtNoscroll)) {
     headdiv.style.width = 1;
     rowdiv.style.width = 1;
     maxWidth = headdiv.parentNode.offsetWidth - headdiv.offsetLeft * 2 - 18;    
     if (document.body.itvtMaxTableWidth) maxWidth = document.body.itvtMaxTableWidth;
     var wantedWidth = calcWidth < maxWidth ? calcWidth : maxWidth; 
     headdiv.style.width = wantedWidth;
     rowdiv.style.width = wantedWidth + 18;  
     if (headdiv.scrollWidth>wantedWidth) {
       rowdiv.onscroll=function() { headdiv.scrollLeft = rowdiv.scrollLeft; }; 
     } else {
       headdiv.style.width = calcWidth;
       rowdiv.style.width = calcWidth + 18;
       headdiv.itvtNoscroll = true;
     }
   }
 }
 

 function wrap(node) {
   var c = null;
   if (node.childNodes.length>0) c = node.firstChild;   
   if (c && c.itvtgen) return c;
   var d = document.createElement("div");   
   d.itvtgen = true;
   if (c) {
     node.removeChild(c);
     d.appendChild(c);
   }
   node.appendChild(d);
   return d;
 }
 
 function formreplace(elemalt,contentneu) {
   var cnt = elemalt.parentNode;
   var oldid = elemalt.id;
   var oldao = elemalt.itvtobj;
   var dis = elemalt.style.display;
   var neuelem = document.createElement("span");
   neuelem.innerHTML = contentneu;
   elemalt.style.display="none";
   var elemneu = neuelem.firstChild;
   if (oldid) elemneu.id = oldid;
   if (oldao) elemneu.itvtobj = oldao;
   if (dis) elemneu.style.display = dis;
   cnt.insertBefore(elemneu,elemalt);
   elemalt.blur();
   elemneu.focus();
   cnt.removeChild(elemalt);   
 }
 
 function findChild(node,type) {
   var c = node.firstChild;
   if (c==null) return null;
   while (c!=null && !(c.nodeName==type)) c = c.nextSibling;
   return c;
 }
 
 function findNext(node,type) {
   var c = node.nextSibling; 
   while (c!=null && !(c.nodeName==type)) {c = c.nextSibling;}
   return c;  
 }

 function findPrev(node,type) {
  var c = node.previousSibling; 
  while (!(c.nodeName==type)) {c = c.previousSibling;}
  return c;  
 }
 
 function findParent(node,type) {
   var c = node.parentNode;
   while (!(c.nodeName==type)) { c=c.parentNode;}
   return c;
 }
 
 function scrollpatch(where) {
   var c = document.getElementsByName(where);
   if (c.length>0) {
     if (c[0].scrollIntoView) {c[0].scrollIntoView(false);return;}
   }
   document.location.hash = where;
 }
 
 function chfield(f) {  
   if (f.className=="unchanged") f.className = "changed";
 }
 
 function isKonqueror() {
   return navigator.userAgent.toLowerCase().indexOf("konqueror")>-1;
 }
 
 function isSafari() {
   return navigator.userAgent.toLowerCase().indexOf("safari")>-1;
 }
 
 function getBodyScrollTop(mywin) {
   var b = mywin.document.getElementsByTagName("body")[0];
   var h = b.pageYOffset;
   if (!h || (b.scrollTop > h)) h = b.scrollTop;
   return h;
 }
 
 function getBodyScrollLeft(mywin) {
   var b = mywin.document.getElementsByTagName("body")[0];
   var h = b.pageXOffset;
   if (!h || b.scrollLeft > h) h = b.scrollLeft;
   return h;
 }
 
 function dragdropinit() {
  window.itvtdnd = new Object();
  window.itvtdnd.targets = new Array();
  document.onmousedown=na; 
  document.onmousemove=dndmousemove;
  document.onmouseup=dndmouseup;  
  document.oncontextmenu=ctxno; 
  document.ondblclick=ctxno;
  document.onclick=clickfilter;
  if (isKonqueror() || window.opera) {
    document.onmousedown=dndmousedownNoCTX;
  }
  setInterval("timer()",50);
 } 
 
 var timeclick = false;
 
 function dndmouseup(e) {
   if (!e) e = event;  
   if ((e.button && e.button==2) || e.altKey) return false;
   if (window.itvtdnd && window.itvtdnd.up) {return window.itvtdnd.up(e,window.itvtdnd.item);} else return true;   
 }
 
 function dndmousemove(e) {
   if (!e) e = event;
   if (window.itvtdnd) {
     if (window.itvtdnd.move) {window.itvtdnd.move(e,window.itvtdnd.item);return false; } else {window.itvtdnd.isDrag=false;return true;}
   }
   return true;
 }
 
 function na(e) {   
   if (!e) e = event;  
   if (window.itvtdnd && window.itvtdnd.move) return false; else return true;
 }
 
 function dndmousedownNoCTX(e) {
   if (!e) e = event;
   if ((e.button && e.button==2) || e.altKey) { 
     var t = e.target;
     while (t!=null) {
       if (t.oncontextmenu) { t.oncontextmenu(e);return false; }
       t = t.parentNode;
     }
     return false;
   } 
   if (window.itvtdnd && window.itvtdnd.move) return false; else return true;
 }
 
 function ctxno(e) {
   return false;
 }
 
 function clickfilter(e) { 
   if (!e) e = event;
   if (isKonqueror() && e.button && e.button==2) return false;  
   if (window.itvtdnd && window.itvtdnd.isDrag) return false; 
   if (window.itvtdnd && window.itvtdnd.menuOpen) { menuclose();return false;} 
   return true;
 } 
 

function timer() {
 timeclick = true;
 return true;
}



function csitvttable(name) {
   var mytable = document.getElementById(name);
   mytable.itvtdata = new Object();
   var dat = mytable.itvtdata;
   var total = mytable.offsetWidth;  

   dat.divA = document.getElementById(name+"A");
   dat.divB = document.getElementById(name+"B");
   dat.divC = document.getElementById(name+"C");
   dat.divD = document.getElementById(name+"D");
   if (dat.divD) dat.divD.style.display = "block";
   dat.cols = new Array();
   dat.rows = new Array();
   
   // Set sizes
   var idx = 0;
   if (dat.divA) idx = fetchsize(dat, findChild(dat.divA,"TABLE"), 0);
   if (dat.divC) idx = fetchsize(dat, findChild(dat.divC,"TABLE"), 0);
   if (dat.divB) fetchsize(dat, findChild(dat.divB,"TABLE"), idx);
   if (dat.divD) fetchsize(dat, findChild(dat.divD,"TABLE"), idx);
   dat.cols[dat.cols.length-1] = 20;
   
   var s1 = 0;
   var s2 = 0;
   if (dat.divA) s1 = cssetsize(dat, findChild(dat.divA,"TABLE"), 0);
   if (dat.divB) s2 = cssetsize(dat, findChild(dat.divB,"TABLE"), idx);
   if (dat.divC) s1 = cssetsize(dat, findChild(dat.divC,"TABLE"), 0);
   if (dat.divD) s2 = cssetsize(dat, findChild(dat.divD,"TABLE"), idx);
   var s3 = total - s1;
   if (s3<200 && s2>200) {
       total = total - s3 + 200;
       s3 = 200;
   //  mytable.style.width = "100%";// total+"px";
   }
   if (dat.divA) { dat.divA.style.width = s1+"px";}
   if (dat.divC) { dat.divC.style.width = s1+"px"; }
   if (dat.divB) dat.divB.style.width = (s3-20)+"px";
   if (dat.divD) { dat.divD.style.width = s3+"px"; }
   
   var maxHeight = 0.4 * screen.availHeight;
   var scrollHeight = 0;
   var containerHeight = 0;
   if (dat.divC) scrollHeight = findChild(dat.divC,"TABLE").offsetHeight;
   else if (dat.divD) scrollHeight = findChild(dat.divD,"TABLE").offsetHeight;
   
   if (scrollHeight > maxHeight + 100) {
     containerHeight = maxHeight;    
     //if (dat.divD) dat.divD.style.clip="rect(auto,auto,auto,auto)";
     dat.clipping = false;
   } else {
     containerHeight = scrollHeight+25;
     dat.clipping = true;
     if (dat.divB) dat.divB.style.width = (s3)+"px";
   }
   
   if (dat.divA) dat.divA.style.height = findChild(dat.divA,"TABLE").offsetHeight+"px";
   if (dat.divB) dat.divB.style.height = findChild(dat.divB,"TABLE").offsetHeight+"px";
 
   if (dat.divC) dat.divC.style.height = containerHeight+"px";
   if (dat.divD) dat.divD.style.height = containerHeight+"px";
   
   dat.finish = true;
   afterResize("cstableresize('"+name+"');");
 }
 
 function cstableresize(name) {
   var mytable = document.getElementById(name);
   if (!mytable) return;
   if (!mytable.itvtdata) return;
   if (!mytable.itvtdata.finish) return;
   var dat = mytable.itvtdata;
   if (dat.divB) dat.divB.style.width="1px";
   if (dat.divD) dat.divD.style.width="1px";
   mytable.style.width="1px";
   mytable.style.width="100%";   
   var s2 = 0;
   if (dat.divA) s2 = dat.divA.offsetWidth;
   else if (dat.divC) s2 = dat.divC.offsetWidth;
   var s3 = mytable.offsetWidth - s2 - 10;
   if (s3<200 && s2>200) {
       s3 = 200;
   }
   if (dat.divB) dat.divB.style.width = (s3-(dat.clipping?0:20))+"px";
   if (dat.divD) dat.divD.style.width = s3+"px";     
   //if (dat.clipping && dat.divD!=null) dat.divD.style.clip="rect(auto,"+(s3-20)+"px,auto,auto)";
 }
 
 function cssetsize(dat,table,idx) {
   var tbody = findChild(table, "TBODY");
   var tr = findChild(tbody,"TR");
   var totalwidth = 0;
   var cont = true;
   while (tr!=null && cont) {
    cont = false;
    var i=idx;
    var w = 1 * table.cellSpacing;
    var td = findChild(tr,"TD");
    while (td) {
      var cs = td.colSpan;
      var wx;
      if (cs==1) {
        wx = dat.cols[i];
      } else {
        wx = cstabx(dat,i,cs);
        cont = true;
      }
      //alert(wx);
      td.style.width = wx+"px"; 
      w = w + wx + (1 * table.cellSpacing) + (2 * table.cellPadding);
      td = findNext(td,"TD");
      i+=cs;
    }
    if (w>totalwidth) totalwidth = w;
    tr = findNext(tr,"TR");
   }
   table.style.width = totalwidth+"px";
   return totalwidth - table.cellSpacing;
 }
 
 function fetchsize(dat,table,idx) {
   var tbody = findChild(table, "TBODY");
   var tr = findChild(tbody,"TR");
   var cont = true;
   while ((tr!=null) && cont) {
    cont = false;
    var i = idx;
    var td = findChild(tr,"TD");
    while (td) {
      var w = td.offsetWidth;
      var cs = td.colSpan;
      if (cs==1) {
        var tw = dat.cols[i];
        if (!tw || w>tw) { dat.cols[i] = w; }
      } else {
        cont = true;
      }
      td = findNext(td,"TD");
      i+=cs;
    }
    tr = findNext(tr,"TR");
   }
   return i;
 }
 
 function cstabx(dat,idx,cs) {
   var result = 0;
   for (var i=idx;i<idx+cs;i++) result+=dat.cols[i];
   return result;
 }
 
 function cstablescroll(e,name) {
   if (!e) e = event;
   var mytable = document.getElementById(name);
   if (!mytable) return;
   var dat = mytable.itvtdata;
   if (!dat || !dat.finish) return;
   if (dat.divB) {dat.divB.scrollLeft = dat.divD.scrollLeft;dat.divB.itvtScrollLeft = dat.divD.scrollLeft; }
   if (dat.divC) {dat.divC.scrollTop = dat.divD.scrollTop;}
 }


var xmlreq = null;
var loadcount = 0;
var locktimer = null;
var canceltimer = null;
var lastclick = 0;

function gourl(win,url) { 
  try {
    if (win.document.readyState && win.document.readyState!="complete" && win.document.readyState!="interactive") {
      return;
    }
    if (win.itvtPageState && win.itvtPageState=="request") return;
  } catch (e) {}
  win.framecontrol.gourl(url);  
}

function ajax(url,data,noasync) {  
  window.framecontrol.ajax(url,data,noasync);
}


function servercrashed() {
  alert("The Server is currently down");
  root(window).appcontrol.errorstate();
}

function errorhandler(msg,file,line) {
  alert(msg+" file="+file+" line="+line);
  root(window).appcontrol.errorstate();
  if (confirm("A client side error occured. An error report will be send to I-TV-T. Click ok to continue - your last session state should be restored.")) {
    var sep = "?";
    if (errorurl.indexOf("?")>0) sep = "&";
    root(window).document.location.href=errorurl+sep+"file="+encodeURIComponent(file)+"&line="+line+"&msg="+encodeURIComponent(msg)+"&appName="+encodeURIComponent(navigator.appName)+"&version="+encodeURIComponent(navigator.appVersion)+"&platform="+encodeURIComponent(navigator.platform);
    return true;
  } else return false;
}

function stacktrace() {
  var s = "Trace:";
  for (var a = arguments.caller;a!=null;a=a.caller) {
    s+="->"+a.caller+"\n";
    if (a.caller == a) { s+="*";break; }
  }
  alert(s);
}

function postform(f) {
  var r = "";
  for (var i=0;i<f.length;i++) {
    if (i>0) r+= "&";
    if (f[i].type=="checkbox" || f[i].type=="radio") {
      if (f[i].checked) r+=f[i].name+"="+encodeURIComponent(f[i].value);
    } else if (f[i].name!="action") r+=f[i].name+"="+encodeURIComponent(f[i].value);
  }
  return r;
}

var framename = "frame"+new Date().getTime();

function deltaload(url,fromwin) {
  window.framecontrol.deltaload(url,fromwin);
}

function checker(myname,repeat) {  
}
 
function deltafinish(scripts,content, posname, source, hide) {  
   var node = document.getElementById("ajax_"+posname);      
   if (node.view) node.view.destroy();
   // loadunlock(window);       
   node.innerHTML = content;  
   if (!hide) {
     node.style.display="block";
     NodeService.trigger(node,"show");
   } else {
     node.style.display="none";
     NodeService.trigger(node,"hide");
   }
   var oldac = document.itvtActive;
   var afterLoad = function(x) { eval(x); }
   var pview = [node.view];    
   var dp = new DP();
   for (var i=1;i<scripts.length;i++) {dbg("df:"+scripts[i]);eval(scripts[i]);}      
   pview[0].doInit();
   checkIEscrollbarbug();
   NodeService.trigger(node,"contentchange");
             
 }

function deltasubview(scripts,content, posname, source, hide) {  
   var node = document.getElementById(posname);             
   if (node.view) node.view.destroy();
   // loadunlock(window);       
   node.innerHTML = content;
   //var container = findParent(node,"DIV");
   //if (!hide) container.style.display="block";   
   //else container.style.display="none";   
   var oldac = document.itvtActive;
   var afterLoad = function(x) { eval(x); }
   var pview = [node.view];    
   var dp = new DP();
   for (var i=1;i<scripts.length;i++) {dbg("df:"+scripts[i]);eval(scripts[i]);}      
   pview[0].doInit();
   checkIEscrollbarbug();              
}

function deltahide(target,posname,hide) {
  var node = target.document.getElementById("ajax_"+posname);
  node.style.display=hide?"none":"block";
  NodeService.trigger(node,hide?"hide":"show");
  checkIEscrollbarbug();  
}

function deltaclear(target,posname) { 
  var node = target.document.getElementById("ajax_"+posname);   
  node.style.display="none";   
  NodeService.trigger(node,"hide");
  if (node && node.view) {
    node.view.destroy(); 
  }
  node.innerHTML=""; 
  NodeService.trigger(node,"contentchange"); 
  checkIEscrollbarbug();
}

 function xc(node,from) {   
   if (!node) alert("from:"+from);
   if (node.offsetParent) {
    return xc(node.offsetParent)+node.offsetLeft-node.scrollLeft;
   } else {
    return node.offsetLeft-getBodyScrollLeft(window);
   }
 }
 
 function bpath(node) {
   var r = node.nodeName+"("+node.id+","+node.scrollLeft+","+node.offsetLeft+")";
   if (node.offsetParent!=null) return r+"\n"+bpath(node.offsetParent); else return r;
 }
 
 function yc(node) {
   if (node.offsetParent) {
     return yc(node.offsetParent)+node.offsetTop-node.scrollTop;
   } else {
     return node.offsetTop-getBodyScrollTop(window);
   }
 }
  
 function makeContext(menu,menucontent) {
   var elem = document.getElementById(menu);
   var d = document.getElementById(menucontent);
   elem.itvtctxmenu = d;  
   elem.oncontextmenu = menuopen_bridge;//evh('menuopen(e,"'+menu+'");');
 }
 
 function menuopen_bridge(e) {
   menuopen(e,this.id);
   try { this.blur(); } catch(e) {}
   return false;
 }
 
 function openctxfunc(e) {  
   menuopen(e,this.id);
   try { this.blur(); } catch(e) {}
   return false;
 }
 
 function menuopen(e,menu) {
   if (!e) e = event;   
     e.cancelBubble = true; 
     var aobj = aocall(menu);
     var trigger = aobj.obj();
     window.itvtdnd.menuAjaxObject = null;
     if (window.itvtdnd.menuOpen!=null) menuclose();
     window.itvtdnd.menuAjaxObject = aobj;
     if (aobj.onctxmenu_code) eval(aobj.onctxmenu_code);
     var url = aobj.onctxmenu_path;
     if (!url && aobj.behavior) {
       if (aobj.behavior.onctxmenu_code) eval(aobj.behavior.onctxmenu_code);
       url = aobj.behavior.onctxmenu_path;
     }
     if (url) {
       ctxMenu(menu+"m",menu,null);
       ctxLazyLoad(menu+"m",url);
       makeContext(menu,menu+"m");
       // ??? trigger.itvtctxmenuurl = null;
     }
     var content = trigger.itvtctxmenu;

     ctxshow(content,trigger);
     window.itvtdnd.menuOpen=trigger;
   
     return false;
 
 }
 
 
 function ctxshow(menu,trigger) {
     var y = yc(trigger);
     if (trigger.itvtmenuparent) {
       menu.style.left = (xc(trigger)+trigger.offsetWidth)+"px";
     } else {
       if (y>20) y-=20;
       menu.style.left = (xc(trigger)+10)+"px";
     }          
     menu.style.top = y+"px";    
     menu.style.display='block'; 
     switchSelects(menu,false);

     if (menu.itvtautoload) {           
       ajax(menu.itvtautoload,"event=ctx&source="+menu.itvtmenuid+"&itemid="+menu.itvtmenuid+"&menuid="+menu.id+(menu.itvtmenuname ? "&menuname="+menu.itvtmenuname : ""),true);
     }
 }
 
 function menuclose() {  
   var dnd = window.itvtdnd;
   var trigger = dnd.menuOpen;
   var content = trigger.itvtctxmenu;
   dnd.menuOpen = null;
   menuclosefrom(content);
   dnd.menuAjaxObject = null;
 }
 
 function menuclosefrom(content) {
   switchSelects(content,true);
   if (window.itvtdnd.menuAjaxObject) {
    content.style.display='none';   
    //(new DP()).fadeout(content,window.itvtdnd.menuAjaxObject.pview);      
   } else {
    content.style.display='none';   
   }       
     
   while (content.itvtsubmenu) {
     var ncontent = content.itvtsubmenu;
     content.itvtsubmenu = null;
     switchSelects(ncontent,true);    
     if (window.itvtdnd.menuAjaxObject) {
      (new DP()).fadeout(ncontent,window.itvtdnd.menuAjaxObject.pview);      
     } else {
       ncontent.style.display='none';       
     }       
     content = ncontent;
   }      
 }

 function ctxMenu(id,itemid,name) {
   if (!window.itvtdnd) dragdropinit();     
   var elem = document.createElement("div");
   elem.id = id;
   elem.itvtmenuid=itemid;
   elem.itvtmenuname=name;
   elem.innerHTML="<div class='ctxblur'></div><div class='ctxmenu'></div>";
   //elem.className="ctxblur";
   elem.style.position='absolute';
   elem.style.zIndex=50;
   elem.style.display='none';  
   elem.style.left="0px";
   elem.style.top="0px"; 
   document.getElementsByTagName("body")[0].appendChild(elem);
   elem.menudiv = findNext(findChild(elem,"DIV"),"DIV");
 }
 
 function ctx(id,vid,url,pview) {   
   var aobj = check_object(id,vid,pview);
   aobj.onctxmenu_path = url;
   aobj.obj().oncontextmenu = openctxfunc;
 }
 
 function ctxLazyLoad(id,url) {  
   var elem = document.getElementById(id);
   elem.itvtautoload=url;   
   elem.menudiv.innerHTML="Please wait...";
 }

 function ctxMenuClear(id) {
   var elem = document.getElementById(id);
   if (elem!=null && elem.menudiv) elem.menudiv.innerHTML="";
 }
 
 function ctxMenuPatch(id) {
   if (window.itvtdnd && window.itvtdnd.menuOpen) {
     var elem = document.getElementById(id);
     if (elem!=null) switchSelects(elem,false);
   }
 }
 
 function ctxMenuItem(father,text,url,useajax) {
   var elem = document.getElementById(father).menudiv;
   var ne = document.createElement("div");
   ne.className="ctxitem";
   ne.innerHTML=text;
   ne.itvturl = url;
   ne.itvtuseajax = useajax;
   ne.onmouseover=ctxmark;
   ne.onmouseout=ctxunmark;
   ne.onclick=ctxclick;
   elem.appendChild(ne);
 }
 
 function ctxSubMenuItem(father,text,name,url) {
   var elem = document.getElementById(father).menudiv;
   var ne = document.createElement("div");   
   ne.className="ctxitem";
   ne.innerHTML=text+" -&gt;";
   ne.itvturl = url;  
   ne.itvtmenuparent=elem;
   ne.itvtsubmenuname=name;
   ne.onmouseover=ctxmark;
   ne.onmouseout=ctxunmark;
   ne.onclick=ctxsubmenuclick;
   elem.appendChild(ne);
 }
 
 function ctxMenuSeperator(father) {
   var elem = document.getElementById(father).menudiv;
   var ne = document.createElement("div");
   ne.className="ctxseperator";   
   ne.innerHTML="<span></span>";
   elem.appendChild(ne);
 }
 
 function ctxMenuInfo(father, html) {
   var elem = $(father).menudiv;
   var ne = document.createElement("div");
   ne.className="ctxinfo";   
   ne.innerHTML=html;
   elem.appendChild(ne);
 }
 
 function ctxMenuTitle(father, text) {
   var elem = document.getElementById(father).menudiv;
   var ne = document.createElement("div");
   ne.className="ctxtitle";
   ne.innerHTML=text;
   elem.appendChild(ne);
   // ctxMenuSeperator(father);
 }
 
 function ctxMenuCheckbox(father,text,url,selected) {
   var elem = document.getElementById(father).menudiv;
   var ne = document.createElement("div");
   ne.className="ctxitem";

   ne.itvturl = url;
   ne.itvtuseajax = true;
   ne.onmouseover=ctxmark;
   ne.onmouseout=ctxunmark;
   ne.onclick=ctxclick;
   elem.appendChild(ne);
 }
 
 
 function ctxmark(e) {
   if (!e) e = event;
   this.className="ctxselected";
 }
 
 function ctxunmark(e) {
  if (!e) e = event;
  this.className="ctxitem";
 }
 
 function ctxclick(e) {
  if (!e) e = event;
  if (e.button && e.button!=1) return true;
  if (!window.itvtdnd || !window.itvtdnd.menuOpen) return true;
  var data = "source="+window.itvtdnd.menuOpen.id+"&event=context";
  if (this.itvtuseajax) { ajax(this.itvturl,data); } else { 
    try { clstore(window); } catch(e) {}
    gourl(window,this.itvturl); 
  }
  return true;
 }
 
 function ctxsubmenuclick(e) {
  if (!e) e = event;
  if (e.button && e.button!=1) return true;
  e.cancelBubble = true;
  var newid = this.itvtmenuparent.id+this.itvtsubmenuname;
  var oldsub = this.itvtmenuparent.itvtsubmenu; 
  if (oldsub && oldsub.id!=newid) {    
    menuclosefrom(oldsub);
    document.getElementsByTagName("body")[0].removeChild(oldsub);
    this.itvtmenuparent.itvtsubmenu = null;
  }
   if (!this.itvtmenuparent.itvtsubmenu) {     
      ctxMenu(newid,this.itvtmenuparent.itvtmenuid,this.itvtsubmenuname);
      ctxLazyLoad(newid,this.itvturl);
      this.itvtmenuparent.itvtsubmenu = document.getElementById(newid);
   }
   ctxshow(this.itvtmenuparent.itvtsubmenu,this);   
   return false;
 }

 
 function aocall(id) {
    var obj = document.getElementById(id);
    if (obj) return obj.itvtobj;
 }

 function ac_create(id,vid,cnt) {
   var aobj = in_object(id,vid,cnt);
   aocall(aobj.itvtcontainer).container_create(aobj);
 }
 
   
 function tr_click(e) {
   if (!e) e = event;
   if (e.button && e.button!=1) return true;  
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('click',source);      
   if (source.onclick_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onclick_code,source.onclick_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onclick_code,source.behavior.onclick_path));
   }   
 }
 
 function tr_dblclick(e) {
   if (!e) e = event;
   if (e.button && e.button!=1) return true;  
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('dblclick',source);      
   if (source.ondblclick_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.ondblclick_code,source.ondblclick_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.ondblclick_code,source.behavior.ondblclick_path));
   }   
 }
 
 function tr_onchange(e) {
   if (!e) e = event;
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('change',source);      
   if (source.onchange_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onchange_code,source.onchange_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onchange_code,source.behavior.onchange_path));
   }   
 }
 
 function tr_onkeyup(e) {
   if (!e) e = event;
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('keyup',source);      
   if (source.onkeyup_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onkeyup_code,source.onkeyup_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onkeyup_code,source.behavior.onkeyup_path));
   }  
   if (source.obj().onkeyup_old) source.obj().onkeyup_old(e); 
 }

 function tr_onfocus(e) {
   if (!e) e = event;
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('focus',source);      
   if (source.onfocus_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onfocus_code,source.onfocus_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onfocus_code,source.behavior.onfocus_path));
   }  
   if (source.obj().onfocus_old) source.obj().onfocus_old(e); 
 }
 
 function tr_onblur(e) {
   if (!e) e = event;
   var source = aocall(this.id);
   var aevent = new AjaxObjects.AjaxEvent('blur',source);      
   if (source.onblur_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onblur_code,source.onblur_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onblur_code,source.behavior.onblur_path));
   }  
   if (source.obj().onblur_old) source.obj().onblur_old(e); 
 }

 
 function tr_init(id) {
   var source = aocall(id);
   var aevent = new AjaxObjects.AjaxEvent('init',source);      
   if (source.oninit_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.oninit_code,source.oninit_path));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.oninit_code,source.behavior.oninit_path));
   }   
 }
 
 function tr_trigger(id,param) {
   var source = aocall(id);
   var aevent = new AjaxObjects.AjaxEvent('trigger',source);
   aevent.params = param;
   if (source.ontrigger_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.ontrigger_code,source.ontrigger_path));
   if (source.behavior) {
    aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.ontrigger_code,source.behavior.ontrigger_path));
   }
 }

 function tr_preinit(id) {
   var source = aocall(id);
   var aevent = new AjaxObjects.AjaxEvent('preinit',source);      
   if (source.onpreinit_code) aevent.trigger(new AjaxObjects.AjaxEventHandler(source.onpreinit_code,null));   
   if (source.behavior) {
     aevent.trigger(new AjaxObjects.AjaxEventHandler(source.behavior.onpreinit_code,null));
   }   
 }
 
   
 function mk_target(id, type, code, path, frombehavior) {
   if (!window.itvtdnd) dragdropinit();
   var mynode = document.getElementById(id);
   var dnd = window.itvtdnd;
   var t = type.split(",");
   for (var i=0;i<t.length;i++) {   
     var target = new Object();
     target.node = mynode.id;
     target.id=id;
     target.types=t[i];
     target.url = path;
     target.itvtcode=code;
     if (frombehavior) target.frombehavior = true;
     // mynode.itvtmustclear = true;  
     dnd.targets[dnd.targets.length] = target;
   }
 }
 
 
 function check_object(id,vid,pview) {
   var elem = document.getElementById(id);
   if (elem.itvtobj) return elem.itvtobj;
   var aobj = new AjaxObjects.AjaxObject(id,vid,pview.last());
   elem.itvtobj = aobj;
   pview.last().addSub(aobj);
   return aobj;
 }
 
 
 function evhST(e,source,target,trans,code) {
    try {    
      eval(code);
    } catch (e) {
      if (e=="cancel") return false;
      else throw e;
    }
    return true;
 }
 
 
 function in_click(id,code,path) {
   var aobj = aocall(id);
   if (aobj!=null) { 
     aobj.onclick_code = code;
     aobj.onclick_path = path;
     aobj.obj().onclick = tr_click;
   }
 }

 function in_doubleclick(id,code,path) {
   var aobj = aocall(id);
   if (aobj!=null) { 
     //e.itvtdblclickold = e.ondblclick;
     aobj.obj().ondblclick = tr_dblclick;
     aobj.ondblclick_path = path;
     aobj.ondblclick_code = code;
   }
 }
 
 function in_change(id,code,path) {
   var aobj = aocall(id);
   if (aobj!=null) {
     aobj.obj().onchange = tr_onchange;
     aobj.onchange_path = path;
     aobj.onchange_code = code;
   }
 }
 
 function in_keyup(id,code,path) {
   var aobj = aocall(id);

   if (aobj!=null) {
     aobj.obj().onkeyup = tr_onkeyup;
     aobj.onkeyup_path = path;
     aobj.onkeyup_code = code;
   }
 }
 
 function in_focus(id,code,path) {
   var aobj = aocall(id);

   if (aobj!=null) {
     aobj.obj().onfocus = tr_onfocus;
     aobj.onfocus_path = path;
     aobj.onfocus_code = code;
   }
 }
 
 function in_blur(id,code,path) {
   var aobj = aocall(id);

   if (aobj!=null) {
     aobj.obj().onblur = tr_onblur;
     aobj.onblur_path = path;
     aobj.onblur_code = code;
   }
 }
 
 function in_trigger(id,code,path) {
   var aobj = aocall(id);
   if (aobj!=null) {
     aobj.ontrigger_path = path;
     aobj.ontrigger_code = code;    
   }
 }
 
 function in_contentchange(id,code,path) {
   var aobj = aocall(id);
   if (aobj!=null) {
     NodeService.connect(id,"contentchange",NodeService.createaohandler(id,"contentchange",code,path));
   }
 }

 function in_init(id,code,path) {
   var aobj = aocall(id);

   if (aobj!=null) {
     aobj.oninit_path = path;
     aobj.oninit_code = code;
     if (!aobj.isbehavior && (path || code)) { 
       aobj.pview.addInit(aobj.key);
     }
   }
   
 }
 
 function in_preinit(id,code,path) {
   var aobj = aocall(id);

   if (aobj!=null) {
     aobj.onpreinit_code = code;
     if (!aobj.isbehavior && (code)) { 
       tr_preinit(id);
     }
   }
   
 }
  
 
 function in_dragdrop(id,code,path,type,highlight,preview) {
   if (path=="") path = "none";  
   
   if (!window.itvtdnd) dragdropinit();
   var aobj = aocall(id);
   var dnd = window.itvtdnd;
   var t = type.split(",");
   for (var i=0;i<t.length;i++) {   
     var target = new RClient.DragTarget(aobj.key,id,t[i],path,code,highlight,preview);
     aobj.addSub(target);
     if (!aobj.isbehavior) {
       window.desktop.dragserver.addTarget(target);
     } 
   }
   
   
   //mk_target(id,type,code,path); 
 }
 
 function in_highlight(id,code) {
   /*var aobj = aocall(id);
   if (aobj!=null) { 
     aobj.onhighlight_code = code;
   }*/
 }
 
 function in_ctxmenu(id,code,path) {
   var aobj = aocall(id);
   aobj.onctxmenu_path = path;
   aobj.onctxmenu_code = code;    
   aobj.obj().oncontextmenu = openctxfunc;
 }
  
  
 function in_desktop(id,vid,pview) {
    var aobj = check_object(id,vid,pview);
    aobj.container_swap = im_swap_desktop;
    aobj.container_create = im_create_desktop;
    aobj.container_delete = im_delete_desktop;
 }
 
 
 function in_list(id,vid,pview) {
   var aobj = check_object(id,vid,pview);
   aobj.container_swap = im_swap_list;
   aobj.container_create = im_create_list;
   aobj.container_delete = im_delete_list;
 }
 
 function in_object(id,cid,vid,pview) {
   var aobj = check_object(id,vid,pview);   
   if (cid!="") { aobj.itvtcontainer = cid; }
   else { aobj.itvtcontainer = null; }     
 }
 
 function in_behavior(id,vid,pview) {
   var aobj = check_object(id,vid,pview);
   aobj.isbehavior = true;   
 }
 
 function in_aobehavior(id,name) {
   var aobj = aocall(id);  
   if (aobj) aobj.setBehavior(name);
 }
 
 function in_farbbutton(id) {
   aocall(id).setDisabled = FarbButtondisable;
 }
 
 function in_checkbox(id) {  
   var o = aocall(id);
   o.setValue = checkbox_setValue;
   o.getValue = checkbox_getValue; 
 }
  
 function im_swap_desktop(obj1,obj2) {
   var x = obj1.obj().style.left;
   var y = obj1.obj().style.top;
   obj1.obj().style.left = obj2.obj().style.left;
   obj1.obj().style.top = obj2.obj().style.top;
   obj2.obj().style.left = x;
   obj2.obj().style.top = y;
 }
 
 function im_create_desktop(obj1) {
   obj1.obj().style.position='absolute';
   this.appendChild(obj1.obj());
 }
 
 function im_delete_desktop(obj1) {
   this.removeChild(obj1.obj());
 }
 
 
 function im_swap_list(obj1,obj2) {  
   var p1 = findParent(obj1.obj(),"TR");
   var p2 = findParent(obj2.obj(),"TR");
   if (p1.sectionRowIndex > p2.sectionRowIndex) {
     this.obj().tBodies[0].removeChild(p1);
     this.obj().tBodies[0].insertBefore(p1,p2);
   } else {
     var pn = p2.nextSibling;
     this.obj().tBodies[0].removeChild(p1);
     if (pn) this.obj().tBodies[0].insertBefore(p1,pn); else this.obj().tBodies[0].appendChild(p1);
   }  
 }
 
 function im_create_list(obj1) {
   var row = this.obj().tBodies[0].insertRow(this.obj().tBodies[0].rows.length);
   row.className = this.obj().className;
   var td = row.insertCell(0);
   td.className = this.obj().className;
   td.appendChild(obj1.obj());
 }
 
 function im_delete_list(obj1) {
   var p1 = findParent(obj1.obj(),"TR");
   obj1.obj().parentNode.removeChild(obj1.obj());
   this.obj().deleteRow(p1.rowIndex);
 }
 
 
function overlaps(a1, l1, a2, l2) {
  var b1 = a1 + l1;
  var b2 = a2 + l2;
  return ((a1 > a2 && a1 < b2) ||
          (b1 > a2 && b1 < b2) ||
          (a2 > a1 && a2 < b1) ||
          (b2 > a1 && b2 < b1));
}

function switchSelects(node,on) {
  
  var cl = xc(node);
  var ct = yc(node);
  var ch = node.offsetHeight;
  var cw = node.offsetWidth;
 
  var sels = document.getElementsByTagName("SELECT");
  for (var e = 0; e < sels.length; e++) {
    var el = sels[e];
    var sl = xc(el);
    var st = yc(el);
    var sh = el.offsetHeight;
    var sw = el.offsetWidth;
    if (overlaps(cl, cw, sl, sw) && overlaps(ct, ch, st, sh)) {
      if (on) {
        el.style.visibility = "visible";
      } else {
        el.style.visibility = "hidden";
      }
    }          
  }
}

function switchAllSelects(on) { 
  var sels = document.getElementsByTagName("SELECT");  
  for (var e = 0; e < sels.length; e++) {
    var el = sels[e];

    if (on) {
      el.style.visibility = "visible";
    } else {
      el.style.visibility = "hidden";
    }        
 
  }
}

var winnr = 0;
function debugwin(obj) {
  var mywin = window.open(null,"win"+winnr,"width=600,height=400,scrollbars=yes,resizable=yes");
  winnr++;
  mywin.document.open();
  if (obj) { obj.debug(mywin.document); } else {
   window.desktop.debug(mywin.document);
  }
  mywin.document.close();  
}

function quickcreate(name,classname,inner) {
  var result = document.createElement(name);
  result.className = classname;
  result.innerHTML = inner;
  return result;
}

function setOpacity(node,value) {
  node.style.filter="alpha(opacity="+value*100+")";
  node.style.MozOpacity=""+value;
  node.style.KhtmlOpacity=""+value;
  node.style.opacity=""+value;
}



function getStyleHeight(node) {
  var mt = parseInt(node.style.marginTop);  
  var mb = parseInt(node.style.marginBottom);
  var bt = parseInt(node.style.borderTopWidth);
  var bb = parseInt(node.style.borderBottomWidth);  
  if (isNaN(mt)) mt = 0;
  if (isNaN(mb)) mb = 0;
  if (isNaN(bt)) bt = 0;
  if (isNaN(bb)) bb = 0;
  var r = mt+mb;//+bt+bb;
  dbg(mt+"/"+mb+"/"+bt+"/"+bb+"/"+r);  
  return r;
}

function getStyleWidth(node) { 
  var mt = parseInt(node.style.marginLeft);  
  var mb = parseInt(node.style.marginRight);
  var bt = parseInt(node.style.borderLeftWidth);
  var bb = parseInt(node.style.borderRightWidth);  
  if (isNaN(mt)) mt = 0;
  if (isNaN(mb)) mb = 0;
  if (isNaN(bt)) bt = 0;
  if (isNaN(bb)) bb = 0;
  var r = mt+mb;//+bt+bb;
  dbg(mt+"/"+mb+"/"+bt+"/"+bb+"/"+r);  
  return r;
}

function getBorderWidth(node) {
 var bt = parseInt(node.style.borderLeftWidth);
 var bb = parseInt(node.style.borderRightWidth);  
 if (isNaN(bt)) bt = 0;
 if (isNaN(bb)) bb = 0;
 return bb+bt; 
}

function getBorderHeight(node) {
  var bt = parseInt(node.style.borderTopWidth);
  var bb = parseInt(node.style.borderBottomWidth);  
  if (isNaN(bt)) bt = 0;
  if (isNaN(bb)) bb = 0;
  return bb+bt;
}

// ------------------------ Extension Tables


function itvttable(name,lh,url,pview) {
  pview.last().addSub(new RClient.DragTable(name,lh,url));
}

function startsize(event,name,col) {
  var dat = tabdata(name);
  dat.startsize(event,col);
}

function startpos(event,name,col) { 
  var dat = tabdata(name);
  dat.startpos(event,col);
}


function itvttableresize(name) {  
  var dat=tabdata(name);
  if (dat) return dat.itvttableresize();
}

function changescroll(event,name) {
  var dat=tabdata(name);
  dat.relayout();
} 


function tabdata(name) {
  var mytable = document.getElementById(name);
  if (!mytable) return null;
  return mytable.itvtdata;
}

var navsize = 8;

RClient.DragTable = Class.create();
RClient.DragTable.prototype = Object.extend(new RClient.ElementComponent(),{

  initialize : function(name,lh,url) {    
   if (!window.itvtdnd) dragdropinit();

   this.mytable = $(name);
   this.mytable.itvtdata = this;
          
   this.unlocked = false; 
   this.cols = new Array();  
   this.errors = new Array();
   this.url = url;
   this.defaultheight = lh;
   this.name = name;

   var heads = findChild(this.mytable,"DIV");
   if (heads==null) return; 
   var bodys = findNext(heads,"DIV");
   if (bodys==null) return;    
   var head = findChild(heads,"DIV");
   if (head==null) return;  
   var title = findNext(head,"DIV");
   var body = findChild(bodys,"DIV");
   var firstbody = null;
   this.heads = heads;
   if (body) firstbody = findChild(findChild(findChild(body,"TABLE"),"TBODY"),"TR");
   var index = 0;
   this.width = this.mytable.offsetWidth - 20;
   this.mode = 0; 

   this.scroller = bodys;
   this.scroller2 = findChild(bodys,"IMG");
   this.scrollindex = 0;
   
   this.saver = findChild(this.mytable,"INPUT");
   
   var recalcheight = false;
   var bodyh = 0;
   var totalw = 0;
   while (head!=null) {
     this.cols[index] = new Object();
     var item = this.cols[index];
     item.head = head;
     item.title = title;   
     item.body = body;
     item.table = findChild(body,"TABLE");
     item.index = index;
     item.defaultfixed = (head.style.zIndex == 2);
     item.fixed = item.defaultfixed;
     item.w = item.body.firstChild.offsetWidth;
     var w2 = item.head.firstChild.offsetWidth + navsize;
     if (w2>item.w) item.w = w2;
     item.x = 0;
     item.minwidth = item.w;
     item.table.style.width = "100%";    
     item.head.firstChild.style.width = "100%";
     if (!recalcheight && bodyh>0 && item.body.offsetHeight!=bodyh) { recalcheight = true;}
     if (item.body.offsetHeight > bodyh) bodyh = item.body.offsetHeight;
     if (item.table) item.syncelem = findChild(findChild(item.table,"TBODY"),"TR");
     if (item.defaultfixed) { head.style.zIndex = 1;this.updatefixed(item); }
     
     head = findNext(title,"DIV");
     if (head!=null) title = findNext(head,"DIV");
     body = findNext(body,"DIV");
     index++;
   }
   if (recalcheight) {     
     var h = 0;
     for (var i=0;i<index;i++) {
       var se = this.cols[i].syncelem;
       while (se!=null) {    
          var hn = se.offsetHeight;     
          if (hn > h) h = hn;
          se = findNext(se,"TR");
       }
     }
     this.newdefaultheight = h;
     for (var i=0;i<index;i++) {     
       var se = this.cols[i].syncelem;
       while (se!=null) {
         se.style.height = h+"px";
         findChild(se,"TD").style.height=h+"px";
         se = findNext(se,"TR");
       }       
     }
   }
   
   var errorindex = 0;
   var iterrow = 0;
 
   while (body!=null) {
     this.errors[errorindex] = body;
     var tgrow = body.offsetTop / this.defaultheight;
 
     while (iterrow < tgrow) { iterrow++; firstbody = findNext(firstbody,"TR"); }  
     body.style.top = firstbody.offsetTop+"px";
     body.style.height = firstbody.offsetHeight+"px";
     if (body.firstChild && body.firstChild.style) body.firstChild.style.height = firstbody.offsetHeight+"px";//tab.newdefaultheight+"px";
     errorindex++;
     body = findNext(body,"DIV");
   }

   var maxHeight = 0.4 * screen.availHeight;
   var h = 0;
   if (bodyh + heads.offsetHeight > maxHeight) {
     h = maxHeight;
     document.body.itvtScrollLock = true;
   }
   else {h= bodyh + heads.offsetHeight + 20;this.noiefix=true;this.width+=20;}
   this.mytable.style.height =h+"px";
   bodys.style.height = (h - heads.offsetHeight)+"px";
   bodys.style.width = this.mytable.offsetWidth+"px";
   heads.style.width = this.mytable.offsetWidth+"px";
      
   if (this.saver) this.settablepers(this.saver.value);
   
   for (var i=0;i<index;i++) totalw+=this.cols[i].w;
   
   if (index>0 && totalw+2*index<this.width) {
     this.extrawidth = Math.round((this.width-totalw-2*index)/index-0.5);    
     for (var i=0;i<index;i++) {this.cols[i].w += this.extrawidth;}     
   } else this.extrawidth = 0;
   
             
   this.unlocked = true;
   this.relayout();   
   if (window.opera) this.operatimer = window.setInterval(this.operapatch.bind(this),50);
   this.resizehandle = NodeService.connect(this.mytable,"resize",this.resize.bind(this));
  },
  
  operapatch : function() {
   var dat = tabdata(this.name);   
   if (this.scrollindex!=this.scroller.scrollLeft) {
     this.scroller.scrollTop++;
     this.relayout();
     this.scroller.scrollTop--;    
   }   
   return true;
  },
  
  relayout : function() {   
    dbg("relayout start");
    if (!this.unlocked) return;
    this.unlocked = false;
    this.scrollindex = this.scroller.scrollLeft;
    var io = this.scrollindex;
    var xo = 0;
    var co = -this.scrollindex;
    for (var i=0;i<this.cols.length;i++) {
      var item = this.cols[i];
      var special = (this.mode==2 && i==this.selected);
      if (!special) { if (item.fixed) item.x = xo; else item.x = co; }
      if (!special && (item.x < xo-item.w || item.x > this.width)) {
        item.head.style.display = "none";
        item.body.style.display = "none";
        item.title.style.display = "none";
        item.orl=-1;
        co+=item.w+2;
      } else {
        var rl = (item.x < xo && !special) ? xo - item.x : 0;
        var rr = (item.x + item.w > this.width) ? item.x + item.w - this.width : 0;
        var w = item.w - rl - rr;
      
        item.head.style.left = item.x+"px";
        item.head.style.clip = "rect(auto,"+(item.w-rr)+"px,auto,"+rl+"px)";
        item.head.style.width = item.w+"px";
        item.head.style.display = "block";      

        if (item.orl!=rl || item.orr!=rr || item.ow!=w || item.ox!=item.x+io) {        
          item.body.style.left = (item.x + io) + "px";
          if (xo==0) item.body.style.clip = "rect(auto,"+(item.w-rr)+"px,auto,auto)";
          else if (!this.noiefix) item.body.style.clip = "rect(auto,"+(item.w)+"px,auto,"+rl+"px)";
          else item.body.style.clip = "rect(auto,"+(item.w-rr)+"px,auto,"+rl+"px)";
          if (item.w>item.minwidth) item.body.style.width = item.w+"px"; else item.body.style.width = item.minwidth+"px";
          item.orl = rl;item.orr = rr;item.ow = w;item.ox = item.x+io;      
          item.body.style.display = "block";
        }
        var tx = item.x + item.w - navsize;             
        if (tx>xo && tx<=this.width) {
           item.title.style.display = "block";
           item.title.style.left = tx+"px";
        } else {
           item.title.style.display = "none";
        }      
        xo += w+2;
        co += item.w+2;      
      }     
    }
  
    for (var i=0;i<this.errors.length;i++) {
      this.errors[i].style.width = (co+this.scrollindex) + "px";
    }
  
    //this.scroller2.firstChild.style.width = (co+this.scrollindex)+"px";
    this.scroller2.style.width = (co+this.scrollindex)+"px";
    this.scroller2.style.display = "block";
    //alert(this.scroller2.innerHTML);
    //alert(this.scroller2.firstChild.style.width);
    //window.status = "co:"+(co+this.scrollindex)+" sc:"+this.scroller2.offsetWidth;
    this.unlocked = true;
    dbg("relayout-end");
  },  
  
  findcol : function(col) {
    for (var i=0;i<this.cols.length;i++) if (this.cols[i].index == col) return i;
    return 0;
  },
  
  changescroll : function(ev) {
    this.relayout();
  },
  
  changefixed : function(col) {    
     var xcol = this.findcol(col);
     var item = this.cols[xcol];
     item.fixed = !item.fixed;
     this.updatefixed(item);
     return false;
  },
  
  startsize : function(event,col) {
    this.mode = 1; 
    this.selected = this.findcol(col);
    this.startX = event.screenX+getBodyScrollLeft(window);
    this.startY = event.screenY+getBodyScrollTop(window);
    this.sizeX = this.cols[this.selected].w;
    window.itvtdnd.item = this.name;
    window.itvtdnd.up = this.endsize.bind(this);
    window.itvtdnd.move = this.changesize.bind(this);
    return false;
  },

  startpos : function(event,col) {
    this.mode = 2;
    this.selected = this.findcol(col);
    this.startX = event.screenX+getBodyScrollLeft(window);
    this.startY = event.screenY+getBodyScrollTop(window);
    var item = this.cols[this.selected];
    this.posX = item.x;
    item.head.style.zIndex = 4;
    item.body.style.zIndex = 4;
    item.title.style.zIndex = 5;  
    window.itvtdnd.item = this.name;
    window.itvtdnd.up = this.endsize.bind(this);
    window.itvtdnd.move = this.changesize.bind(this);
    return false;
  },

  endsize : function (event) {  
    if (this.mode==2) {
      var item = this.cols[this.selected]; 
      item.head.style.zIndex = 1;
      item.body.style.zIndex = 1;
      item.title.style.zIndex = 2;
      if (Math.abs(item.x-this.posX)<5) this.changefixed(item.index);
    }
    this.mode = 0;
    this.selected = -1;
    window.itvtdnd.up = null;
    window.itvtdnd.move = null;
    window.itvtdnd.item = null; 
    window.itvtdnd.source = null;
    this.relayout();
    if (this.saver) {
      this.saver.value = this.gettablepers();
      ajax(this.url,"table="+this.saver.name+"&value="+this.saver.value);
    }
    return false;
  },


  changesize : function(event) {
    if (this.mode == 1) {
      var x = event.screenX+getBodyScrollLeft(window);
      var y = event.screenY+getBodyScrollTop(window);
      var item = this.cols[this.selected];
      item.w = this.sizeX + (x - this.startX);
      if (item.w<12) item.w = 12;    
      if (timeclick) {this.relayout();timeclick = false;}
    }  else if (this.mode == 2) {
      //this.ignorecol = this.selected;
      var x = event.screenX+getBodyScrollLeft(window);
      var y = event.screenY+getBodyScrollTop(window);
      var item = this.cols[this.selected];
      item.x = this.posX + (x - this.startX);
      if (this.selected>0 && (this.cols[this.selected-1].x+this.posX)/2 > item.x) {
        this.cols[this.selected] = this.cols[this.selected-1];
        this.cols[this.selected-1] = item;
        this.selected--;
        this.relayout();
        this.startpos(event,item.index);
     } else if (this.selected<this.cols.length-1 && (this.cols[this.selected+1].x+this.posX)/2 < item.x) {
        this.cols[this.selected] = this.cols[this.selected+1];
        this.cols[this.selected+1] = item;
        this.selected++;
        this.relayout();
        this.startpos(event,item.index);
     }
     if (timeclick) {this.relayout();timeclick = false;}
   }
   return false;
  },

  updatefixed : function(item) {
    if (item.fixed) {
      item.title.style.backgroundColor = "#333367";
    } else {
      item.title.style.backgroundColor = "#c8c1ae";
    }
  },
  
  itvttableresize : function() {  
    if (!window.itvtdnd) return;
    if (!this.mytable) return false;
    if (!this.mytable.itvtdata) return;          
    if (!this.unlocked) return; 
    if (this.newresize) return false;
    this.mytable.style.width="1px";     
    if (this.heads==null) return; 
    var bodys = findNext(this.heads,"DIV");
    if (bodys==null) return; 
    bodys.style.width = "1px";
    this.heads.style.width = "1px"; 
    this.mytable.style.width="100%";     
    this.width = this.mytable.offsetWidth - 20;   
    bodys.style.width = this.mytable.offsetWidth+"px";
    this.heads.style.width = this.mytable.offsetWidth+"px";   
    this.relayout();     
    return true;
  },
  
  resize : function() {
   this.newresize = true;
   this.width = this.mytable.offsetWidth - 20;    
   if (this.heads==null) return; 
   var bodys = findNext(this.heads,"DIV");
   if (bodys==null) return; 
   bodys.style.width = this.mytable.offsetWidth+"px";
   this.heads.style.width = this.mytable.offsetWidth+"px";   
   var h = parseInt(this.mytable.style.height);
   bodys.style.height = (h - this.heads.offsetHeight)+"px";
   this.relayout();   
  },
  
  gettablepers : function() {
   var result = this.cols.length+":";
   var interest ="F";
   for (var i=0;i<this.cols.length;i++) {
     var item = this.cols[i];
     var w1 = (item.w>=item.minwidth-2 && item.w<=item.minwidth+this.extrawidth+2) ? -1 : item.w;
     var w2 = (w1==-1) ? -1 : item.minwidth;
     if (w1!=-1 || item.fixed!=item.defaultfixed) interest = "T";
     if (item.index!=i) interest = "T";
     result += item.index+":"+w1+":"+w2+":"+(item.fixed?"T":"F")+":";
   }
   result+=interest;   
   return result;
  },

  settablepers : function(pers) {
    //alert("set:"+pers);

    var pd = pers.split(":");
    if (pd.length==0) return;
    if (Math.abs(pd[0])!=Math.abs(this.cols.length)) return;
    var oldcols = this.cols;
    this.cols = new Array(oldcols.length);
    var idx = 1;
    for (var i=0;i<oldcols.length;i++) {
      var item = oldcols[pd[idx]];
      this.cols[i] = item;
      if (pd[idx+3]=="T") item.fixed = true; else item.fixed = false;
      this.updatefixed(item);
      if (item.minwidth<=Math.abs(pd[idx+1])) item.w = Math.abs(pd[idx+1]);
      else if (Math.abs(pd[idx+2])>Math.abs(pd[idx+1])) item.w = Math.abs(pd[idx+1]);    
      idx+=4;
    }
  },
          
  _destroy : function() {
    if (this.operatimer) window.clearInterval(this.operatimer);
    this.operatimer = null;    
    NodeService.deconnect(this.mytable,"resize",this.resizehandle);
    this.resizehandle = null;
    this.mytable = null;
    this.heads = null;
  }

}); 

    var MapsExtension = Class.create();
    
    MapsExtension.System = Class.create();
    MapsExtension.System.prototype = {
    
      initialize : function(postload) {      
        google.load("maps","2.115",{"callback": postload});
      }
      
    };
        
    MapsExtension.Map = Class.create();
    MapsExtension.Map.prototype = {
    
      initialize : function(divid,x,y,zoom,typ) {
        this.allowresize = false;
        if (google.maps.BrowserIsCompatible()) {
         try {
          this.mydiv = $(divid);
          this.mymap = new google.maps.Map2(this.mydiv);  
          this.mymap.addControl(new google.maps.LargeMapControl());  
          //this.mymap.addControl(new google.maps.OverviewMapControl()); 
          this.mymap.setCenter(new google.maps.LatLng(x, y), zoom);                
          this.geocoder = new google.maps.ClientGeocoder();   
          this.markers = []; 
          if (this.mydiv.itvtresizer) this.mydiv.itvtresizer.onresize = this.resize.bind(this);
          if (this.mydiv.itvtresizer2) this.mydiv.itvtresizer2.onresize = this.resize.bind(this);          
          this.allowresize = true;
         } catch (e) { dbg("init-error:"+e); }
        }
      },
      
      zoomIn : function() {
        this.mymap.zoomIn();
      },
      
      zoomOut : function() {
        this.mymap.zoomOut();
      },
      
      lookup : function(input) {
        var my = this;
        this.geocoder.getLatLng(
          input,
          function(point) {
           if (!point) {
            alert(input + " not found");
           } else {
            my.mymap.setCenter(point, 14);
            my.clickHandler(null,point);            
           }
          }
        );
      },
            
      addClickHandler : function(aobj) {
        this.clickaobj = aobj;
        google.maps.Event.addListener(this.mymap,"click",this.clickHandler.bind(this));
      },
      
      clickHandler : function(overlay,point) {
       if (point) {
         var event = new MapsExtension.Event();
         event.x = point.lat();
         event.y = point.lng();
         tr_trigger(this.clickaobj.key,event);
       }
      },
      
      clearMarkers : function() {
       try {
         this.mymap.clearOverlays();
         this.markers.clear();
       } catch (e) {dbg("ERROR:"+e);}
      },
      
      addMarker : function(x,y,icon,aobjkey) {
        var marker;
        if (icon) {           
          var specialIcon = new google.maps.Icon(google.maps.DEFAULT_ICON);
          specialIcon.image = icon;//"http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";                
          var markerOptions = { icon:specialIcon };
          marker = new google.maps.Marker(new google.maps.LatLng(x,y), markerOptions);
        } else {
          marker = new google.maps.Marker(new google.maps.LatLng(x,y));
        }
        if (aobjkey!=null) {
          google.maps.Event.addListener(marker,"click",function() { aocall(aobjkey).trigger(); });
          this.markers[aobjkey] = marker;
        }
        this.mymap.addOverlay(marker);        
      },
            
      markersDone : function() {
      },
                  
      addPolyline : function(color,boldness,coords) {
        var polyline = new google.maps.Polyline(coords,color,boldness);
        this.mymap.addOverlay(polyline);
        return polyline;
      },
      
      removePolyline : function(polyline) {
        
      },
      
      appendToPolyline : function(polyline,x,y) {
        polyline.insertVertex(polyline.getVertexCount(),MEXY(x,y));
      },
      
      setInfoWindow : function(x,y,text) {
        this.mymap.openInfoWindowHtml(new google.maps.LatLng(x,y),text);
      },
      
      setInfoWindowMarker : function(aobjkey,text) {
        var m = this.markers[aobjkey];
        if (m) {
          m.openInfoWindowHtml(text);
        }
      },
      
      setInfoWindowNode : function(x,y,node) {
        var mynode = $(node);
        if (mynode==null) mynode = this.lastdiv;
        else {
         mynode.parentNode.removeChild(mynode);
        }
        this.lastdiv = mynode;        
        this.mymap.openInfoWindow(new google.maps.LatLng(x,y),mynode);
      },
      
      resize : function() {
       if (this.allowresize) {
        try { this.mymap.checkResize(); } catch(e) { dbg("ERROR:"+e); }
       }
      }
      
    };
    
    MapsExtension.Event = Class.create();
    MapsExtension.Event.prototype = {
     
      initialize : function() {}
      
    };
    
    function MEXY(x,y) {
      return new google.maps.LatLng(x,y);
    }


var baseurl = "/abox";
var errorurl = baseurl+"/repair.do";
var debugmode = false;  