/*  Prototype JavaScript framework, version 1.4.0 *  (c) 2005 Sam Stephenson <sam@conio.net> * *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff *  against the source tree, available from the Prototype darcs repository. * *  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.4.0',    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 (property in source) {        destination[property] = source[property];    }    return destination;}Object.inspect = function(object) {    try {        if (object == undefined) return 'undefined';        if (object == null) return 'null';        return object.inspect ? object.inspect() : object.toString();    } catch (e) {        if (e instanceof RangeError) return '...';        throw e;    }}Function.prototype.bind = function() {    var __method = this, args = $A(arguments), object = args.shift();    return function() {        return __method.apply(object, args.concat($A(arguments)));    }}Function.prototype.bindAsEventListener = function(object) {    var __method = this;    return function(event) {        return __method.call(object, event || window.event);    }}Object.extend(Number.prototype, {    toColorPart: function() {        var digits = this.toString(16);        if (this < 16) return '0' + digits;        return digits;    },    succ: function() {        return this + 1;    },    times: function(iterator) {        $R(0, this, true).each(iterator);        return this;    }});var Try = {    these: function() {        var returnValue;        for (var i = 0; i < arguments.length; i++) {            var lambda = arguments[i];            try {                returnValue = lambda();                break;            } catch (e) {            }        }        return returnValue;    }}/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = {    initialize: function(callback, frequency) {        this.callback = callback;        this.frequency = frequency;        this.currentlyExecuting = false;        this.registerCallback();    },    registerCallback: function() {        setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);    },    onTimerEvent: function() {        if (!this.currentlyExecuting) {            try {                this.currentlyExecuting = true;                this.callback();            } finally {                this.currentlyExecuting = false;            }        }    }}/*--------------------------------------------------------------------------*/function $() {    var elements = new Array();    for (var i = 0; i < arguments.length; i++) {        var element = arguments[i];        if (typeof element == 'string')            element = document.getElementById(element);        if (arguments.length == 1)            return element;        elements.push(element);    }    return elements;}Object.extend(String.prototype, {    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(eval);    },    escapeHTML: function() {        var div = document.createElement('div');        var text = document.createTextNode(this);        div.appendChild(text);        return div.innerHTML;    },    unescapeHTML: function() {        var div = document.createElement('div');        div.innerHTML = this.stripTags();        return div.childNodes[0] ? div.childNodes[0].nodeValue : '';    },    toQueryParams: function() {        var pairs = this.match(/^\??(.*)$/)[1].split('&');        return pairs.inject({}, function(params, pairString) {            var pair = pairString.split('=');            params[pair[0]] = pair[1];            return params;        });    },    toArray: function() {        return this.split('');    },    camelize: function() {        var oStringList = this.split('-');        if (oStringList.length == 1) return oStringList[0];        var camelizedString = this.indexOf('-') == 0                ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)                : oStringList[0];        for (var i = 1, len = oStringList.length; i < len; i++) {            var s = oStringList[i];            camelizedString += s.charAt(0).toUpperCase() + s.substring(1);        }        return camelizedString;    },    inspect: function() {        return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";    }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = {    each: function(iterator) {        var index = 0;        try {            this._each(function(value) {                try {                    iterator(value, index++);                } catch (e) {                    if (e != $continue) throw e;                }            });        } catch (e) {            if (e != $break) throw e;        }    },    all: function(iterator) {        var result = true;        this.each(function(value, index) {            result = result && !!(iterator || Prototype.K)(value, index);            if (!result) throw $break;        });        return result;    },    any: function(iterator) {        var result = true;        this.each(function(value, index) {            if (result = !!(iterator || Prototype.K)(value, index))                throw $break;        });        return result;    },    collect: function(iterator) {        var results = [];        this.each(function(value, index) {            results.push(iterator(value, index));        });        return results;    },    detect: function (iterator) {        var result;        this.each(function(value, index) {            if (iterator(value, index)) {                result = value;                throw $break;            }        });        return result;    },    findAll: function(iterator) {        var results = [];        this.each(function(value, index) {            if (iterator(value, index))                results.push(value);        });        return results;    },    grep: function(pattern, iterator) {        var results = [];        this.each(function(value, index) {            var stringValue = value.toString();            if (stringValue.match(pattern))                results.push((iterator || Prototype.K)(value, index));        })        return results;    },    include: function(object) {        var found = false;        this.each(function(value) {            if (value == object) {                found = true;                throw $break;            }        });        return found;    },    inject: function(memo, iterator) {        this.each(function(value, index) {            memo = iterator(memo, value, index);        });        return memo;    },    invoke: function(method) {        var args = $A(arguments).slice(1);        return this.collect(function(value) {            return value[method].apply(value, args);        });    },    max: function(iterator) {        var result;        this.each(function(value, index) {            value = (iterator || Prototype.K)(value, index);            if (value >= (result || value))                result = value;        });        return result;    },    min: function(iterator) {        var result;        this.each(function(value, index) {            value = (iterator || Prototype.K)(value, index);            if (value <= (result || value))                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) {            iterator(value = collections.pluck(index));            return value;        });    },    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);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.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();    },    shift: function() {        var result = this[0];        for (var i = 0; i < this.length - 1; i++)            this[i] = this[i + 1];        this.length--;        return result;    },    inspect: function() {        return '[' + this.map(Object.inspect).join(', ') + ']';    }});var Hash = {    _each: function(iterator) {        for (key in this) {            var value = this[key];            if (typeof value == 'function') continue;            var pair = [key, value];            pair.key = key;            pair.value = value;            iterator(pair);        }    },    keys: function() {        return this.pluck('key');    },    values: function() {        return this.pluck('value');    },    merge: function(hash) {        return $H(hash).inject($H(this), function(mergedHash, pair) {            mergedHash[pair.key] = pair.value;            return mergedHash;        });    },    toQueryString: function() {        return this.map(function(pair) {            return pair.map(encodeURIComponent).join('=');        }).join('&');    },    inspect: function() {        return '#<Hash:{' + this.map(function(pair) {            return pair.map(Object.inspect).join(': ');        }).join(', ') + '}>';    }}function $H(object) {    var hash = Object.extend({}, object || {});    Object.extend(hash, Enumerable);    Object.extend(hash, Hash);    return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, {    initialize: function(start, end, exclusive) {        this.start = start;        this.end = end;        this.exclusive = exclusive;    },    _each: function(iterator) {        var value = this.start;        do {            iterator(value);            value = value.succ();        } while (this.include(value));    },    include: function(value) {        if (value < this.start)            return false;        if (this.exclusive)            return value < this.end;        return value <= this.end;    }});var $R = function(start, end, exclusive) {    return new ObjectRange(start, end, exclusive);}var Ajax = {    getTransport: function() {        return Try.these(                function() {                    return new ActiveXObject('Msxml2.XMLHTTP')                },                function() {                    return new ActiveXObject('Microsoft.XMLHTTP')                },                function() {                    return new XMLHttpRequest()                }                ) || 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,            parameters:   ''        }        Object.extend(this.options, options || {});    },    responseIsSuccess: function() {        return this.transport.status == undefined                || this.transport.status == 0                || (this.transport.status >= 200 && this.transport.status < 300);    },    responseIsFailure: function() {        return !this.responseIsSuccess();    }}Ajax.Request = Class.create();Ajax.Request.Events =['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), {    initialize: function(url, options) {        this.transport = Ajax.getTransport();        this.setOptions(options);        this.request(url);    },    request: function(url) {        var parameters = this.options.parameters || '';        if (parameters.length > 0) parameters += '&_=';        try {            this.url = url;            if (this.options.method == 'get' && parameters.length > 0)                this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;            Ajax.Responders.dispatch('onCreate', this, this.transport);            this.transport.open(this.options.method, this.url,                    this.options.asynchronous);            if (this.options.asynchronous) {                this.transport.onreadystatechange = this.onStateChange.bind(this);                setTimeout((function() {                    this.respondToReadyState(1)                }).bind(this), 10);            }            this.setRequestHeaders();            var body = this.options.postBody ? this.options.postBody : parameters;            this.transport.send(this.options.method == 'post' ? body : null);        } catch (e) {            this.dispatchException(e);        }    },    setRequestHeaders: function() {        var requestHeaders =                ['X-Requested-With', 'XMLHttpRequest',                        'X-Prototype-Version', Prototype.Version];        if (this.options.method == 'post') {            requestHeaders.push('Content-type',                    'application/x-www-form-urlencoded');            /* Force "Connection: close" for Mozilla browsers to work around            * a bug where XMLHttpReqeuest sends an incorrect Content-length            * header. See Mozilla Bugzilla #246651.            */            if (this.transport.overrideMimeType)                requestHeaders.push('Connection', 'close');        }        if (this.options.requestHeaders)            requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);        for (var i = 0; i < requestHeaders.length; i += 2)            this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i + 1]);    },    onStateChange: function() {        var readyState = this.transport.readyState;        if (readyState != 1)            this.respondToReadyState(this.transport.readyState);    },    header: function(name) {        try {            return this.transport.getResponseHeader(name);        } catch (e) {        }    },    evalJSON: function() {        try {            return eval(this.header('X-JSON'));        } catch (e) {        }    },    evalResponse: function() {        try {            return eval(this.transport.responseText);        } catch (e) {            this.dispatchException(e);        }    },    respondToReadyState: function(readyState) {        var event = Ajax.Request.Events[readyState];        var transport = this.transport, json = this.evalJSON();        if (event == 'Complete') {            try {                (this.options['on' + this.transport.status]                        || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]                        || Prototype.emptyFunction)(transport, json);            } catch (e) {                this.dispatchException(e);            }            if ((this.header('Content-type') || '').match(/^text\/javascript/i))                this.evalResponse();        }        try {            (this.options['on' + event] || Prototype.emptyFunction)(transport, json);            Ajax.Responders.dispatch('on' + event, this, transport, json);        } catch (e) {            this.dispatchException(e);        }        /* Avoid memory leak in MSIE: clean up the oncomplete event handler */        if (event == 'Complete')            this.transport.onreadystatechange = Prototype.emptyFunction;    },    dispatchException: function(exception) {        (this.options.onException || Prototype.emptyFunction)(this, exception);        Ajax.Responders.dispatch('onException', this, exception);    }});Ajax.Updater = Class.create();Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {    initialize: function(container, url, options) {        this.containers = {            success: container.success ? $(container.success) : $(container),            failure: container.failure ? $(container.failure) :                     (container.success ? null : $(container))        }        this.transport = Ajax.getTransport();        this.setOptions(options);        var onComplete = this.options.onComplete || Prototype.emptyFunction;        this.options.onComplete = (function(transport, object) {            this.updateContent();            onComplete(transport, object);        }).bind(this);        this.request(url);    },    updateContent: function() {        var receiver = this.responseIsSuccess() ?                       this.containers.success : this.containers.failure;        var response = this.transport.responseText;        if (!this.options.evalScripts)            response = response.stripScripts();        if (receiver) {            if (this.options.insertion) {                new this.options.insertion(receiver, response);            } else {                Element.update(receiver, response);            }        }        if (this.responseIsSuccess()) {            if (this.onComplete)                setTimeout(this.onComplete.bind(this), 10);        }    }});Ajax.PeriodicalUpdater = Class.create();Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {    initialize: function(container, url, options) {        this.setOptions(options);        this.onComplete = this.options.onComplete;        this.frequency = (this.options.frequency || 2);        this.decay = (this.options.decay || 1);        this.updater = {};        this.container = container;        this.url = url;        this.start();    },    start: function() {        this.options.onComplete = this.updateComplete.bind(this);        this.onTimerEvent();    },    stop: function() {        this.updater.onComplete = undefined;        clearTimeout(this.timer);        (this.onComplete || Prototype.emptyFunction).apply(this, arguments);    },    updateComplete: function(request) {        if (this.options.decay) {            this.decay = (request.responseText == this.lastText ?                          this.decay * this.options.decay : 1);            this.lastText = request.responseText;        }        this.timer = setTimeout(this.onTimerEvent.bind(this),                this.decay * this.frequency * 1000);    },    onTimerEvent: function() {        this.updater = new Ajax.Updater(this.container, this.url, this.options);    }});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(child);        return elements;    });}/*--------------------------------------------------------------------------*/if (!window.Element) {    var Element = new Object();}Object.extend(Element, {    visible: function(element) {        return $(element).style.display != 'none';    },    toggle: function() {        for (var i = 0; i < arguments.length; i++) {            var element = $(arguments[i]);            Element[Element.visible(element) ? 'hide' : 'show'](element);        }    },    hide: function() {        for (var i = 0; i < arguments.length; i++) {            var element = $(arguments[i]);            element.style.display = 'none';        }    },    show: function() {        for (var i = 0; i < arguments.length; i++) {            var element = $(arguments[i]);            element.style.display = '';        }    },    remove: function(element) {        element = $(element);        element.parentNode.removeChild(element);    },    update: function(element, html) {        $(element).innerHTML = html.stripScripts();        setTimeout(function() {            html.evalScripts()        }, 10);    },    getHeight: function(element) {        element = $(element);        return element.offsetHeight;    },    classNames: function(element) {        return new Element.ClassNames(element);    },    hasClassName: function(element, className) {        if (!(element = $(element))) return;        return Element.classNames(element).include(className);    },    addClassName: function(element, className) {        if (!(element = $(element))) return;        return Element.classNames(element).add(className);    },    removeClassName: function(element, className) {        if (!(element = $(element))) return;        return Element.classNames(element).remove(className);    },// removes whitespace-only text node children    cleanWhitespace: function(element) {        element = $(element);        for (var i = 0; i < element.childNodes.length; i++) {            var node = element.childNodes[i];            if (node.nodeType == 3 && !/\S/.test(node.nodeValue))                Element.remove(node);        }    },    empty: function(element) {        return $(element).innerHTML.match(/^\s*$/);    },    scrollTo: function(element) {        element = $(element);        var x = element.x ? element.x : element.offsetLeft,                y = element.y ? element.y : element.offsetTop;        window.scrollTo(x, y);    },    getStyle: function(element, style) {        element = $(element);        var value = element.style[style.camelize()];        if (!value) {            if (document.defaultView && document.defaultView.getComputedStyle) {                var css = document.defaultView.getComputedStyle(element, null);                value = css ? css.getPropertyValue(style) : null;            } else if (element.currentStyle) {                value = element.currentStyle[style.camelize()];            }        }        if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))            if (Element.getStyle(element, 'position') == 'static') value = 'auto';        return value == 'auto' ? null : value;    },    setStyle: function(element, style) {        element = $(element);        for (name in style)            element.style[name.camelize()] = style[name];    },    getDimensions: function(element) {        element = $(element);        if (Element.getStyle(element, 'display') != 'none')            return {width: element.offsetWidth, height: element.offsetHeight};        // All *Width and *Height properties give 0 on elements with display none,        // so enable the element temporarily        var els = element.style;        var originalVisibility = els.visibility;        var originalPosition = els.position;        els.visibility = 'hidden';        els.position = 'absolute';        els.display = '';        var originalWidth = element.clientWidth;        var originalHeight = element.clientHeight;        els.display = 'none';        els.position = originalPosition;        els.visibility = originalVisibility;        return {width: originalWidth, height: originalHeight};    },    makePositioned: function(element) {        element = $(element);        var pos = Element.getStyle(element, 'position');        if (pos == 'static' || !pos) {            element._madePositioned = true;            element.style.position = 'relative';            // Opera returns the offset relative to the positioning context, when an            // element is position relative but top and left have not been defined            if (window.opera) {                element.style.top = 0;                element.style.left = 0;            }        }    },    undoPositioned: function(element) {        element = $(element);        if (element._madePositioned) {            element._madePositioned = undefined;            element.style.position =            element.style.top =            element.style.left =            element.style.bottom =            element.style.right = '';        }    },    makeClipping: function(element) {        element = $(element);        if (element._overflow) return;        element._overflow = element.style.overflow;        if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')            element.style.overflow = 'hidden';    },    undoClipping: function(element) {        element = $(element);        if (element._overflow) return;        element.style.overflow = element._overflow;        element._overflow = undefined;    }});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) {                if (this.element.tagName.toLowerCase() == 'tbody') {                    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 Field = {    clear: function() {        for (var i = 0; i < arguments.length; i++)            $(arguments[i]).value = '';    },    focus: function(element) {        $(element).focus();    },    present: function() {        for (var i = 0; i < arguments.length; i++)            if ($(arguments[i]).value == '') return false;        return true;    },    select: function(element) {        $(element).select();    },    activate: function(element) {        element = $(element);        element.focus();        if (element.select)            element.select();    }}/*--------------------------------------------------------------------------*/var Form = {    serialize: function(form) {        var elements = Form.getElements($(form));        var queryComponents = new Array();        for (var i = 0; i < elements.length; i++) {            var queryComponent = Form.Element.serialize(elements[i]);            if (queryComponent)                queryComponents.push(queryComponent);        }        return queryComponents.join('&');    },    getElements: function(form) {        form = $(form);        var elements = new Array();        for (tagName in Form.Element.Serializers) {            var tagElements = form.getElementsByTagName(tagName);            for (var j = 0; j < tagElements.length; j++)                elements.push(tagElements[j]);        }        return elements;    },    getInputs: function(form, typeName, name) {        form = $(form);        var inputs = form.getElementsByTagName('input');        if (!typeName && !name)            return inputs;        var matchingInputs = new Array();        for (var i = 0; i < inputs.length; i++) {            var input = inputs[i];            if ((typeName && input.type != typeName) ||                (name && input.name != name))                continue;            matchingInputs.push(input);        }        return matchingInputs;    },    disable: function(form) {        var elements = Form.getElements(form);        for (var i = 0; i < elements.length; i++) {            var element = elements[i];            element.blur();            element.disabled = 'true';        }    },    enable: function(form) {        var elements = Form.getElements(form);        for (var i = 0; i < elements.length; i++) {            var element = elements[i];            element.disabled = '';        }    },    findFirstElement: function(form) {        return Form.getElements(form).find(function(element) {            return element.type != 'hidden' && !element.disabled &&                   ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());        });    },    focusFirstElement: function(form) {        Field.activate(Form.findFirstElement(form));    },    reset: function(form) {        $(form).reset();    }}Form.Element = {    serialize: function(element) {        element = $(element);        var method = element.tagName.toLowerCase();        var parameter = Form.Element.Serializers[method](element);        if (parameter) {            var key = encodeURIComponent(parameter[0]);            if (key.length == 0) return;            if (parameter[1].constructor != Array)                parameter[1] = [parameter[1]];            return parameter[1].map(function(value) {                return key + '=' + encodeURIComponent(value);            }).join('&');        }    },    getValue: function(element) {        element = $(element);        var method = element.tagName.toLowerCase();        var parameter = Form.Element.Serializers[method](element);        if (parameter)            return parameter[1];    }}Form.Element.Serializers = {    input: function(element) {        switch (element.type.toLowerCase()) {            case 'submit':            case 'hidden':            case 'password':            case 'text':                return Form.Element.Serializers.textarea(element);            case 'checkbox':            case 'radio':                return Form.Element.Serializers.inputSelector(element);        }        return false;    },    inputSelector: function(element) {        if (element.checked)            return [element.name, element.value];    },    textarea: function(element) {        return [element.name, element.value];    },    select: function(element) {        return Form.Element.Serializers[element.type == 'select-one' ?                                        'selectOne' : 'selectMany'](element);    },    selectOne: function(element) {        var value = '', opt, index = element.selectedIndex;        if (index >= 0) {            opt = element.options[index];            value = opt.value;            if (!value && !('value' in opt))                value = opt.text;        }        return [element.name, value];    },    selectMany: function(element) {        var value = new Array();        for (var i = 0; i < element.length; i++) {            var opt = element.options[i];            if (opt.selected) {                var optValue = opt.value;                if (!optValue && !('value' in opt))                    optValue = opt.text;                value.push(optValue);            }        }        return [element.name, value];    }}/*--------------------------------------------------------------------------*/var $F = Form.Element.getValue;/*--------------------------------------------------------------------------*/Abstract.TimedObserver = function() {}Abstract.TimedObserver.prototype = {    initialize: function(element, frequency, callback) {        this.frequency = frequency;        this.element = $(element);        this.callback = callback;        this.lastValue = this.getValue();        this.registerCallback();    },    registerCallback: function() {        setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);    },    onTimerEvent: function() {        var value = this.getValue();        if (this.lastValue != value) {            this.callback(this.element, value);            this.lastValue = value;        }    }}Form.Element.Observer = Class.create();Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {    getValue: function() {        return Form.Element.getValue(this.element);    }});Form.Observer = Class.create();Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {    getValue: function() {        return Form.serialize(this.element);    }});/*--------------------------------------------------------------------------*/Abstract.EventObserver = function() {}Abstract.EventObserver.prototype = {    initialize: function(element, callback) {        this.element = $(element);        this.callback = callback;        this.lastValue = this.getValue();        if (this.element.tagName.toLowerCase() == 'form')            this.registerFormCallbacks();        else            this.registerCallback(this.element);    },    onElementEvent: function() {        var value = this.getValue();        if (this.lastValue != value) {            this.callback(this.element, value);            this.lastValue = value;        }    },    registerFormCallbacks: function() {        var elements = Form.getElements(this.element);        for (var i = 0; i < elements.length; i++)            this.registerCallback(elements[i]);    },    registerCallback: function(element) {        if (element.type) {            switch (element.type.toLowerCase()) {                case 'checkbox':                case 'radio':                    Event.observe(element, 'click', this.onElementEvent.bind(this));                    break;                case 'password':                case 'text':                case 'textarea':                case 'select-one':                case 'select-multiple':                    Event.observe(element, 'change', this.onElementEvent.bind(this));                    break;            }        }    }}Form.Element.EventObserver = Class.create();Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {    getValue: function() {        return Form.Element.getValue(this.element);    }});Form.EventObserver = Class.create();Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {    getValue: function() {        return Form.serialize(this.element);    }});if (!window.Event) {    var Event = new Object();}Object.extend(Event, {    KEY_BACKSPACE: 8,    KEY_TAB:       9,    KEY_RETURN:   13,    KEY_ESC:      27,    KEY_LEFT:     37,    KEY_UP:       38,    KEY_RIGHT:    39,    KEY_DOWN:     40,    KEY_DELETE:   46,    element: function(event) {        return event.target || event.srcElement;    },    isLeftClick: function(event) {        return (((event.which) && (event.which == 1)) ||                ((event.button) && (event.button == 1)));    },    pointerX: function(event) {        return event.pageX || (event.clientX +                               (document.documentElement.scrollLeft || document.body.scrollLeft));    },    pointerY: function(event) {        return event.pageY || (event.clientY +                               (document.documentElement.scrollTop || document.body.scrollTop));    },    stop: function(event) {        if (event.preventDefault) {            event.preventDefault();            event.stopPropagation();        } else {            event.returnValue = false;            event.cancelBubble = true;        }    },// find the first node with the given tagName, starting from the// node the event was triggered on; traverses the DOM upwards    findElement: function(event, tagName) {        var element = Event.element(event);        while (element.parentNode && (!element.tagName ||                                      (element.tagName.toUpperCase() != tagName.toUpperCase())))            element = element.parentNode;        return element;    },    observers: false,    _observeAndCache: function(element, name, observer, useCapture) {        if (!this.observers) this.observers = [];        if (element.addEventListener) {            this.observers.push([element, name, observer, useCapture]);            element.addEventListener(name, observer, useCapture);        } else if (element.attachEvent) {            this.observers.push([element, name, observer, useCapture]);            element.attachEvent('on' + name, observer);        }    },    unloadCache: function() {        if (!Event.observers) return;        for (var i = 0; i < Event.observers.length; i++) {            Event.stopObserving.apply(this, Event.observers[i]);            Event.observers[i][0] = null;        }        Event.observers = false;    },    observe: function(element, name, observer, useCapture) {        var element = $(element);        useCapture = useCapture || false;        if (name == 'keypress' &&            (navigator.appVersion.match(/Konqueror|Safari|KHTML/)                    || element.attachEvent))            name = 'keydown';        this._observeAndCache(element, name, observer, useCapture);    },    stopObserving: function(element, name, observer, useCapture) {        var element = $(element);        useCapture = useCapture || false;        if (name == 'keypress' &&            (navigator.appVersion.match(/Konqueror|Safari|KHTML/)                    || element.detachEvent))            name = 'keydown';        if (element.removeEventListener) {            element.removeEventListener(name, observer, useCapture);        } else if (element.detachEvent) {            element.detachEvent('on' + name, observer);        }    }});/* prevent memory leaks in IE */Event.observe(window, 'unload', Event.unloadCache, false);var Position = {// set to true if needed, warning: firefox performance problems// NOT neeeded for page scrolling, only if draggable contained in// scrollable elements    includeScrollOffsets: false,// must be called before calling withinIncludingScrolloffset, every time the// page is scrolled    prepare: function() {        this.deltaX = window.pageXOffset                || document.documentElement.scrollLeft                || document.body.scrollLeft                || 0;        this.deltaY = window.pageYOffset                || document.documentElement.scrollTop                || document.body.scrollTop                || 0;    },    realOffset: function(element) {        var valueT = 0, valueL = 0;        do {            valueT += element.scrollTop || 0;            valueL += element.scrollLeft || 0;            element = element.parentNode;        } while (element);        return [valueL, valueT];    },    cumulativeOffset: function(element) {        var valueT = 0, valueL = 0;        do {            valueT += element.offsetTop || 0;            valueL += element.offsetLeft || 0;            element = element.offsetParent;        } while (element);        return [valueL, valueT];    },    positionedOffset: function(element) {        var valueT = 0, valueL = 0;        do {            valueT += element.offsetTop || 0;            valueL += element.offsetLeft || 0;            element = element.offsetParent;            if (element) {                p = Element.getStyle(element, 'position');                if (p == 'relative' || p == 'absolute') break;            }        } while (element);        return [valueL, valueT];    },    offsetParent: function(element) {        if (element.offsetParent) return element.offsetParent;        if (element == document.body) return element;        while ((element = element.parentNode) && element != document.body)            if (Element.getStyle(element, 'position') != 'static')                return element;        return document.body;    },// caches x/y coordinate pair to use with overlap    within: function(element, x, y) {        if (this.includeScrollOffsets)            return this.withinIncludingScrolloffsets(element, x, y);        this.xcomp = x;        this.ycomp = y;        this.offset = this.cumulativeOffset(element);        return (y >= this.offset[1] &&                y < this.offset[1] + element.offsetHeight &&                x >= this.offset[0] &&                x < this.offset[0] + element.offsetWidth);    },    withinIncludingScrolloffsets: function(element, x, y) {        var offsetcache = this.realOffset(element);        this.xcomp = x + offsetcache[0] - this.deltaX;        this.ycomp = y + offsetcache[1] - this.deltaY;        this.offset = this.cumulativeOffset(element);        return (this.ycomp >= this.offset[1] &&                this.ycomp < this.offset[1] + element.offsetHeight &&                this.xcomp >= this.offset[0] &&                this.xcomp < this.offset[0] + element.offsetWidth);    },// within must be called directly before    overlap: function(mode, element) {        if (!mode) return 0;        if (mode == 'vertical')            return ((this.offset[1] + element.offsetHeight) - this.ycomp) /                   element.offsetHeight;        if (mode == 'horizontal')            return ((this.offset[0] + element.offsetWidth) - this.xcomp) /                   element.offsetWidth;    },    clone: function(source, target) {        source = $(source);        target = $(target);        target.style.position = 'absolute';        var offsets = this.cumulativeOffset(source);        target.style.top = offsets[1] + 'px';        target.style.left = offsets[0] + 'px';        target.style.width = source.offsetWidth + 'px';        target.style.height = source.offsetHeight + 'px';    },    page: function(forElement) {        var valueT = 0, valueL = 0;        var element = forElement;        do {            valueT += element.offsetTop || 0;            valueL += element.offsetLeft || 0;            // Safari fix            if (element.offsetParent == document.body)                if (Element.getStyle(element, 'position') == 'absolute') break;        } while (element = element.offsetParent);        element = forElement;        do {            valueT -= element.scrollTop || 0;            valueL -= element.scrollLeft || 0;        } while (element = element.parentNode);        return [valueL, valueT];    },    clone: function(source, target) {        var options = Object.extend({            setLeft:    true,            setTop:     true,            setWidth:   true,            setHeight:  true,            offsetTop:  0,            offsetLeft: 0        }, arguments[2] || {})        // find page position of source        source = $(source);        var p = Position.page(source);        // find coordinate system to use        target = $(target);        var delta = [0, 0];        var parent = null;        // delta [0,0] will do fine with position: fixed elements,        // position:absolute needs offsetParent deltas        if (Element.getStyle(target, 'position') == 'absolute') {            parent = Position.offsetParent(target);            delta = Position.page(parent);        }        // correct by body offsets (fixes Safari)        if (parent == document.body) {            delta[0] -= document.body.offsetLeft;            delta[1] -= document.body.offsetTop;        }        // set position        if (options.setLeft)   target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';        if (options.setTop)    target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';        if (options.setWidth)  target.style.width = source.offsetWidth + 'px';        if (options.setHeight) target.style.height = source.offsetHeight + 'px';    },    absolutize: function(element) {        element = $(element);        if (element.style.position == 'absolute') return;        Position.prepare();        var offsets = Position.positionedOffset(element);        var top = offsets[1];        var left = offsets[0];        var width = element.clientWidth;        var height = element.clientHeight;        element._originalLeft = left - parseFloat(element.style.left || 0);        element._originalTop = top - parseFloat(element.style.top || 0);        element._originalWidth = element.style.width;        element._originalHeight = element.style.height;        element.style.position = 'absolute';        element.style.top = top + 'px';        ;        element.style.left = left + 'px';        ;        element.style.width = width + 'px';        ;        element.style.height = height + 'px';        ;    },    relativize: function(element) {        element = $(element);        if (element.style.position == 'relative') return;        Position.prepare();        element.style.position = 'relative';        var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);        var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);        element.style.top = top + 'px';        element.style.left = left + 'px';        element.style.height = element._originalHeight;        element.style.width = element._originalWidth;    }}// Safari returns margins on body which is incorrect if the child is absolutely// positioned.  For performance reasons, redefine Position.cumulativeOffset for// KHTML/WebKit only.if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {    Position.cumulativeOffset = function(element) {        var valueT = 0, valueL = 0;        do {            valueT += element.offsetTop || 0;            valueL += element.offsetLeft || 0;            if (element.offsetParent == document.body)                if (Element.getStyle(element, 'position') == 'absolute') break;            element = element.offsetParent;        } while (element);        return [valueL, valueT];    }}