﻿/*  Prototype JavaScript framework, version 1.3.1
*  (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.3.1',
    emptyFunction: function() { }
}

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.prototype.extend = function(object) {
    return Object.extend.apply(this, [this, object]);
}

Function.prototype.bind = function(object) {
    var __method = this;
    return function() {
        __method.apply(object, arguments);
    }
}

Function.prototype.bindAsEventListener = function(object) {
    var __method = this;
    return function(event) {
        __method.call(object, event || window.event);
    }
}

Number.prototype.toColorPart = function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
}

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;
}

if (!Array.prototype.push) {
    Array.prototype.push = function() {
        var startLength = this.length;
        for (var i = 0; i < arguments.length; i++)
            this[startLength + i] = arguments[i];
        return this.length;
    }
}

if (!Function.prototype.apply) {
    // Based on code from http://www.youngpup.net/
    Function.prototype.apply = function(object, parameters) {
        var parameterStrings = new Array();
        if (!object) object = window;
        if (!parameters) parameters = new Array();

        for (var i = 0; i < parameters.length; i++)
            parameterStrings[i] = 'parameters[' + i + ']';

        object.__apply__ = this;
        var result = eval('object.__apply__(' +
      parameterStrings.join(', ') + ')');
        object.__apply__ = null;

        return result;
    }
}

String.prototype.extend({
    stripTags: function() {
        return this.replace(/<\/?[^>]+>/gi, '');
    },

    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].nodeValue;
    }
});

var Ajax = {
    getTransport: function() {
        return Try.these(
      function() { return new ActiveXObject('Msxml2.XMLHTTP') },
      function() { return new ActiveXObject('Microsoft.XMLHTTP') },
      function() { return new XMLHttpRequest() }
    ) || false;
    }
}

Ajax.Base = function() { };
Ajax.Base.prototype = {
    setOptions: function(options) {
        this.options = {
            method: 'post',
            asynchronous: true,
            parameters: ''
}.extend(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 = (new Ajax.Base()).extend({
        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 {
                if (this.options.method == 'get')
                    url += '?' + parameters;

                this.transport.open(this.options.method, 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) {
            }
        },

        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);
        },

        respondToReadyState: function(readyState) {
            var event = Ajax.Request.Events[readyState];

            if (event == 'Complete')
                (this.options['on' + this.transport.status]
       || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
       || Prototype.emptyFunction)(this.transport);

            (this.options['on' + event] || Prototype.emptyFunction)(this.transport);

            /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
            if (event == 'Complete')
                this.transport.onreadystatechange = Prototype.emptyFunction;
        }
    });

    Ajax.Updater = Class.create();
    Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';

    Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
        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() {
                this.updateContent();
                onComplete(this.transport);
            }).bind(this);

            this.request(url);
        },

        updateContent: function() {
            var receiver = this.responseIsSuccess() ?
      this.containers.success : this.containers.failure;

            var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');
            var response = this.transport.responseText.replace(match, '');
            var scripts = this.transport.responseText.match(match);

            if (receiver) {
                if (this.options.insertion) {
                    new this.options.insertion(receiver, response);
                } else {
                    receiver.innerHTML = response;
                }
            }

            if (this.responseIsSuccess()) {
                if (this.onComplete)
                    setTimeout((function() {
                        this.onComplete(
          this.transport)
                    }).bind(this), 10);
            }

            if (this.options.evalScripts && scripts) {
                match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
                setTimeout((function() {
                    for (var i = 0; i < scripts.length; i++)
                        eval(scripts[i].match(match)[1]);
                }).bind(this), 10);
            }
        }
    });

    Ajax.PeriodicalUpdater = Class.create();
    Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
        initialize: function(container, url, options) {
            this.setOptions(options);
            this.onComplete = this.options.onComplete;

            this.frequency = (this.options.frequency || 2);
            this.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 || Ajax.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) {
        var children = document.getElementsByTagName('*') || document.all;
        var elements = new Array();

        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var classNames = child.className.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    elements.push(child);
                    break;
                }
            }
        }

        return elements;
    }

    /*--------------------------------------------------------------------------*/

    if (!window.Element) {
        var Element = new Object();
    }

    Object.extend(Element, {
        toggle: function() {
            for (var i = 0; i < arguments.length; i++) {
                var element = $(arguments[i]);
                element.style.display =
        (element.style.display == 'none' ? '' : 'none');
            }
        },

        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);
        },

        getHeight: function(element) {
            element = $(element);
            return element.offsetHeight;
        },

        hasClassName: function(element, className) {
            element = $(element);
            if (!element)
                return;
            var a = element.className.split(' ');
            for (var i = 0; i < a.length; i++) {
                if (a[i] == className)
                    return true;
            }
            return false;
        },

        addClassName: function(element, className) {
            element = $(element);
            Element.removeClassName(element, className);
            element.className += ' ' + className;
        },

        removeClassName: function(element, className) {
            element = $(element);
            if (!element)
                return;
            var newClassName = '';
            var a = element.className.split(' ');
            for (var i = 0; i < a.length; i++) {
                if (a[i] != className) {
                    if (i > 0)
                        newClassName += ' ';
                    newClassName += a[i];
                }
            }
            element.className = newClassName;
        },

        // removes whitespace-only text node children
        cleanWhitespace: function(element) {
            var 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);
            }
        }
    });

    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;

            if (this.adjacency && this.element.insertAdjacentHTML) {
                this.element.insertAdjacentHTML(this.adjacency, this.content);
            } else {
                this.range = this.element.ownerDocument.createRange();
                if (this.initializeRange) this.initializeRange();
                this.fragment = this.range.createContextualFragment(this.content);
                this.insertContent();
            }
        }
    }

    var Insertion = new Object();

    Insertion.Before = Class.create();
    Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
        initializeRange: function() {
            this.range.setStartBefore(this.element);
        },

        insertContent: function() {
            this.element.parentNode.insertBefore(this.fragment, this.element);
        }
    });

    Insertion.Top = Class.create();
    Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
        initializeRange: function() {
            this.range.selectNodeContents(this.element);
            this.range.collapse(true);
        },

        insertContent: function() {
            this.element.insertBefore(this.fragment, this.element.firstChild);
        }
    });

    Insertion.Bottom = Class.create();
    Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
        initializeRange: function() {
            this.range.selectNodeContents(this.element);
            this.range.collapse(this.element);
        },

        insertContent: function() {
            this.element.appendChild(this.fragment);
        }
    });

    Insertion.After = Class.create();
    Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
        initializeRange: function() {
            this.range.setStartAfter(this.element);
        },

        insertContent: function() {
            this.element.parentNode.insertBefore(this.fragment,
      this.element.nextSibling);
        }
    });

    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).focus();
            $(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) {
            var 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) {
            var 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 = '';
            }
        },

        focusFirstElement: function(form) {
            var form = $(form);
            var elements = Form.getElements(form);
            for (var i = 0; i < elements.length; i++) {
                var element = elements[i];
                if (element.type != 'hidden' && !element.disabled) {
                    Field.activate(element);
                    break;
                }
            }
        },

        reset: function(form) {
            $(form).reset();
        }
    }

    Form.Element = {
        serialize: function(element) {
            var element = $(element);
            var method = element.tagName.toLowerCase();
            var parameter = Form.Element.Serializers[method](element);

            if (parameter)
                return encodeURIComponent(parameter[0]) + '=' +
        encodeURIComponent(parameter[1]);
        },

        getValue: function(element) {
            var 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) {
            var value = '';
            if (element.type == 'select-one') {
                var index = element.selectedIndex;
                if (index >= 0)
                    value = element.options[index].value || element.options[index].text;
            } else {
                value = new Array();
                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 = (new Abstract.TimedObserver()).extend({
        getValue: function() {
            return Form.Element.getValue(this.element);
        }
    });

    Form.Observer = Class.create();
    Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
        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':
                        element.target = this;
                        element.prev_onclick = element.onclick || Prototype.emptyFunction;
                        element.onclick = function() {
                            this.prev_onclick();
                            this.target.onElementEvent();
                        }
                        break;
                    case 'password':
                    case 'text':
                    case 'textarea':
                    case 'select-one':
                    case 'select-multiple':
                        element.target = this;
                        element.prev_onchange = element.onchange || Prototype.emptyFunction;
                        element.onchange = function() {
                            this.prev_onchange();
                            this.target.onElementEvent();
                        }
                        break;
                }
            }
        }
    }

    Form.Element.EventObserver = Class.create();
    Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
        getValue: function() {
            return Form.Element.getValue(this.element);
        }
    });

    Form.EventObserver = Class.create();
    Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
        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;
            }
        },

        // 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.indexOf('AppleWebKit') > 0)
        || 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.indexOf('AppleWebKit') > 0)
        || 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];
        },

        // 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';
        }
    }
