var Prototype = {
    Version: "1.7",
    Browser: (function() {
        var b = navigator.userAgent;
        var a = Object.prototype.toString.call(window.opera) == "[object Opera]";
        return {
            IE: !!window.attachEvent && !a,
            Opera: a,
            WebKit: b.indexOf("AppleWebKit/") > -1,
            Gecko: b.indexOf("Gecko") > -1 && b.indexOf("KHTML") === -1,
            MobileSafari: /Apple.*Mobile/.test(b)
        }
    })(),
    BrowserFeatures: {
        XPath: !!document.evaluate,
        SelectorsAPI: !!document.querySelector,
        ElementExtensions: (function() {
            var a = window.Element || window.HTMLElement;
            return !! (a && a.prototype)
        })(),
        SpecificElementExtensions: (function() {
            if (typeof window.HTMLDivElement !== "undefined") {
                return true
            }
            var c = document.createElement("div"),
            b = document.createElement("form"),
            a = false;
            if (c.__proto__ && (c.__proto__ !== b.__proto__)) {
                a = true
            }
            c = b = null;
            return a
        })()
    },
    ScriptFragment: "<script[^>]*>([\\S\\s]*?)<\/script>",
    JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
    emptyFunction: function() {},
    K: function(a) {
        return a
    }
};
if (Prototype.Browser.MobileSafari) {
    Prototype.BrowserFeatures.SpecificElementExtensions = false
}
var Class = (function() {
    var d = (function() {
        for (var e in {
            toString: 1
        }) {
            if (e === "toString") {
                return false
            }
        }
        return true
    })();
    function a() {}
    function b() {
        var h = null,
        g = $A(arguments);
        if (Object.isFunction(g[0])) {
            h = g.shift()
        }
        function e() {
            this.initialize.apply(this, arguments)
        }
        Object.extend(e, Class.Methods);
        e.superclass = h;
        e.subclasses = [];
        if (h) {
            a.prototype = h.prototype;
            e.prototype = new a;
            h.subclasses.push(e)
        }
        for (var f = 0, j = g.length; f < j; f++) {
            e.addMethods(g[f])
        }
        if (!e.prototype.initialize) {
            e.prototype.initialize = Prototype.emptyFunction
        }
        e.prototype.constructor = e;
        return e
    }
    function c(l) {
        var g = this.superclass && this.superclass.prototype,
        f = Object.keys(l);
        if (d) {
            if (l.toString != Object.prototype.toString) {
                f.push("toString")
            }
            if (l.valueOf != Object.prototype.valueOf) {
                f.push("valueOf")
            }
        }
        for (var e = 0, h = f.length; e < h; e++) {
            var k = f[e],
            j = l[k];
            if (g && Object.isFunction(j) && j.argumentNames()[0] == "$super") {
                var m = j;
                j = (function(n) {
                    return function() {
                        return g[n].apply(this, arguments)
                    }
                })(k).wrap(m);
                j.valueOf = m.valueOf.bind(m);
                j.toString = m.toString.bind(m)
            }
            this.prototype[k] = j
        }
        return this
    }
    return {
        create: b,
        Methods: {
            addMethods: c
        }
    }
})(); (function() {
    var D = Object.prototype.toString,
    C = "Null",
    p = "Undefined",
    w = "Boolean",
    f = "Number",
    t = "String",
    I = "Object",
    u = "[object Function]",
    z = "[object Boolean]",
    g = "[object Number]",
    m = "[object String]",
    h = "[object Array]",
    y = "[object Date]",
    j = window.JSON && typeof JSON.stringify === "function" && JSON.stringify(0) === "0" && typeof JSON.stringify(Prototype.K) === "undefined";
    function l(K) {
        switch (K) {
        case null:
            return C;
        case(void 0):
            return p
        }
        var J = typeof K;
        switch (J) {
        case "boolean":
            return w;
        case "number":
            return f;
        case "string":
            return t
        }
        return I
    }
    function A(J, L) {
        for (var K in L) {
            J[K] = L[K]
        }
        return J
    }
    function H(J) {
        try {
            if (c(J)) {
                return "undefined"
            }
            if (J === null) {
                return "null"
            }
            return J.inspect ? J.inspect() : String(J)
        } catch(K) {
            if (K instanceof RangeError) {
                return "..."
            }
            throw K
        }
    }
    function E(J) {
        return G("", {
            "": J
        },
        [])
    }
    function G(S, P, Q) {
        var R = P[S],
        O = typeof R;
        if (l(R) === I && typeof R.toJSON === "function") {
            R = R.toJSON(S)
        }
        var L = D.call(R);
        switch (L) {
        case g:
        case z:
        case m:
            R = R.valueOf()
        }
        switch (R) {
        case null:
            return "null";
        case true:
            return "true";
        case false:
            return "false"
        }
        O = typeof R;
        switch (O) {
        case "string":
            return R.inspect(true);
        case "number":
            return isFinite(R) ? String(R) : "null";
        case "object":
            for (var K = 0, J = Q.length; K < J; K++) {
                if (Q[K] === R) {
                    throw new TypeError()
                }
            }
            Q.push(R);
            var N = [];
            if (L === h) {
                for (var K = 0, J = R.length; K < J; K++) {
                    var M = G(K, R, Q);
                    N.push(typeof M === "undefined" ? "null": M)
                }
                N = "[" + N.join(",") + "]"
            } else {
                var T = Object.keys(R);
                for (var K = 0, J = T.length; K < J; K++) {
                    var S = T[K],
                    M = G(S, R, Q);
                    if (typeof M !== "undefined") {
                        N.push(S.inspect(true) + ":" + M)
                    }
                }
                N = "{" + N.join(",") + "}"
            }
            Q.pop();
            return N
        }
    }
    function x(J) {
        return JSON.stringify(J)
    }
    function k(J) {
        return $H(J).toQueryString()
    }
    function q(J) {
        return J && J.toHTML ? J.toHTML() : String.interpret(J)
    }
    function s(J) {
        if (l(J) !== I) {
            throw new TypeError()
        }
        var K = [];
        for (var L in J) {
            if (J.hasOwnProperty(L)) {
                K.push(L)
            }
        }
        return K
    }
    function d(J) {
        var K = [];
        for (var L in J) {
            K.push(J[L])
        }
        return K
    }
    function B(J) {
        return A({},
        J)
    }
    function v(J) {
        return !! (J && J.nodeType == 1)
    }
    function n(J) {
        return D.call(J) === h
    }
    var b = (typeof Array.isArray == "function") && Array.isArray([]) && !Array.isArray({});
    if (b) {
        n = Array.isArray
    }
    function e(J) {
        return J instanceof Hash
    }
    function a(J) {
        return D.call(J) === u
    }
    function o(J) {
        return D.call(J) === m
    }
    function r(J) {
        return D.call(J) === g
    }
    function F(J) {
        return D.call(J) === y
    }
    function c(J) {
        return typeof J === "undefined"
    }
    A(Object, {
        extend: A,
        inspect: H,
        toJSON: j ? x: E,
        toQueryString: k,
        toHTML: q,
        keys: Object.keys || s,
        values: d,
        clone: B,
        isElement: v,
        isArray: n,
        isHash: e,
        isFunction: a,
        isString: o,
        isNumber: r,
        isDate: F,
        isUndefined: c
    })
})();
Object.extend(Function.prototype, (function() {
    var l = Array.prototype.slice;
    function d(p, m) {
        var o = p.length,
        n = m.length;
        while (n--) {
            p[o + n] = m[n]
        }
        return p
    }
    function j(n, m) {
        n = l.call(n, 0);
        return d(n, m)
    }
    function g() {
        var m = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, "").replace(/\s+/g, "").split(",");
        return m.length == 1 && !m[0] ? [] : m
    }
    function h(o) {
        if (arguments.length < 2 && Object.isUndefined(arguments[0])) {
            return this
        }
        var m = this,
        n = l.call(arguments, 1);
        return function() {
            var p = j(n, arguments);
            return m.apply(o, p)
        }
    }
    function f(o) {
        var m = this,
        n = l.call(arguments, 1);
        return function(q) {
            var p = d([q || window.event], n);
            return m.apply(o, p)
        }
    }
    function k() {
        if (!arguments.length) {
            return this
        }
        var m = this,
        n = l.call(arguments, 0);
        return function() {
            var o = j(n, arguments);
            return m.apply(this, o)
        }
    }
    function e(o) {
        var m = this,
        n = l.call(arguments, 1);
        o = o * 1000;
        return window.setTimeout(function() {
            return m.apply(m, n)
        },
        o)
    }
    function a() {
        var m = d([0.01], arguments);
        return this.delay.apply(this, m)
    }
    function c(n) {
        var m = this;
        return function() {
            var o = d([m.bind(this)], arguments);
            return n.apply(this, o)
        }
    }
    function b() {
        if (this._methodized) {
            return this._methodized
        }
        var m = this;
        return this._methodized = function() {
            var n = d([this], arguments);
            return m.apply(null, n)
        }
    }
    return {
        argumentNames: g,
        bind: h,
        bindAsEventListener: f,
        curry: k,
        delay: e,
        defer: a,
        wrap: c,
        methodize: b
    }
})()); (function(c) {
    function b() {
        return this.getUTCFullYear() + "-" + (this.getUTCMonth() + 1).toPaddedString(2) + "-" + this.getUTCDate().toPaddedString(2) + "T" + this.getUTCHours().toPaddedString(2) + ":" + this.getUTCMinutes().toPaddedString(2) + ":" + this.getUTCSeconds().toPaddedString(2) + "Z"
    }
    function a() {
        return this.toISOString()
    }
    if (!c.toISOString) {
        c.toISOString = b
    }
    if (!c.toJSON) {
        c.toJSON = a
    }
})(Date.prototype);
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(a) {
    return String(a).replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1")
};
var PeriodicalExecuter = Class.create({
    initialize: function(b, a) {
        this.callback = b;
        this.frequency = a;
        this.currentlyExecuting = false;
        this.registerCallback()
    },
    registerCallback: function() {
        this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000)
    },
    execute: function() {
        this.callback(this)
    },
    stop: function() {
        if (!this.timer) {
            return
        }
        clearInterval(this.timer);
        this.timer = null
    },
    onTimerEvent: function() {
        if (!this.currentlyExecuting) {
            try {
                this.currentlyExecuting = true;
                this.execute();
                this.currentlyExecuting = false
            } catch(a) {
                this.currentlyExecuting = false;
                throw a
            }
        }
    }
});
Object.extend(String, {
    interpret: function(a) {
        return a == null ? "": String(a)
    },
    specialChar: {
        "\b": "\\b",
        "\t": "\\t",
        "\n": "\\n",
        "\f": "\\f",
        "\r": "\\r",
        "\\": "\\\\"
    }
});
Object.extend(String.prototype, (function() {
    var NATIVE_JSON_PARSE_SUPPORT = window.JSON && typeof JSON.parse === "function" && JSON.parse('{"test": true}').test;
    function prepareReplacement(replacement) {
        if (Object.isFunction(replacement)) {
            return replacement
        }
        var template = new Template(replacement);
        return function(match) {
            return template.evaluate(match)
        }
    }
    function gsub(pattern, replacement) {
        var result = "",
        source = this,
        match;
        replacement = prepareReplacement(replacement);
        if (Object.isString(pattern)) {
            pattern = RegExp.escape(pattern)
        }
        if (! (pattern.length || pattern.source)) {
            replacement = replacement("");
            return replacement + source.split("").join(replacement) + replacement
        }
        while (source.length > 0) {
            if (match = source.match(pattern)) {
                result += source.slice(0, match.index);
                result += String.interpret(replacement(match));
                source = source.slice(match.index + match[0].length)
            } else {
                result += source,
                source = ""
            }
        }
        return result
    }
    function sub(pattern, replacement, count) {
        replacement = prepareReplacement(replacement);
        count = Object.isUndefined(count) ? 1: count;
        return this.gsub(pattern,
        function(match) {
            if (--count < 0) {
                return match[0]
            }
            return replacement(match)
        })
    }
    function scan(pattern, iterator) {
        this.gsub(pattern, iterator);
        return String(this)
    }
    function truncate(length, truncation) {
        length = length || 30;
        truncation = Object.isUndefined(truncation) ? "...": truncation;
        return this.length > length ? this.slice(0, length - truncation.length) + truncation: String(this)
    }
    function strip() {
        return this.replace(/^\s+/, "").replace(/\s+$/, "")
    }
    function stripTags() {
        return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, "")
    }
    function stripScripts() {
        return this.replace(new RegExp(Prototype.ScriptFragment, "img"), "")
    }
    function extractScripts() {
        var matchAll = new RegExp(Prototype.ScriptFragment, "img"),
        matchOne = new RegExp(Prototype.ScriptFragment, "im");
        return (this.match(matchAll) || []).map(function(scriptTag) {
            return (scriptTag.match(matchOne) || ["", ""])[1]
        })
    }
    function evalScripts() {
        return this.extractScripts().map(function(script) {
            return eval(script)
        })
    }
    function escapeHTML() {
        return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
    }
    function unescapeHTML() {
        return this.stripTags().replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&")
    }
    function toQueryParams(separator) {
        var match = this.strip().match(/([^?#]*)(#.*)?$/);
        if (!match) {
            return {}
        }
        return match[1].split(separator || "&").inject({},
        function(hash, pair) {
            if ((pair = pair.split("="))[0]) {
                var key = decodeURIComponent(pair.shift()),
                value = pair.length > 1 ? pair.join("=") : pair[0];
                if (value != undefined) {
                    value = decodeURIComponent(value)
                }
                if (key in hash) {
                    if (!Object.isArray(hash[key])) {
                        hash[key] = [hash[key]]
                    }
                    hash[key].push(value)
                } else {
                    hash[key] = value
                }
            }
            return hash
        })
    }
    function toArray() {
        return this.split("")
    }
    function succ() {
        return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1)
    }
    function times(count) {
        return count < 1 ? "": new Array(count + 1).join(this)
    }
    function camelize() {
        return this.replace(/-+(.)?/g,
        function(match, chr) {
            return chr ? chr.toUpperCase() : ""
        })
    }
    function capitalize() {
        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase()
    }
    function underscore() {
        return this.replace(/::/g, "/").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/-/g, "_").toLowerCase()
    }
    function dasherize() {
        return this.replace(/_/g, "-")
    }
    function inspect(useDoubleQuotes) {
        var escapedString = this.replace(/[\x00-\x1f\\]/g,
        function(character) {
            if (character in String.specialChar) {
                return String.specialChar[character]
            }
            return "\\u00" + character.charCodeAt().toPaddedString(2, 16)
        });
        if (useDoubleQuotes) {
            return '"' + escapedString.replace(/"/g, '\\"') + '"'
        }
        return "'" + escapedString.replace(/'/g, "\\'") + "'"
    }
    function unfilterJSON(filter) {
        return this.replace(filter || Prototype.JSONFilter, "$1")
    }
    function isJSON() {
        var str = this;
        if (str.blank()) {
            return false
        }
        str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@");
        str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]");
        str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, "");
        return (/^[\],:{}\s]*$/).test(str)
    }
    function evalJSON(sanitize) {
        var json = this.unfilterJSON(),
        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        if (cx.test(json)) {
            json = json.replace(cx,
            function(a) {
                return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice( - 4)
            })
        }
        try {
            if (!sanitize || json.isJSON()) {
                return eval("(" + json + ")")
            }
        } catch(e) {}
        throw new SyntaxError("Badly formed JSON string: " + this.inspect())
    }
    function parseJSON() {
        var json = this.unfilterJSON();
        return JSON.parse(json)
    }
    function include(pattern) {
        return this.indexOf(pattern) > -1
    }
    function startsWith(pattern) {
        return this.lastIndexOf(pattern, 0) === 0
    }
    function endsWith(pattern) {
        var d = this.length - pattern.length;
        return d >= 0 && this.indexOf(pattern, d) === d
    }
    function empty() {
        return this == ""
    }
    function blank() {
        return /^\s*$/.test(this)
    }
    function interpolate(object, pattern) {
        return new Template(this, pattern).evaluate(object)
    }
    return {
        gsub: gsub,
        sub: sub,
        scan: scan,
        truncate: truncate,
        strip: String.prototype.trim || strip,
        stripTags: stripTags,
        stripScripts: stripScripts,
        extractScripts: extractScripts,
        evalScripts: evalScripts,
        escapeHTML: escapeHTML,
        unescapeHTML: unescapeHTML,
        toQueryParams: toQueryParams,
        parseQuery: toQueryParams,
        toArray: toArray,
        succ: succ,
        times: times,
        camelize: camelize,
        capitalize: capitalize,
        underscore: underscore,
        dasherize: dasherize,
        inspect: inspect,
        unfilterJSON: unfilterJSON,
        isJSON: isJSON,
        evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON: evalJSON,
        include: include,
        startsWith: startsWith,
        endsWith: endsWith,
        empty: empty,
        blank: blank,
        interpolate: interpolate
    }
})());
var Template = Class.create({
    initialize: function(a, b) {
        this.template = a.toString();
        this.pattern = b || Template.Pattern
    },
    evaluate: function(a) {
        if (a && Object.isFunction(a.toTemplateReplacements)) {
            a = a.toTemplateReplacements()
        }
        return this.template.gsub(this.pattern,
        function(d) {
            if (a == null) {
                return (d[1] + "")
            }
            var f = d[1] || "";
            if (f == "\\") {
                return d[2]
            }
            var b = a,
            g = d[3],
            e = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
            d = e.exec(g);
            if (d == null) {
                return f
            }
            while (d != null) {
                var c = d[1].startsWith("[") ? d[2].replace(/\\\\]/g, "]") : d[1];
                b = b[c];
                if (null == b || "" == d[3]) {
                    break
                }
                g = g.substring("[" == d[3] ? d[1].length: d[0].length);
                d = e.exec(g)
            }
            return f + String.interpret(b)
        })
    }
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = {};
var Enumerable = (function() {
    function c(z, y) {
        var x = 0;
        try {
            this._each(function(B) {
                z.call(y, B, x++)
            })
        } catch(A) {
            if (A != $break) {
                throw A
            }
        }
        return this
    }
    function s(A, z, y) {
        var x = -A,
        B = [],
        C = this.toArray();
        if (A < 1) {
            return C
        }
        while ((x += A) < C.length) {
            B.push(C.slice(x, x + A))
        }
        return B.collect(z, y)
    }
    function b(z, y) {
        z = z || Prototype.K;
        var x = true;
        this.each(function(B, A) {
            x = x && !!z.call(y, B, A);
            if (!x) {
                throw $break
            }
        });
        return x
    }
    function j(z, y) {
        z = z || Prototype.K;
        var x = false;
        this.each(function(B, A) {
            if (x = !!z.call(y, B, A)) {
                throw $break
            }
        });
        return x
    }
    function k(z, y) {
        z = z || Prototype.K;
        var x = [];
        this.each(function(B, A) {
            x.push(z.call(y, B, A))
        });
        return x
    }
    function u(z, y) {
        var x;
        this.each(function(B, A) {
            if (z.call(y, B, A)) {
                x = B;
                throw $break
            }
        });
        return x
    }
    function h(z, y) {
        var x = [];
        this.each(function(B, A) {
            if (z.call(y, B, A)) {
                x.push(B)
            }
        });
        return x
    }
    function g(A, z, y) {
        z = z || Prototype.K;
        var x = [];
        if (Object.isString(A)) {
            A = new RegExp(RegExp.escape(A))
        }
        this.each(function(C, B) {
            if (A.match(C)) {
                x.push(z.call(y, C, B))
            }
        });
        return x
    }
    function a(x) {
        if (Object.isFunction(this.indexOf)) {
            if (this.indexOf(x) != -1) {
                return true
            }
        }
        var y = false;
        this.each(function(z) {
            if (z == x) {
                y = true;
                throw $break
            }
        });
        return y
    }
    function r(y, x) {
        x = Object.isUndefined(x) ? null: x;
        return this.eachSlice(y,
        function(z) {
            while (z.length < y) {
                z.push(x)
            }
            return z
        })
    }
    function m(x, z, y) {
        this.each(function(B, A) {
            x = z.call(y, x, B, A)
        });
        return x
    }
    function w(y) {
        var x = $A(arguments).slice(1);
        return this.map(function(z) {
            return z[y].apply(z, x)
        })
    }
    function q(z, y) {
        z = z || Prototype.K;
        var x;
        this.each(function(B, A) {
            B = z.call(y, B, A);
            if (x == null || B >= x) {
                x = B
            }
        });
        return x
    }
    function o(z, y) {
        z = z || Prototype.K;
        var x;
        this.each(function(B, A) {
            B = z.call(y, B, A);
            if (x == null || B < x) {
                x = B
            }
        });
        return x
    }
    function e(A, y) {
        A = A || Prototype.K;
        var z = [],
        x = [];
        this.each(function(C, B) { (A.call(y, C, B) ? z: x).push(C)
        });
        return [z, x]
    }
    function f(y) {
        var x = [];
        this.each(function(z) {
            x.push(z[y])
        });
        return x
    }
    function d(z, y) {
        var x = [];
        this.each(function(B, A) {
            if (!z.call(y, B, A)) {
                x.push(B)
            }
        });
        return x
    }
    function n(y, x) {
        return this.map(function(A, z) {
            return {
                value: A,
                criteria: y.call(x, A, z)
            }
        }).sort(function(C, B) {
            var A = C.criteria,
            z = B.criteria;
            return A < z ? -1: A > z ? 1: 0
        }).pluck("value")
    }
    function p() {
        return this.map()
    }
    function t() {
        var y = Prototype.K,
        x = $A(arguments);
        if (Object.isFunction(x.last())) {
            y = x.pop()
        }
        var z = [this].concat(x).map($A);
        return this.map(function(B, A) {
            return y(z.pluck(A))
        })
    }
    function l() {
        return this.toArray().length
    }
    function v() {
        return "#<Enumerable:" + this.toArray().inspect() + ">"
    }
    return {
        each: c,
        eachSlice: s,
        all: b,
        every: b,
        any: j,
        some: j,
        collect: k,
        map: k,
        detect: u,
        findAll: h,
        select: h,
        filter: h,
        grep: g,
        include: a,
        member: a,
        inGroupsOf: r,
        inject: m,
        invoke: w,
        max: q,
        min: o,
        partition: e,
        pluck: f,
        reject: d,
        sortBy: n,
        toArray: p,
        entries: p,
        zip: t,
        size: l,
        inspect: v,
        find: u
    }
})();
function $A(c) {
    if (!c) {
        return []
    }
    if ("toArray" in Object(c)) {
        return c.toArray()
    }
    var b = c.length || 0,
    a = new Array(b);
    while (b--) {
        a[b] = c[b]
    }
    return a
}
function $w(a) {
    if (!Object.isString(a)) {
        return []
    }
    a = a.strip();
    return a ? a.split(/\s+/) : []
}
Array.from = $A; (function() {
    var s = Array.prototype,
    n = s.slice,
    p = s.forEach;
    function b(x, w) {
        for (var v = 0, y = this.length >>> 0; v < y; v++) {
            if (v in this) {
                x.call(w, this[v], v, this)
            }
        }
    }
    if (!p) {
        p = b
    }
    function m() {
        this.length = 0;
        return this
    }
    function d() {
        return this[0]
    }
    function g() {
        return this[this.length - 1]
    }
    function j() {
        return this.select(function(v) {
            return v != null
        })
    }
    function u() {
        return this.inject([],
        function(w, v) {
            if (Object.isArray(v)) {
                return w.concat(v.flatten())
            }
            w.push(v);
            return w
        })
    }
    function h() {
        var v = n.call(arguments, 0);
        return this.select(function(w) {
            return ! v.include(w)
        })
    }
    function f(v) {
        return (v === false ? this.toArray() : this)._reverse()
    }
    function l(v) {
        return this.inject([],
        function(y, x, w) {
            if (0 == w || (v ? y.last() != x: !y.include(x))) {
                y.push(x)
            }
            return y
        })
    }
    function q(v) {
        return this.uniq().findAll(function(w) {
            return v.detect(function(x) {
                return w === x
            })
        })
    }
    function r() {
        return n.call(this, 0)
    }
    function k() {
        return this.length
    }
    function t() {
        return "[" + this.map(Object.inspect).join(", ") + "]"
    }
    function a(x, v) {
        v || (v = 0);
        var w = this.length;
        if (v < 0) {
            v = w + v
        }
        for (; v < w; v++) {
            if (this[v] === x) {
                return v
            }
        }
        return - 1
    }
    function o(w, v) {
        v = isNaN(v) ? this.length: (v < 0 ? this.length + v: v) + 1;
        var x = this.slice(0, v).reverse().indexOf(w);
        return (x < 0) ? x: v - x - 1
    }
    function c() {
        var A = n.call(this, 0),
        y;
        for (var w = 0, x = arguments.length; w < x; w++) {
            y = arguments[w];
            if (Object.isArray(y) && !("callee" in y)) {
                for (var v = 0, z = y.length; v < z; v++) {
                    A.push(y[v])
                }
            } else {
                A.push(y)
            }
        }
        return A
    }
    Object.extend(s, Enumerable);
    if (!s._reverse) {
        s._reverse = s.reverse
    }
    Object.extend(s, {
        _each: p,
        clear: m,
        first: d,
        last: g,
        compact: j,
        flatten: u,
        without: h,
        reverse: f,
        uniq: l,
        intersect: q,
        clone: r,
        toArray: r,
        size: k,
        inspect: t
    });
    var e = (function() {
        return [].concat(arguments)[0][0] !== 1
    })(1, 2);
    if (e) {
        s.concat = c
    }
    if (!s.indexOf) {
        s.indexOf = a
    }
    if (!s.lastIndexOf) {
        s.lastIndexOf = o
    }
})();
function $H(a) {
    return new Hash(a)
}
var Hash = Class.create(Enumerable, (function() {
    function e(q) {
        this._object = Object.isHash(q) ? q.toObject() : Object.clone(q)
    }
    function f(r) {
        for (var q in this._object) {
            var s = this._object[q],
            t = [q, s];
            t.key = q;
            t.value = s;
            r(t)
        }
    }
    function k(q, r) {
        return this._object[q] = r
    }
    function c(q) {
        if (this._object[q] !== Object.prototype[q]) {
            return this._object[q]
        }
    }
    function n(q) {
        var r = this._object[q];
        delete this._object[q];
        return r
    }
    function p() {
        return Object.clone(this._object)
    }
    function o() {
        return this.pluck("key")
    }
    function m() {
        return this.pluck("value")
    }
    function g(r) {
        var q = this.detect(function(s) {
            return s.value === r
        });
        return q && q.key
    }
    function j(q) {
        return this.clone().update(q)
    }
    function d(q) {
        return new Hash(q).inject(this,
        function(r, s) {
            r.set(s.key, s.value);
            return r
        })
    }
    function b(q, r) {
        if (Object.isUndefined(r)) {
            return q
        }
        return q + "=" + encodeURIComponent(String.interpret(r))
    }
    function a() {
        return this.inject([],
        function(u, x) {
            var t = encodeURIComponent(x.key),
            r = x.value;
            if (r && typeof r == "object") {
                if (Object.isArray(r)) {
                    var w = [];
                    for (var s = 0, q = r.length, v; s < q; s++) {
                        v = r[s];
                        w.push(b(t, v))
                    }
                    return u.concat(w)
                }
            } else {
                u.push(b(t, r))
            }
            return u
        }).join("&")
    }
    function l() {
        return "#<Hash:{" + this.map(function(q) {
            return q.map(Object.inspect).join(": ")
        }).join(", ") + "}>"
    }
    function h() {
        return new Hash(this)
    }
    return {
        initialize: e,
        _each: f,
        set: k,
        get: c,
        unset: n,
        toObject: p,
        toTemplateReplacements: p,
        keys: o,
        values: m,
        index: g,
        merge: j,
        update: d,
        toQueryString: a,
        inspect: l,
        toJSON: p,
        clone: h
    }
})());
Hash.from = $H;
Object.extend(Number.prototype, (function() {
    function d() {
        return this.toPaddedString(2, 16)
    }
    function b() {
        return this + 1
    }
    function h(k, j) {
        $R(0, this, true).each(k, j);
        return this
    }
    function g(l, k) {
        var j = this.toString(k || 10);
        return "0".times(l - j.length) + j
    }
    function a() {
        return Math.abs(this)
    }
    function c() {
        return Math.round(this)
    }
    function e() {
        return Math.ceil(this)
    }
    function f() {
        return Math.floor(this)
    }
    return {
        toColorPart: d,
        succ: b,
        times: h,
        toPaddedString: g,
        abs: a,
        round: c,
        ceil: e,
        floor: f
    }
})());
function $R(c, a, b) {
    return new ObjectRange(c, a, b)
}
var ObjectRange = Class.create(Enumerable, (function() {
    function b(f, d, e) {
        this.start = f;
        this.end = d;
        this.exclusive = e
    }
    function c(d) {
        var e = this.start;
        while (this.include(e)) {
            d(e);
            e = e.succ()
        }
    }
    function a(d) {
        if (d < this.start) {
            return false
        }
        if (this.exclusive) {
            return d < this.end
        }
        return d <= this.end
    }
    return {
        initialize: b,
        _each: c,
        include: a
    }
})());
var Abstract = {};
var Try = {
    these: function() {
        var c;
        for (var b = 0, d = arguments.length; b < d; b++) {
            var a = arguments[b];
            try {
                c = a();
                break
            } catch(f) {}
        }
        return c
    }
};
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(a) {
        this.responders._each(a)
    },
    register: function(a) {
        if (!this.include(a)) {
            this.responders.push(a)
        }
    },
    unregister: function(a) {
        this.responders = this.responders.without(a)
    },
    dispatch: function(d, b, c, a) {
        this.each(function(f) {
            if (Object.isFunction(f[d])) {
                try {
                    f[d].apply(f, [b, c, a])
                } catch(g) {}
            }
        })
    }
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
    onCreate: function() {
        Ajax.activeRequestCount++
    },
    onComplete: function() {
        Ajax.activeRequestCount--
    }
});
Ajax.Base = Class.create({
    initialize: function(a) {
        this.options = {
            method: "post",
            asynchronous: true,
            contentType: "application/x-www-form-urlencoded",
            encoding: "UTF-8",
            parameters: "",
            evalJSON: true,
            evalJS: true
        };
        Object.extend(this.options, a || {});
        this.options.method = this.options.method.toLowerCase();
        if (Object.isHash(this.options.parameters)) {
            this.options.parameters = this.options.parameters.toObject()
        }
    }
});
Ajax.Request = Class.create(Ajax.Base, {
    _complete: false,
    initialize: function($super, b, a) {
        $super(a);
        this.transport = Ajax.getTransport();
        this.request(b)
    },
    request: function(b) {
        this.url = b;
        this.method = this.options.method;
        var d = Object.isString(this.options.parameters) ? this.options.parameters: Object.toQueryString(this.options.parameters);
        if (! ["get", "post"].include(this.method)) {
            d += (d ? "&": "") + "_method=" + this.method;
            this.method = "post"
        }
        if (d && this.method === "get") {
            this.url += (this.url.include("?") ? "&": "?") + d
        }
        this.parameters = d.toQueryParams();
        try {
            var a = new Ajax.Response(this);
            if (this.options.onCreate) {
                this.options.onCreate(a)
            }
            Ajax.Responders.dispatch("onCreate", this, a);
            this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous);
            if (this.options.asynchronous) {
                this.respondToReadyState.bind(this).defer(1)
            }
            this.transport.onreadystatechange = this.onStateChange.bind(this);
            this.setRequestHeaders();
            this.body = this.method == "post" ? (this.options.postBody || d) : null;
            this.transport.send(this.body);
            if (!this.options.asynchronous && this.transport.overrideMimeType) {
                this.onStateChange()
            }
        } catch(c) {
            this.dispatchException(c)
        }
    },
    onStateChange: function() {
        var a = this.transport.readyState;
        if (a > 1 && !((a == 4) && this._complete)) {
            this.respondToReadyState(this.transport.readyState)
        }
    },
    setRequestHeaders: function() {
        var e = {
            "X-Requested-With": "XMLHttpRequest",
            "X-Prototype-Version": Prototype.Version,
            Accept: "text/javascript, text/html, application/xml, text/xml, */*"
        };
        if (this.method == "post") {
            e["Content-type"] = this.options.contentType + (this.options.encoding ? "; charset=" + this.options.encoding: "");
            if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1] < 2005) {
                e.Connection = "close"
            }
        }
        if (typeof this.options.requestHeaders == "object") {
            var c = this.options.requestHeaders;
            if (Object.isFunction(c.push)) {
                for (var b = 0, d = c.length; b < d; b += 2) {
                    e[c[b]] = c[b + 1]
                }
            } else {
                $H(c).each(function(f) {
                    e[f.key] = f.value
                })
            }
        }
        for (var a in e) {
            this.transport.setRequestHeader(a, e[a])
        }
    },
    success: function() {
        var a = this.getStatus();
        return ! a || (a >= 200 && a < 300) || a == 304
    },
    getStatus: function() {
        try {
            if (this.transport.status === 1223) {
                return 204
            }
            return this.transport.status || 0
        } catch(a) {
            return 0
        }
    },
    respondToReadyState: function(a) {
        var c = Ajax.Request.Events[a],
        b = new Ajax.Response(this);
        if (c == "Complete") {
            try {
                this._complete = true; (this.options["on" + b.status] || this.options["on" + (this.success() ? "Success": "Failure")] || Prototype.emptyFunction)(b, b.headerJSON)
            } catch(d) {
                this.dispatchException(d)
            }
            var f = b.getHeader("Content-type");
            if (this.options.evalJS == "force" || (this.options.evalJS && this.isSameOrigin() && f && f.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) {
                this.evalResponse()
            }
        }
        try { (this.options["on" + c] || Prototype.emptyFunction)(b, b.headerJSON);
            Ajax.Responders.dispatch("on" + c, this, b, b.headerJSON)
        } catch(d) {
            this.dispatchException(d)
        }
        if (c == "Complete") {
            this.transport.onreadystatechange = Prototype.emptyFunction
        }
    },
    isSameOrigin: function() {
        var a = this.url.match(/^\s*https?:\/\/[^\/]*/);
        return ! a || (a[0] == "#{protocol}//#{domain}#{port}".interpolate({
            protocol: location.protocol,
            domain: document.domain,
            port: location.port ? ":" + location.port: ""
        }))
    },
    getHeader: function(a) {
        try {
            return this.transport.getResponseHeader(a) || null
        } catch(b) {
            return null
        }
    },
    evalResponse: function() {
        try {
            return eval((this.transport.responseText || "").unfilterJSON())
        } catch(e) {
            this.dispatchException(e)
        }
    },
    dispatchException: function(a) { (this.options.onException || Prototype.emptyFunction)(this, a);
        Ajax.Responders.dispatch("onException", this, a)
    }
});
Ajax.Request.Events = ["Uninitialized", "Loading", "Loaded", "Interactive", "Complete"];
Ajax.Response = Class.create({
    initialize: function(c) {
        this.request = c;
        var d = this.transport = c.transport,
        a = this.readyState = d.readyState;
        if ((a > 2 && !Prototype.Browser.IE) || a == 4) {
            this.status = this.getStatus();
            this.statusText = this.getStatusText();
            this.responseText = String.interpret(d.responseText);
            this.headerJSON = this._getHeaderJSON()
        }
        if (a == 4) {
            var b = d.responseXML;
            this.responseXML = Object.isUndefined(b) ? null: b;
            this.responseJSON = this._getResponseJSON()
        }
    },
    status: 0,
    statusText: "",
    getStatus: Ajax.Request.prototype.getStatus,
    getStatusText: function() {
        try {
            return this.transport.statusText || ""
        } catch(a) {
            return ""
        }
    },
    getHeader: Ajax.Request.prototype.getHeader,
    getAllHeaders: function() {
        try {
            return this.getAllResponseHeaders()
        } catch(a) {
            return null
        }
    },
    getResponseHeader: function(a) {
        return this.transport.getResponseHeader(a)
    },
    getAllResponseHeaders: function() {
        return this.transport.getAllResponseHeaders()
    },
    _getHeaderJSON: function() {
        var a = this.getHeader("X-JSON");
        if (!a) {
            return null
        }
        a = decodeURIComponent(escape(a));
        try {
            return a.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin())
        } catch(b) {
            this.request.dispatchException(b)
        }
    },
    _getResponseJSON: function() {
        var a = this.request.options;
        if (!a.evalJSON || (a.evalJSON != "force" && !(this.getHeader("Content-type") || "").include("application/json")) || this.responseText.blank()) {
            return null
        }
        try {
            return this.responseText.evalJSON(a.sanitizeJSON || !this.request.isSameOrigin())
        } catch(b) {
            this.request.dispatchException(b)
        }
    }
});
Ajax.Updater = Class.create(Ajax.Request, {
    initialize: function($super, a, c, b) {
        this.container = {
            success: (a.success || a),
            failure: (a.failure || (a.success ? null: a))
        };
        b = Object.clone(b);
        var d = b.onComplete;
        b.onComplete = (function(e, f) {
            this.updateContent(e.responseText);
            if (Object.isFunction(d)) {
                d(e, f)
            }
        }).bind(this);
        $super(c, b)
    },
    updateContent: function(d) {
        var c = this.container[this.success() ? "success": "failure"],
        a = this.options;
        if (!a.evalScripts) {
            d = d.stripScripts()
        }
        if (c = $(c)) {
            if (a.insertion) {
                if (Object.isString(a.insertion)) {
                    var b = {};
                    b[a.insertion] = d;
                    c.insert(b)
                } else {
                    a.insertion(c, d)
                }
            } else {
                c.update(d)
            }
        }
    }
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
    initialize: function($super, a, c, b) {
        $super(b);
        this.onComplete = this.options.onComplete;
        this.frequency = (this.options.frequency || 2);
        this.decay = (this.options.decay || 1);
        this.updater = {};
        this.container = a;
        this.url = c;
        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(a) {
        if (this.options.decay) {
            this.decay = (a.responseText == this.lastText ? this.decay * this.options.decay: 1);
            this.lastText = a.responseText
        }
        this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency)
    },
    onTimerEvent: function() {
        this.updater = new Ajax.Updater(this.container, this.url, this.options)
    }
});
function $(b) {
    if (arguments.length > 1) {
        for (var a = 0, d = [], c = arguments.length; a < c; a++) {
            d.push($(arguments[a]))
        }
        return d
    }
    if (Object.isString(b)) {
        b = document.getElementById(b)
    }
    return Element.extend(b)
}
if (Prototype.BrowserFeatures.XPath) {
    document._getElementsByXPath = function(f, a) {
        var c = [];
        var e = document.evaluate(f, $(a) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var b = 0, d = e.snapshotLength; b < d; b++) {
            c.push(Element.extend(e.snapshotItem(b)))
        }
        return c
    }
}
if (!Node) {
    var Node = {}
}
if (!Node.ELEMENT_NODE) {
    Object.extend(Node, {
        ELEMENT_NODE: 1,
        ATTRIBUTE_NODE: 2,
        TEXT_NODE: 3,
        CDATA_SECTION_NODE: 4,
        ENTITY_REFERENCE_NODE: 5,
        ENTITY_NODE: 6,
        PROCESSING_INSTRUCTION_NODE: 7,
        COMMENT_NODE: 8,
        DOCUMENT_NODE: 9,
        DOCUMENT_TYPE_NODE: 10,
        DOCUMENT_FRAGMENT_NODE: 11,
        NOTATION_NODE: 12
    })
} (function(c) {
    function d(f, e) {
        if (f === "select") {
            return false
        }
        if ("type" in e) {
            return false
        }
        return true
    }
    var b = (function() {
        try {
            var e = document.createElement('<input name="x">');
            return e.tagName.toLowerCase() === "input" && e.name === "x"
        } catch(f) {
            return false
        }
    })();
    var a = c.Element;
    c.Element = function(g, f) {
        f = f || {};
        g = g.toLowerCase();
        var e = Element.cache;
        if (b && f.name) {
            g = "<" + g + ' name="' + f.name + '">';
            delete f.name;
            return Element.writeAttribute(document.createElement(g), f)
        }
        if (!e[g]) {
            e[g] = Element.extend(document.createElement(g))
        }
        var h = d(g, f) ? e[g].cloneNode(false) : document.createElement(g);
        return Element.writeAttribute(h, f)
    };
    Object.extend(c.Element, a || {});
    if (a) {
        c.Element.prototype = a.prototype
    }
})(this);
Element.idCounter = 1;
Element.cache = {};
Element._purgeElement = function(b) {
    var a = b._prototypeUID;
    if (a) {
        Element.stopObserving(b);
        b._prototypeUID = void 0;
        delete Element.Storage[a]
    }
};
Element.Methods = {
    visible: function(a) {
        return $(a).style.display != "none"
    },
    toggle: function(a) {
        a = $(a);
        Element[Element.visible(a) ? "hide": "show"](a);
        return a
    },
    hide: function(a) {
        a = $(a);
        a.style.display = "none";
        return a
    },
    show: function(a) {
        a = $(a);
        a.style.display = "";
        return a
    },
    remove: function(a) {
        a = $(a);
        a.parentNode.removeChild(a);
        return a
    },
    update: (function() {
        var d = (function() {
            var g = document.createElement("select"),
            h = true;
            g.innerHTML = '<option value="test">test</option>';
            if (g.options && g.options[0]) {
                h = g.options[0].nodeName.toUpperCase() !== "OPTION"
            }
            g = null;
            return h
        })();
        var b = (function() {
            try {
                var g = document.createElement("table");
                if (g && g.tBodies) {
                    g.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
                    var j = typeof g.tBodies[0] == "undefined";
                    g = null;
                    return j
                }
            } catch(h) {
                return true
            }
        })();
        var a = (function() {
            try {
                var g = document.createElement("div");
                g.innerHTML = "<link>";
                var j = (g.childNodes.length === 0);
                g = null;
                return j
            } catch(h) {
                return true
            }
        })();
        var c = d || b || a;
        var f = (function() {
            var g = document.createElement("script"),
            j = false;
            try {
                g.appendChild(document.createTextNode(""));
                j = !g.firstChild || g.firstChild && g.firstChild.nodeType !== 3
            } catch(h) {
                j = true
            }
            g = null;
            return j
        })();
        function e(l, m) {
            l = $(l);
            var g = Element._purgeElement;
            var n = l.getElementsByTagName("*"),
            k = n.length;
            while (k--) {
                g(n[k])
            }
            if (m && m.toElement) {
                m = m.toElement()
            }
            if (Object.isElement(m)) {
                return l.update().insert(m)
            }
            m = Object.toHTML(m);
            var j = l.tagName.toUpperCase();
            if (j === "SCRIPT" && f) {
                l.text = m;
                return l
            }
            if (c) {
                if (j in Element._insertionTranslations.tags) {
                    while (l.firstChild) {
                        l.removeChild(l.firstChild)
                    }
                    Element._getContentFromAnonymousElement(j, m.stripScripts()).each(function(o) {
                        l.appendChild(o)
                    })
                } else {
                    if (a && Object.isString(m) && m.indexOf("<link") > -1) {
                        while (l.firstChild) {
                            l.removeChild(l.firstChild)
                        }
                        var h = Element._getContentFromAnonymousElement(j, m.stripScripts(), true);
                        h.each(function(o) {
                            l.appendChild(o)
                        })
                    } else {
                        l.innerHTML = m.stripScripts()
                    }
                }
            } else {
                l.innerHTML = m.stripScripts()
            }
            m.evalScripts.bind(m).defer();
            return l
        }
        return e
    })(),
    replace: function(b, c) {
        b = $(b);
        if (c && c.toElement) {
            c = c.toElement()
        } else {
            if (!Object.isElement(c)) {
                c = Object.toHTML(c);
                var a = b.ownerDocument.createRange();
                a.selectNode(b);
                c.evalScripts.bind(c).defer();
                c = a.createContextualFragment(c.stripScripts())
            }
        }
        b.parentNode.replaceChild(c, b);
        return b
    },
    insert: function(c, e) {
        c = $(c);
        if (Object.isString(e) || Object.isNumber(e) || Object.isElement(e) || (e && (e.toElement || e.toHTML))) {
            e = {
                bottom: e
            }
        }
        var d,
        f,
        b,
        g;
        for (var a in e) {
            d = e[a];
            a = a.toLowerCase();
            f = Element._insertionTranslations[a];
            if (d && d.toElement) {
                d = d.toElement()
            }
            if (Object.isElement(d)) {
                f(c, d);
                continue
            }
            d = Object.toHTML(d);
            b = ((a == "before" || a == "after") ? c.parentNode: c).tagName.toUpperCase();
            g = Element._getContentFromAnonymousElement(b, d.stripScripts());
            if (a == "top" || a == "after") {
                g.reverse()
            }
            g.each(f.curry(c));
            d.evalScripts.bind(d).defer()
        }
        return c
    },
    wrap: function(b, c, a) {
        b = $(b);
        if (Object.isElement(c)) {
            $(c).writeAttribute(a || {})
        } else {
            if (Object.isString(c)) {
                c = new Element(c, a)
            } else {
                c = new Element("div", c)
            }
        }
        if (b.parentNode) {
            b.parentNode.replaceChild(c, b)
        }
        c.appendChild(b);
        return c
    },
    inspect: function(b) {
        b = $(b);
        var a = "<" + b.tagName.toLowerCase();
        $H({
            id: "id",
            className: "class"
        }).each(function(f) {
            var e = f.first(),
            c = f.last(),
            d = (b[e] || "").toString();
            if (d) {
                a += " " + c + "=" + d.inspect(true)
            }
        });
        return a + ">"
    },
    recursivelyCollect: function(a, c, d) {
        a = $(a);
        d = d || -1;
        var b = [];
        while (a = a[c]) {
            if (a.nodeType == 1) {
                b.push(Element.extend(a))
            }
            if (b.length == d) {
                break
            }
        }
        return b
    },
    ancestors: function(a) {
        return Element.recursivelyCollect(a, "parentNode")
    },
    descendants: function(a) {
        return Element.select(a, "*")
    },
    firstDescendant: function(a) {
        a = $(a).firstChild;
        while (a && a.nodeType != 1) {
            a = a.nextSibling
        }
        return $(a)
    },
    immediateDescendants: function(b) {
        var a = [],
        c = $(b).firstChild;
        while (c) {
            if (c.nodeType === 1) {
                a.push(Element.extend(c))
            }
            c = c.nextSibling
        }
        return a
    },
    previousSiblings: function(a, b) {
        return Element.recursivelyCollect(a, "previousSibling")
    },
    nextSiblings: function(a) {
        return Element.recursivelyCollect(a, "nextSibling")
    },
    siblings: function(a) {
        a = $(a);
        return Element.previousSiblings(a).reverse().concat(Element.nextSiblings(a))
    },
    match: function(b, a) {
        b = $(b);
        if (Object.isString(a)) {
            return Prototype.Selector.match(b, a)
        }
        return a.match(b)
    },
    up: function(b, d, a) {
        b = $(b);
        if (arguments.length == 1) {
            return $(b.parentNode)
        }
        var c = Element.ancestors(b);
        return Object.isNumber(d) ? c[d] : Prototype.Selector.find(c, d, a)
    },
    down: function(b, c, a) {
        b = $(b);
        if (arguments.length == 1) {
            return Element.firstDescendant(b)
        }
        return Object.isNumber(c) ? Element.descendants(b)[c] : Element.select(b, c)[a || 0]
    },
    previous: function(b, c, a) {
        b = $(b);
        if (Object.isNumber(c)) {
            a = c,
            c = false
        }
        if (!Object.isNumber(a)) {
            a = 0
        }
        if (c) {
            return Prototype.Selector.find(b.previousSiblings(), c, a)
        } else {
            return b.recursivelyCollect("previousSibling", a + 1)[a]
        }
    },
    next: function(b, d, a) {
        b = $(b);
        if (Object.isNumber(d)) {
            a = d,
            d = false
        }
        if (!Object.isNumber(a)) {
            a = 0
        }
        if (d) {
            return Prototype.Selector.find(b.nextSiblings(), d, a)
        } else {
            var c = Object.isNumber(a) ? a + 1: 1;
            return b.recursivelyCollect("nextSibling", a + 1)[a]
        }
    },
    select: function(a) {
        a = $(a);
        var b = Array.prototype.slice.call(arguments, 1).join(", ");
        return Prototype.Selector.select(b, a)
    },
    adjacent: function(a) {
        a = $(a);
        var b = Array.prototype.slice.call(arguments, 1).join(", ");
        return Prototype.Selector.select(b, a.parentNode).without(a)
    },
    identify: function(a) {
        a = $(a);
        var b = Element.readAttribute(a, "id");
        if (b) {
            return b
        }
        do {
            b = "anonymous_element_" + Element.idCounter++
        }
        while ($(b));
        Element.writeAttribute(a, "id", b);
        return b
    },
    readAttribute: function(c, a) {
        c = $(c);
        if (Prototype.Browser.IE) {
            var b = Element._attributeTranslations.read;
            if (b.values[a]) {
                return b.values[a](c, a)
            }
            if (b.names[a]) {
                a = b.names[a]
            }
            if (a.include(":")) {
                return (!c.attributes || !c.attributes[a]) ? null: c.attributes[a].value
            }
        }
        return c.getAttribute(a)
    },
    writeAttribute: function(e, c, f) {
        e = $(e);
        var b = {},
        d = Element._attributeTranslations.write;
        if (typeof c == "object") {
            b = c
        } else {
            b[c] = Object.isUndefined(f) ? true: f
        }
        for (var a in b) {
            c = d.names[a] || a;
            f = b[a];
            if (d.values[a]) {
                c = d.values[a](e, f)
            }
            if (f === false || f === null) {
                e.removeAttribute(c)
            } else {
                if (f === true) {
                    e.setAttribute(c, c)
                } else {
                    e.setAttribute(c, f)
                }
            }
        }
        return e
    },
    getHeight: function(a) {
        return Element.getDimensions(a).height
    },
    getWidth: function(a) {
        return Element.getDimensions(a).width
    },
    classNames: function(a) {
        return new Element.ClassNames(a)
    },
    hasClassName: function(a, b) {
        if (! (a = $(a))) {
            return
        }
        var c = a.className;
        return (c.length > 0 && (c == b || new RegExp("(^|\\s)" + b + "(\\s|$)").test(c)))
    },
    addClassName: function(a, b) {
        if (! (a = $(a))) {
            return
        }
        if (!Element.hasClassName(a, b)) {
            a.className += (a.className ? " ": "") + b
        }
        return a
    },
    removeClassName: function(a, b) {
        if (! (a = $(a))) {
            return
        }
        a.className = a.className.replace(new RegExp("(^|\\s+)" + b + "(\\s+|$)"), " ").strip();
        return a
    },
    toggleClassName: function(a, b) {
        if (! (a = $(a))) {
            return
        }
        return Element[Element.hasClassName(a, b) ? "removeClassName": "addClassName"](a, b)
    },
    cleanWhitespace: function(b) {
        b = $(b);
        var c = b.firstChild;
        while (c) {
            var a = c.nextSibling;
            if (c.nodeType == 3 && !/\S/.test(c.nodeValue)) {
                b.removeChild(c)
            }
            c = a
        }
        return b
    },
    empty: function(a) {
        return $(a).innerHTML.blank()
    },
    descendantOf: function(b, a) {
        b = $(b),
        a = $(a);
        if (b.compareDocumentPosition) {
            return (b.compareDocumentPosition(a) & 8) === 8
        }
        if (a.contains) {
            return a.contains(b) && a !== b
        }
        while (b = b.parentNode) {
            if (b == a) {
                return true
            }
        }
        return false
    },
    scrollTo: function(a) {
        a = $(a);
        var b = Element.cumulativeOffset(a);
        window.scrollTo(b[0], b[1]);
        return a
    },
    getStyle: function(b, c) {
        b = $(b);
        c = c == "float" ? "cssFloat": c.camelize();
        var d = b.style[c];
        if (!d || d == "auto") {
            var a = document.defaultView.getComputedStyle(b, null);
            d = a ? a[c] : null
        }
        if (c == "opacity") {
            return d ? parseFloat(d) : 1
        }
        return d == "auto" ? null: d
    },
    getOpacity: function(a) {
        return $(a).getStyle("opacity")
    },
    setStyle: function(b, c) {
        b = $(b);
        var e = b.style,
        a;
        if (Object.isString(c)) {
            b.style.cssText += ";" + c;
            return c.include("opacity") ? b.setOpacity(c.match(/opacity:\s*(\d?\.?\d*)/)[1]) : b
        }
        for (var d in c) {
            if (d == "opacity") {
                b.setOpacity(c[d])
            } else {
                e[(d == "float" || d == "cssFloat") ? (Object.isUndefined(e.styleFloat) ? "cssFloat": "styleFloat") : d] = c[d]
            }
        }
        return b
    },
    setOpacity: function(a, b) {
        a = $(a);
        a.style.opacity = (b == 1 || b === "") ? "": (b < 0.00001) ? 0: b;
        return a
    },
    makePositioned: function(a) {
        a = $(a);
        var b = Element.getStyle(a, "position");
        if (b == "static" || !b) {
            a._madePositioned = true;
            a.style.position = "relative";
            if (Prototype.Browser.Opera) {
                a.style.top = 0;
                a.style.left = 0
            }
        }
        return a
    },
    undoPositioned: function(a) {
        a = $(a);
        if (a._madePositioned) {
            a._madePositioned = undefined;
            a.style.position = a.style.top = a.style.left = a.style.bottom = a.style.right = ""
        }
        return a
    },
    makeClipping: function(a) {
        a = $(a);
        if (a._overflow) {
            return a
        }
        a._overflow = Element.getStyle(a, "overflow") || "auto";
        if (a._overflow !== "hidden") {
            a.style.overflow = "hidden"
        }
        return a
    },
    undoClipping: function(a) {
        a = $(a);
        if (!a._overflow) {
            return a
        }
        a.style.overflow = a._overflow == "auto" ? "": a._overflow;
        a._overflow = null;
        return a
    },
    clonePosition: function(b, d) {
        var a = Object.extend({
            setLeft: true,
            setTop: true,
            setWidth: true,
            setHeight: true,
            offsetTop: 0,
            offsetLeft: 0
        },
        arguments[2] || {});
        d = $(d);
        var e = Element.viewportOffset(d),
        f = [0, 0],
        c = null;
        b = $(b);
        if (Element.getStyle(b, "position") == "absolute") {
            c = Element.getOffsetParent(b);
            f = Element.viewportOffset(c)
        }
        if (c == document.body) {
            f[0] -= document.body.offsetLeft;
            f[1] -= document.body.offsetTop
        }
        if (a.setLeft) {
            b.style.left = (e[0] - f[0] + a.offsetLeft) + "px"
        }
        if (a.setTop) {
            b.style.top = (e[1] - f[1] + a.offsetTop) + "px"
        }
        if (a.setWidth) {
            b.style.width = d.offsetWidth + "px"
        }
        if (a.setHeight) {
            b.style.height = d.offsetHeight + "px"
        }
        return b
    }
};
Object.extend(Element.Methods, {
    getElementsBySelector: Element.Methods.select,
    childElements: Element.Methods.immediateDescendants
});
Element._attributeTranslations = {
    write: {
        names: {
            className: "class",
            htmlFor: "for"
        },
        values: {}
    }
};
if (Prototype.Browser.Opera) {
    Element.Methods.getStyle = Element.Methods.getStyle.wrap(function(d, b, c) {
        switch (c) {
        case "height":
        case "width":
            if (!Element.visible(b)) {
                return null
            }
            var e = parseInt(d(b, c), 10);
            if (e !== b["offset" + c.capitalize()]) {
                return e + "px"
            }
            var a;
            if (c === "height") {
                a = ["border-top-width", "padding-top", "padding-bottom", "border-bottom-width"]
            } else {
                a = ["border-left-width", "padding-left", "padding-right", "border-right-width"]
            }
            return a.inject(e,
            function(f, g) {
                var h = d(b, g);
                return h === null ? f: f - parseInt(h, 10)
            }) + "px";
        default:
            return d(b, c)
        }
    });
    Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(function(c, a, b) {
        if (b === "title") {
            return a.title
        }
        return c(a, b)
    })
} else {
    if (Prototype.Browser.IE) {
        Element.Methods.getStyle = function(a, b) {
            a = $(a);
            b = (b == "float" || b == "cssFloat") ? "styleFloat": b.camelize();
            var c = a.style[b];
            if (!c && a.currentStyle) {
                c = a.currentStyle[b]
            }
            if (b == "opacity") {
                if (c = (a.getStyle("filter") || "").match(/alpha\(opacity=(.*)\)/)) {
                    if (c[1]) {
                        return parseFloat(c[1]) / 100
                    }
                }
                return 1
            }
            if (c == "auto") {
                if ((b == "width" || b == "height") && (a.getStyle("display") != "none")) {
                    return a["offset" + b.capitalize()] + "px"
                }
                return null
            }
            return c
        };
        Element.Methods.setOpacity = function(b, e) {
            function f(g) {
                return g.replace(/alpha\([^\)]*\)/gi, "")
            }
            b = $(b);
            var a = b.currentStyle;
            if ((a && !a.hasLayout) || (!a && b.style.zoom == "normal")) {
                b.style.zoom = 1
            }
            var d = b.getStyle("filter"),
            c = b.style;
            if (e == 1 || e === "") { (d = f(d)) ? c.filter = d: c.removeAttribute("filter");
                return b
            } else {
                if (e < 0.00001) {
                    e = 0
                }
            }
            c.filter = f(d) + "alpha(opacity=" + (e * 100) + ")";
            return b
        };
        Element._attributeTranslations = (function() {
            var b = "className",
            a = "for",
            c = document.createElement("div");
            c.setAttribute(b, "x");
            if (c.className !== "x") {
                c.setAttribute("class", "x");
                if (c.className === "x") {
                    b = "class"
                }
            }
            c = null;
            c = document.createElement("label");
            c.setAttribute(a, "x");
            if (c.htmlFor !== "x") {
                c.setAttribute("htmlFor", "x");
                if (c.htmlFor === "x") {
                    a = "htmlFor"
                }
            }
            c = null;
            return {
                read: {
                    names: {
                        "class": b,
                        className: b,
                        "for": a,
                        htmlFor: a
                    },
                    values: {
                        _getAttr: function(d, e) {
                            return d.getAttribute(e)
                        },
                        _getAttr2: function(d, e) {
                            return d.getAttribute(e, 2)
                        },
                        _getAttrNode: function(d, f) {
                            var e = d.getAttributeNode(f);
                            return e ? e.value: ""
                        },
                        _getEv: (function() {
                            var d = document.createElement("div"),
                            g;
                            d.onclick = Prototype.emptyFunction;
                            var e = d.getAttribute("onclick");
                            if (String(e).indexOf("{") > -1) {
                                g = function(f, h) {
                                    h = f.getAttribute(h);
                                    if (!h) {
                                        return null
                                    }
                                    h = h.toString();
                                    h = h.split("{")[1];
                                    h = h.split("}")[0];
                                    return h.strip()
                                }
                            } else {
                                if (e === "") {
                                    g = function(f, h) {
                                        h = f.getAttribute(h);
                                        if (!h) {
                                            return null
                                        }
                                        return h.strip()
                                    }
                                }
                            }
                            d = null;
                            return g
                        })(),
                        _flag: function(d, e) {
                            return $(d).hasAttribute(e) ? e: null
                        },
                        style: function(d) {
                            return d.style.cssText.toLowerCase()
                        },
                        title: function(d) {
                            return d.title
                        }
                    }
                }
            }
        })();
        Element._attributeTranslations.write = {
            names: Object.extend({
                cellpadding: "cellPadding",
                cellspacing: "cellSpacing"
            },
            Element._attributeTranslations.read.names),
            values: {
                checked: function(a, b) {
                    a.checked = !!b
                },
                style: function(a, b) {
                    a.style.cssText = b ? b: ""
                }
            }
        };
        Element._attributeTranslations.has = {};
        $w("colSpan rowSpan vAlign dateTime accessKey tabIndex encType maxLength readOnly longDesc frameBorder").each(function(a) {
            Element._attributeTranslations.write.names[a.toLowerCase()] = a;
            Element._attributeTranslations.has[a.toLowerCase()] = a
        }); (function(a) {
            Object.extend(a, {
                href: a._getAttr2,
                src: a._getAttr2,
                type: a._getAttr,
                action: a._getAttrNode,
                disabled: a._flag,
                checked: a._flag,
                readonly: a._flag,
                multiple: a._flag,
                onload: a._getEv,
                onunload: a._getEv,
                onclick: a._getEv,
                ondblclick: a._getEv,
                onmousedown: a._getEv,
                onmouseup: a._getEv,
                onmouseover: a._getEv,
                onmousemove: a._getEv,
                onmouseout: a._getEv,
                onfocus: a._getEv,
                onblur: a._getEv,
                onkeypress: a._getEv,
                onkeydown: a._getEv,
                onkeyup: a._getEv,
                onsubmit: a._getEv,
                onreset: a._getEv,
                onselect: a._getEv,
                onchange: a._getEv
            })
        })(Element._attributeTranslations.read.values);
        if (Prototype.BrowserFeatures.ElementExtensions) { (function() {
                function a(e) {
                    var b = e.getElementsByTagName("*"),
                    d = [];
                    for (var c = 0, f; f = b[c]; c++) {
                        if (f.tagName !== "!") {
                            d.push(f)
                        }
                    }
                    return d
                }
                Element.Methods.down = function(c, d, b) {
                    c = $(c);
                    if (arguments.length == 1) {
                        return c.firstDescendant()
                    }
                    return Object.isNumber(d) ? a(c)[d] : Element.select(c, d)[b || 0]
                }
            })()
        }
    } else {
        if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
            Element.Methods.setOpacity = function(a, b) {
                a = $(a);
                a.style.opacity = (b == 1) ? 0.999999: (b === "") ? "": (b < 0.00001) ? 0: b;
                return a
            }
        } else {
            if (Prototype.Browser.WebKit) {
                Element.Methods.setOpacity = function(a, b) {
                    a = $(a);
                    a.style.opacity = (b == 1 || b === "") ? "": (b < 0.00001) ? 0: b;
                    if (b == 1) {
                        if (a.tagName.toUpperCase() == "IMG" && a.width) {
                            a.width++;
                            a.width--
                        } else {
                            try {
                                var d = document.createTextNode(" ");
                                a.appendChild(d);
                                a.removeChild(d)
                            } catch(c) {}
                        }
                    }
                    return a
                }
            }
        }
    }
}
if ("outerHTML" in document.documentElement) {
    Element.Methods.replace = function(c, e) {
        c = $(c);
        if (e && e.toElement) {
            e = e.toElement()
        }
        if (Object.isElement(e)) {
            c.parentNode.replaceChild(e, c);
            return c
        }
        e = Object.toHTML(e);
        var d = c.parentNode,
        b = d.tagName.toUpperCase();
        if (Element._insertionTranslations.tags[b]) {
            var f = c.next(),
            a = Element._getContentFromAnonymousElement(b, e.stripScripts());
            d.removeChild(c);
            if (f) {
                a.each(function(g) {
                    d.insertBefore(g, f)
                })
            } else {
                a.each(function(g) {
                    d.appendChild(g)
                })
            }
        } else {
            c.outerHTML = e.stripScripts()
        }
        e.evalScripts.bind(e).defer();
        return c
    }
}
Element._returnOffset = function(b, c) {
    var a = [b, c];
    a.left = b;
    a.top = c;
    return a
};
Element._getContentFromAnonymousElement = function(e, d, f) {
    var g = new Element("div"),
    c = Element._insertionTranslations.tags[e];
    var a = false;
    if (c) {
        a = true
    } else {
        if (f) {
            a = true;
            c = ["", "", 0]
        }
    }
    if (a) {
        g.innerHTML = "&nbsp;" + c[0] + d + c[1];
        g.removeChild(g.firstChild);
        for (var b = c[2]; b--;) {
            g = g.firstChild
        }
    } else {
        g.innerHTML = d
    }
    return $A(g.childNodes)
};
Element._insertionTranslations = {
    before: function(a, b) {
        a.parentNode.insertBefore(b, a)
    },
    top: function(a, b) {
        a.insertBefore(b, a.firstChild)
    },
    bottom: function(a, b) {
        a.appendChild(b)
    },
    after: function(a, b) {
        a.parentNode.insertBefore(b, a.nextSibling)
    },
    tags: {
        TABLE: ["<table>", "</table>", 1],
        TBODY: ["<table><tbody>", "</tbody></table>", 2],
        TR: ["<table><tbody><tr>", "</tr></tbody></table>", 3],
        TD: ["<table><tbody><tr><td>", "</td></tr></tbody></table>", 4],
        SELECT: ["<select>", "</select>", 1]
    }
}; (function() {
    var a = Element._insertionTranslations.tags;
    Object.extend(a, {
        THEAD: a.TBODY,
        TFOOT: a.TBODY,
        TH: a.TD
    })
})();
Element.Methods.Simulated = {
    hasAttribute: function(a, c) {
        c = Element._attributeTranslations.has[c] || c;
        var b = $(a).getAttributeNode(c);
        return !! (b && b.specified)
    }
};
Element.Methods.ByTag = {};
Object.extend(Element, Element.Methods); (function(a) {
    if (!Prototype.BrowserFeatures.ElementExtensions && a.__proto__) {
        window.HTMLElement = {};
        window.HTMLElement.prototype = a.__proto__;
        Prototype.BrowserFeatures.ElementExtensions = true
    }
    a = null
})(document.createElement("div"));
Element.extend = (function() {
    function c(g) {
        if (typeof window.Element != "undefined") {
            var j = window.Element.prototype;
            if (j) {
                var l = "_" + (Math.random() + "").slice(2),
                h = document.createElement(g);
                j[l] = "x";
                var k = (h[l] !== "x");
                delete j[l];
                h = null;
                return k
            }
        }
        return false
    }
    function b(h, g) {
        for (var k in g) {
            var j = g[k];
            if (Object.isFunction(j) && !(k in h)) {
                h[k] = j.methodize()
            }
        }
    }
    var d = c("object");
    if (Prototype.BrowserFeatures.SpecificElementExtensions) {
        if (d) {
            return function(h) {
                if (h && typeof h._extendedByPrototype == "undefined") {
                    var g = h.tagName;
                    if (g && (/^(?:object|applet|embed)$/i.test(g))) {
                        b(h, Element.Methods);
                        b(h, Element.Methods.Simulated);
                        b(h, Element.Methods.ByTag[g.toUpperCase()])
                    }
                }
                return h
            }
        }
        return Prototype.K
    }
    var a = {},
    e = Element.Methods.ByTag;
    var f = Object.extend(function(j) {
        if (!j || typeof j._extendedByPrototype != "undefined" || j.nodeType != 1 || j == window) {
            return j
        }
        var g = Object.clone(a),
        h = j.tagName.toUpperCase();
        if (e[h]) {
            Object.extend(g, e[h])
        }
        b(j, g);
        j._extendedByPrototype = Prototype.emptyFunction;
        return j
    },
    {
        refresh: function() {
            if (!Prototype.BrowserFeatures.ElementExtensions) {
                Object.extend(a, Element.Methods);
                Object.extend(a, Element.Methods.Simulated)
            }
        }
    });
    f.refresh();
    return f
})();
if (document.documentElement.hasAttribute) {
    Element.hasAttribute = function(a, b) {
        return a.hasAttribute(b)
    }
} else {
    Element.hasAttribute = Element.Methods.Simulated.hasAttribute
}
Element.addMethods = function(c) {
    var j = Prototype.BrowserFeatures,
    d = Element.Methods.ByTag;
    if (!c) {
        Object.extend(Form, Form.Methods);
        Object.extend(Form.Element, Form.Element.Methods);
        Object.extend(Element.Methods.ByTag, {
            FORM: Object.clone(Form.Methods),
            INPUT: Object.clone(Form.Element.Methods),
            SELECT: Object.clone(Form.Element.Methods),
            TEXTAREA: Object.clone(Form.Element.Methods),
            BUTTON: Object.clone(Form.Element.Methods)
        })
    }
    if (arguments.length == 2) {
        var b = c;
        c = arguments[1]
    }
    if (!b) {
        Object.extend(Element.Methods, c || {})
    } else {
        if (Object.isArray(b)) {
            b.each(g)
        } else {
            g(b)
        }
    }
    function g(l) {
        l = l.toUpperCase();
        if (!Element.Methods.ByTag[l]) {
            Element.Methods.ByTag[l] = {}
        }
        Object.extend(Element.Methods.ByTag[l], c)
    }
    function a(n, m, l) {
        l = l || false;
        for (var p in n) {
            var o = n[p];
            if (!Object.isFunction(o)) {
                continue
            }
            if (!l || !(p in m)) {
                m[p] = o.methodize()
            }
        }
    }
    function e(o) {
        var l;
        var n = {
            OPTGROUP: "OptGroup",
            TEXTAREA: "TextArea",
            P: "Paragraph",
            FIELDSET: "FieldSet",
            UL: "UList",
            OL: "OList",
            DL: "DList",
            DIR: "Directory",
            H1: "Heading",
            H2: "Heading",
            H3: "Heading",
            H4: "Heading",
            H5: "Heading",
            H6: "Heading",
            Q: "Quote",
            INS: "Mod",
            DEL: "Mod",
            A: "Anchor",
            IMG: "Image",
            CAPTION: "TableCaption",
            COL: "TableCol",
            COLGROUP: "TableCol",
            THEAD: "TableSection",
            TFOOT: "TableSection",
            TBODY: "TableSection",
            TR: "TableRow",
            TH: "TableCell",
            TD: "TableCell",
            FRAMESET: "FrameSet",
            IFRAME: "IFrame"
        };
        if (n[o]) {
            l = "HTML" + n[o] + "Element"
        }
        if (window[l]) {
            return window[l]
        }
        l = "HTML" + o + "Element";
        if (window[l]) {
            return window[l]
        }
        l = "HTML" + o.capitalize() + "Element";
        if (window[l]) {
            return window[l]
        }
        var m = document.createElement(o),
        p = m.__proto__ || m.constructor.prototype;
        m = null;
        return p
    }
    var h = window.HTMLElement ? HTMLElement.prototype: Element.prototype;
    if (j.ElementExtensions) {
        a(Element.Methods, h);
        a(Element.Methods.Simulated, h, true)
    }
    if (j.SpecificElementExtensions) {
        for (var k in Element.Methods.ByTag) {
            var f = e(k);
            if (Object.isUndefined(f)) {
                continue
            }
            a(d[k], f.prototype)
        }
    }
    Object.extend(Element, Element.Methods);
    delete Element.ByTag;
    if (Element.extend.refresh) {
        Element.extend.refresh()
    }
    Element.cache = {}
};
document.viewport = {
    getDimensions: function() {
        return {
            width: this.getWidth(),
            height: this.getHeight()
        }
    },
    getScrollOffsets: function() {
        return Element._returnOffset(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop)
    }
}; (function(b) {
    var g = Prototype.Browser,
    e = document,
    c,
    d = {};
    function a() {
        if (g.WebKit && !e.evaluate) {
            return document
        }
        if (g.Opera && window.parseFloat(window.opera.version()) < 9.5) {
            return document.body
        }
        return document.documentElement
    }
    function f(h) {
        if (!c) {
            c = a()
        }
        d[h] = "client" + h;
        b["get" + h] = function() {
            return c[d[h]]
        };
        return b["get" + h]()
    }
    b.getWidth = f.curry("Width");
    b.getHeight = f.curry("Height")
})(document.viewport);
Element.Storage = {
    UID: 1
};
Element.addMethods({
    getStorage: function(b) {
        if (! (b = $(b))) {
            return
        }
        var a;
        if (b === window) {
            a = 0
        } else {
            if (typeof b._prototypeUID === "undefined") {
                b._prototypeUID = Element.Storage.UID++
            }
            a = b._prototypeUID
        }
        if (!Element.Storage[a]) {
            Element.Storage[a] = $H()
        }
        return Element.Storage[a]
    },
    store: function(b, a, c) {
        if (! (b = $(b))) {
            return
        }
        if (arguments.length === 2) {
            Element.getStorage(b).update(a)
        } else {
            Element.getStorage(b).set(a, c)
        }
        return b
    },
    retrieve: function(c, b, a) {
        if (! (c = $(c))) {
            return
        }
        var e = Element.getStorage(c),
        d = e.get(b);
        if (Object.isUndefined(d)) {
            e.set(b, a);
            d = a
        }
        return d
    },
    clone: function(c, a) {
        if (! (c = $(c))) {
            return
        }
        var e = c.cloneNode(a);
        e._prototypeUID = void 0;
        if (a) {
            var d = Element.select(e, "*"),
            b = d.length;
            while (b--) {
                d[b]._prototypeUID = void 0
            }
        }
        return Element.extend(e)
    },
    purge: function(c) {
        if (! (c = $(c))) {
            return
        }
        var a = Element._purgeElement;
        a(c);
        var d = c.getElementsByTagName("*"),
        b = d.length;
        while (b--) {
            a(d[b])
        }
        return null
    }
}); (function() {
    function h(w) {
        var v = w.match(/^(\d+)%?$/i);
        if (!v) {
            return null
        }
        return (Number(v[1]) / 100)
    }
    function p(G, H, w) {
        var z = null;
        if (Object.isElement(G)) {
            z = G;
            G = z.getStyle(H)
        }
        if (G === null) {
            return null
        }
        if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(G)) {
            return window.parseFloat(G)
        }
        var B = G.include("%"),
        x = (w === document.viewport);
        if (/\d/.test(G) && z && z.runtimeStyle && !(B && x)) {
            var v = z.style.left,
            F = z.runtimeStyle.left;
            z.runtimeStyle.left = z.currentStyle.left;
            z.style.left = G || 0;
            G = z.style.pixelLeft;
            z.style.left = v;
            z.runtimeStyle.left = F;
            return G
        }
        if (z && B) {
            w = w || z.parentNode;
            var y = h(G);
            var C = null;
            var A = z.getStyle("position");
            var E = H.include("left") || H.include("right") || H.include("width");
            var D = H.include("top") || H.include("bottom") || H.include("height");
            if (w === document.viewport) {
                if (E) {
                    C = document.viewport.getWidth()
                } else {
                    if (D) {
                        C = document.viewport.getHeight()
                    }
                }
            } else {
                if (E) {
                    C = $(w).measure("width")
                } else {
                    if (D) {
                        C = $(w).measure("height")
                    }
                }
            }
            return (C === null) ? 0: C * y
        }
        return 0
    }
    function g(v) {
        if (Object.isString(v) && v.endsWith("px")) {
            return v
        }
        return v + "px"
    }
    function k(w) {
        var v = w;
        while (w && w.parentNode) {
            var x = w.getStyle("display");
            if (x === "none") {
                return false
            }
            w = $(w.parentNode)
        }
        return true
    }
    var d = Prototype.K;
    if ("currentStyle" in document.documentElement) {
        d = function(v) {
            if (!v.currentStyle.hasLayout) {
                v.style.zoom = 1
            }
            return v
        }
    }
    function f(v) {
        if (v.include("border")) {
            v = v + "-width"
        }
        return v.camelize()
    }
    Element.Layout = Class.create(Hash, {
        initialize: function($super, w, v) {
            $super();
            this.element = $(w);
            Element.Layout.PROPERTIES.each(function(x) {
                this._set(x, null)
            },
            this);
            if (v) {
                this._preComputing = true;
                this._begin();
                Element.Layout.PROPERTIES.each(this._compute, this);
                this._end();
                this._preComputing = false
            }
        },
        _set: function(w, v) {
            return Hash.prototype.set.call(this, w, v)
        },
        set: function(w, v) {
            throw "Properties of Element.Layout are read-only."
        },
        get: function($super, w) {
            var v = $super(w);
            return v === null ? this._compute(w) : v
        },
        _begin: function() {
            if (this._prepared) {
                return
            }
            var z = this.element;
            if (k(z)) {
                this._prepared = true;
                return
            }
            var B = {
                position: z.style.position || "",
                width: z.style.width || "",
                visibility: z.style.visibility || "",
                display: z.style.display || ""
            };
            z.store("prototype_original_styles", B);
            var C = z.getStyle("position"),
            v = z.getStyle("width");
            if (v === "0px" || v === null) {
                z.style.display = "block";
                v = z.getStyle("width")
            }
            var w = (C === "fixed") ? document.viewport: z.parentNode;
            z.setStyle({
                position: "absolute",
                visibility: "hidden",
                display: "block"
            });
            var x = z.getStyle("width");
            var y;
            if (v && (x === v)) {
                y = p(z, "width", w)
            } else {
                if (C === "absolute" || C === "fixed") {
                    y = p(z, "width", w)
                } else {
                    var D = z.parentNode,
                    A = $(D).getLayout();
                    y = A.get("width") - this.get("margin-left") - this.get("border-left") - this.get("padding-left") - this.get("padding-right") - this.get("border-right") - this.get("margin-right")
                }
            }
            z.setStyle({
                width: y + "px"
            });
            this._prepared = true
        },
        _end: function() {
            var w = this.element;
            var v = w.retrieve("prototype_original_styles");
            w.store("prototype_original_styles", null);
            w.setStyle(v);
            this._prepared = false
        },
        _compute: function(w) {
            var v = Element.Layout.COMPUTATIONS;
            if (! (w in v)) {
                throw "Property not found."
            }
            return this._set(w, v[w].call(this, this.element))
        },
        toObject: function() {
            var v = $A(arguments);
            var w = (v.length === 0) ? Element.Layout.PROPERTIES: v.join(" ").split(" ");
            var x = {};
            w.each(function(y) {
                if (!Element.Layout.PROPERTIES.include(y)) {
                    return
                }
                var z = this.get(y);
                if (z != null) {
                    x[y] = z
                }
            },
            this);
            return x
        },
        toHash: function() {
            var v = this.toObject.apply(this, arguments);
            return new Hash(v)
        },
        toCSS: function() {
            var v = $A(arguments);
            var x = (v.length === 0) ? Element.Layout.PROPERTIES: v.join(" ").split(" ");
            var w = {};
            x.each(function(y) {
                if (!Element.Layout.PROPERTIES.include(y)) {
                    return
                }
                if (Element.Layout.COMPOSITE_PROPERTIES.include(y)) {
                    return
                }
                var z = this.get(y);
                if (z != null) {
                    w[f(y)] = z + "px"
                }
            },
            this);
            return w
        },
        inspect: function() {
            return "#<Element.Layout>"
        }
    });
    Object.extend(Element.Layout, {
        PROPERTIES: $w("height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height"),
        COMPOSITE_PROPERTIES: $w("padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height"),
        COMPUTATIONS: {
            height: function(x) {
                if (!this._preComputing) {
                    this._begin()
                }
                var v = this.get("border-box-height");
                if (v <= 0) {
                    if (!this._preComputing) {
                        this._end()
                    }
                    return 0
                }
                var y = this.get("border-top"),
                w = this.get("border-bottom");
                var A = this.get("padding-top"),
                z = this.get("padding-bottom");
                if (!this._preComputing) {
                    this._end()
                }
                return v - y - w - A - z
            },
            width: function(x) {
                if (!this._preComputing) {
                    this._begin()
                }
                var w = this.get("border-box-width");
                if (w <= 0) {
                    if (!this._preComputing) {
                        this._end()
                    }
                    return 0
                }
                var A = this.get("border-left"),
                v = this.get("border-right");
                var y = this.get("padding-left"),
                z = this.get("padding-right");
                if (!this._preComputing) {
                    this._end()
                }
                return w - A - v - y - z
            },
            "padding-box-height": function(w) {
                var v = this.get("height"),
                y = this.get("padding-top"),
                x = this.get("padding-bottom");
                return v + y + x
            },
            "padding-box-width": function(v) {
                var w = this.get("width"),
                x = this.get("padding-left"),
                y = this.get("padding-right");
                return w + x + y
            },
            "border-box-height": function(w) {
                if (!this._preComputing) {
                    this._begin()
                }
                var v = w.offsetHeight;
                if (!this._preComputing) {
                    this._end()
                }
                return v
            },
            "border-box-width": function(v) {
                if (!this._preComputing) {
                    this._begin()
                }
                var w = v.offsetWidth;
                if (!this._preComputing) {
                    this._end()
                }
                return w
            },
            "margin-box-height": function(w) {
                var v = this.get("border-box-height"),
                x = this.get("margin-top"),
                y = this.get("margin-bottom");
                if (v <= 0) {
                    return 0
                }
                return v + x + y
            },
            "margin-box-width": function(x) {
                var w = this.get("border-box-width"),
                y = this.get("margin-left"),
                v = this.get("margin-right");
                if (w <= 0) {
                    return 0
                }
                return w + y + v
            },
            top: function(v) {
                var w = v.positionedOffset();
                return w.top
            },
            bottom: function(v) {
                var y = v.positionedOffset(),
                w = v.getOffsetParent(),
                x = w.measure("height");
                var z = this.get("border-box-height");
                return x - z - y.top
            },
            left: function(v) {
                var w = v.positionedOffset();
                return w.left
            },
            right: function(x) {
                var z = x.positionedOffset(),
                y = x.getOffsetParent(),
                v = y.measure("width");
                var w = this.get("border-box-width");
                return v - w - z.left
            },
            "padding-top": function(v) {
                return p(v, "paddingTop")
            },
            "padding-bottom": function(v) {
                return p(v, "paddingBottom")
            },
            "padding-left": function(v) {
                return p(v, "paddingLeft")
            },
            "padding-right": function(v) {
                return p(v, "paddingRight")
            },
            "border-top": function(v) {
                return p(v, "borderTopWidth")
            },
            "border-bottom": function(v) {
                return p(v, "borderBottomWidth")
            },
            "border-left": function(v) {
                return p(v, "borderLeftWidth")
            },
            "border-right": function(v) {
                return p(v, "borderRightWidth")
            },
            "margin-top": function(v) {
                return p(v, "marginTop")
            },
            "margin-bottom": function(v) {
                return p(v, "marginBottom")
            },
            "margin-left": function(v) {
                return p(v, "marginLeft")
            },
            "margin-right": function(v) {
                return p(v, "marginRight")
            }
        }
    });
    if ("getBoundingClientRect" in document.documentElement) {
        Object.extend(Element.Layout.COMPUTATIONS, {
            right: function(w) {
                var x = d(w.getOffsetParent());
                var y = w.getBoundingClientRect(),
                v = x.getBoundingClientRect();
                return (v.right - y.right).round()
            },
            bottom: function(w) {
                var x = d(w.getOffsetParent());
                var y = w.getBoundingClientRect(),
                v = x.getBoundingClientRect();
                return (v.bottom - y.bottom).round()
            }
        })
    }
    Element.Offset = Class.create({
        initialize: function(w, v) {
            this.left = w.round();
            this.top = v.round();
            this[0] = this.left;
            this[1] = this.top
        },
        relativeTo: function(v) {
            return new Element.Offset(this.left - v.left, this.top - v.top)
        },
        inspect: function() {
            return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this)
        },
        toString: function() {
            return "[#{left}, #{top}]".interpolate(this)
        },
        toArray: function() {
            return [this.left, this.top]
        }
    });
    function s(w, v) {
        return new Element.Layout(w, v)
    }
    function b(v, w) {
        return $(v).getLayout().get(w)
    }
    function o(w) {
        w = $(w);
        var A = Element.getStyle(w, "display");
        if (A && A !== "none") {
            return {
                width: w.offsetWidth,
                height: w.offsetHeight
            }
        }
        var x = w.style;
        var v = {
            visibility: x.visibility,
            position: x.position,
            display: x.display
        };
        var z = {
            visibility: "hidden",
            display: "block"
        };
        if (v.position !== "fixed") {
            z.position = "absolute"
        }
        Element.setStyle(w, z);
        var y = {
            width: w.offsetWidth,
            height: w.offsetHeight
        };
        Element.setStyle(w, v);
        return y
    }
    function m(v) {
        v = $(v);
        if (e(v) || c(v) || n(v) || l(v)) {
            return $(document.body)
        }
        var w = (Element.getStyle(v, "display") === "inline");
        if (!w && v.offsetParent) {
            return $(v.offsetParent)
        }
        while ((v = v.parentNode) && v !== document.body) {
            if (Element.getStyle(v, "position") !== "static") {
                return l(v) ? $(document.body) : $(v)
            }
        }
        return $(document.body)
    }
    function u(w) {
        w = $(w);
        var v = 0,
        x = 0;
        if (w.parentNode) {
            do {
                v += w.offsetTop || 0;
                x += w.offsetLeft || 0;
                w = w.offsetParent
            }
            while (w)
        }
        return new Element.Offset(x, v)
    }
    function q(w) {
        w = $(w);
        var x = w.getLayout();
        var v = 0,
        z = 0;
        do {
            v += w.offsetTop || 0;
            z += w.offsetLeft || 0;
            w = w.offsetParent;
            if (w) {
                if (n(w)) {
                    break
                }
                var y = Element.getStyle(w, "position");
                if (y !== "static") {
                    break
                }
            }
        }
        while (w);
        z -= x.get("margin-top");
        v -= x.get("margin-left");
        return new Element.Offset(z, v)
    }
    function a(w) {
        var v = 0,
        x = 0;
        do {
            v += w.scrollTop || 0;
            x += w.scrollLeft || 0;
            w = w.parentNode
        }
        while (w);
        return new Element.Offset(x, v)
    }
    function t(z) {
        w = $(w);
        var v = 0,
        y = 0,
        x = document.body;
        var w = z;
        do {
            v += w.offsetTop || 0;
            y += w.offsetLeft || 0;
            if (w.offsetParent == x && Element.getStyle(w, "position") == "absolute") {
                break
            }
        }
        while (w = w.offsetParent);
        w = z;
        do {
            if (w != x) {
                v -= w.scrollTop || 0;
                y -= w.scrollLeft || 0
            }
        }
        while (w = w.parentNode);
        return new Element.Offset(y, v)
    }
    function r(v) {
        v = $(v);
        if (Element.getStyle(v, "position") === "absolute") {
            return v
        }
        var z = m(v);
        var y = v.viewportOffset(),
        w = z.viewportOffset();
        var A = y.relativeTo(w);
        var x = v.getLayout();
        v.store("prototype_absolutize_original_styles", {
            left: v.getStyle("left"),
            top: v.getStyle("top"),
            width: v.getStyle("width"),
            height: v.getStyle("height")
        });
        v.setStyle({
            position: "absolute",
            top: A.top + "px",
            left: A.left + "px",
            width: x.get("width") + "px",
            height: x.get("height") + "px"
        });
        return v
    }
    function j(w) {
        w = $(w);
        if (Element.getStyle(w, "position") === "relative") {
            return w
        }
        var v = w.retrieve("prototype_absolutize_original_styles");
        if (v) {
            w.setStyle(v)
        }
        return w
    }
    if (Prototype.Browser.IE) {
        m = m.wrap(function(x, w) {
            w = $(w);
            if (e(w) || c(w) || n(w) || l(w)) {
                return $(document.body)
            }
            var v = w.getStyle("position");
            if (v !== "static") {
                return x(w)
            }
            w.setStyle({
                position: "relative"
            });
            var y = x(w);
            w.setStyle({
                position: v
            });
            return y
        });
        q = q.wrap(function(y, w) {
            w = $(w);
            if (!w.parentNode) {
                return new Element.Offset(0, 0)
            }
            var v = w.getStyle("position");
            if (v !== "static") {
                return y(w)
            }
            var x = w.getOffsetParent();
            if (x && x.getStyle("position") === "fixed") {
                d(x)
            }
            w.setStyle({
                position: "relative"
            });
            var z = y(w);
            w.setStyle({
                position: v
            });
            return z
        })
    } else {
        if (Prototype.Browser.Webkit) {
            u = function(w) {
                w = $(w);
                var v = 0,
                x = 0;
                do {
                    v += w.offsetTop || 0;
                    x += w.offsetLeft || 0;
                    if (w.offsetParent == document.body) {
                        if (Element.getStyle(w, "position") == "absolute") {
                            break
                        }
                    }
                    w = w.offsetParent
                }
                while (w);
                return new Element.Offset(x, v)
            }
        }
    }
    Element.addMethods({
        getLayout: s,
        measure: b,
        getDimensions: o,
        getOffsetParent: m,
        cumulativeOffset: u,
        positionedOffset: q,
        cumulativeScrollOffset: a,
        viewportOffset: t,
        absolutize: r,
        relativize: j
    });
    function n(v) {
        return v.nodeName.toUpperCase() === "BODY"
    }
    function l(v) {
        return v.nodeName.toUpperCase() === "HTML"
    }
    function e(v) {
        return v.nodeType === Node.DOCUMENT_NODE
    }
    function c(v) {
        return v !== document.body && !Element.descendantOf(v, document.body)
    }
    if ("getBoundingClientRect" in document.documentElement) {
        Element.addMethods({
            viewportOffset: function(v) {
                v = $(v);
                if (c(v)) {
                    return new Element.Offset(0, 0)
                }
                var w = v.getBoundingClientRect(),
                x = document.documentElement;
                return new Element.Offset(w.left - x.clientLeft, w.top - x.clientTop)
            }
        })
    }
})();
window.$$ = function() {
    var a = $A(arguments).join(", ");
    return Prototype.Selector.select(a, document)
};
Prototype.Selector = (function() {
    function a() {
        throw new Error('Method "Prototype.Selector.select" must be defined.')
    }
    function c() {
        throw new Error('Method "Prototype.Selector.match" must be defined.')
    }
    function d(l, m, h) {
        h = h || 0;
        var g = Prototype.Selector.match,
        k = l.length,
        f = 0,
        j;
        for (j = 0; j < k; j++) {
            if (g(l[j], m) && h == f++) {
                return Element.extend(l[j])
            }
        }
    }
    function e(h) {
        for (var f = 0, g = h.length; f < g; f++) {
            Element.extend(h[f])
        }
        return h
    }
    var b = Prototype.K;
    return {
        select: a,
        match: c,
        find: d,
        extendElements: (Element.extend === b) ? b: e,
        extendElement: Element.extend
    }
})();
/*
 * Sizzle CSS Selector Engine - v1.0
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
 (function() {
    var r = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
    k = 0,
    d = Object.prototype.toString,
    p = false,
    j = true; [0, 0].sort(function() {
        j = false;
        return 0
    });
    var b = function(F, v, C, x) {
        C = C || [];
        var e = v = v || document;
        if (v.nodeType !== 1 && v.nodeType !== 9) {
            return []
        }
        if (!F || typeof F !== "string") {
            return C
        }
        var D = [],
        E,
        A,
        J,
        I,
        B,
        u,
        t = true,
        y = q(v),
        H = F;
        while ((r.exec(""), E = r.exec(H)) !== null) {
            H = E[3];
            D.push(E[1]);
            if (E[2]) {
                u = E[3];
                break
            }
        }
        if (D.length > 1 && l.exec(F)) {
            if (D.length === 2 && f.relative[D[0]]) {
                A = g(D[0] + D[1], v)
            } else {
                A = f.relative[D[0]] ? [v] : b(D.shift(), v);
                while (D.length) {
                    F = D.shift();
                    if (f.relative[F]) {
                        F += D.shift()
                    }
                    A = g(F, A)
                }
            }
        } else {
            if (!x && D.length > 1 && v.nodeType === 9 && !y && f.match.ID.test(D[0]) && !f.match.ID.test(D[D.length - 1])) {
                var K = b.find(D.shift(), v, y);
                v = K.expr ? b.filter(K.expr, K.set)[0] : K.set[0]
            }
            if (v) {
                var K = x ? {
                    expr: D.pop(),
                    set: a(x)
                }: b.find(D.pop(), D.length === 1 && (D[0] === "~" || D[0] === "+") && v.parentNode ? v.parentNode: v, y);
                A = K.expr ? b.filter(K.expr, K.set) : K.set;
                if (D.length > 0) {
                    J = a(A)
                } else {
                    t = false
                }
                while (D.length) {
                    var w = D.pop(),
                    z = w;
                    if (!f.relative[w]) {
                        w = ""
                    } else {
                        z = D.pop()
                    }
                    if (z == null) {
                        z = v
                    }
                    f.relative[w](J, z, y)
                }
            } else {
                J = D = []
            }
        }
        if (!J) {
            J = A
        }
        if (!J) {
            throw "Syntax error, unrecognized expression: " + (w || F)
        }
        if (d.call(J) === "[object Array]") {
            if (!t) {
                C.push.apply(C, J)
            } else {
                if (v && v.nodeType === 1) {
                    for (var G = 0; J[G] != null; G++) {
                        if (J[G] && (J[G] === true || J[G].nodeType === 1 && h(v, J[G]))) {
                            C.push(A[G])
                        }
                    }
                } else {
                    for (var G = 0; J[G] != null; G++) {
                        if (J[G] && J[G].nodeType === 1) {
                            C.push(A[G])
                        }
                    }
                }
            }
        } else {
            a(J, C)
        }
        if (u) {
            b(u, e, C, x);
            b.uniqueSort(C)
        }
        return C
    };
    b.uniqueSort = function(t) {
        if (c) {
            p = j;
            t.sort(c);
            if (p) {
                for (var e = 1; e < t.length; e++) {
                    if (t[e] === t[e - 1]) {
                        t.splice(e--, 1)
                    }
                }
            }
        }
        return t
    };
    b.matches = function(e, t) {
        return b(e, null, null, t)
    };
    b.find = function(z, e, A) {
        var y,
        w;
        if (!z) {
            return []
        }
        for (var v = 0, u = f.order.length; v < u; v++) {
            var x = f.order[v],
            w;
            if ((w = f.leftMatch[x].exec(z))) {
                var t = w[1];
                w.splice(1, 1);
                if (t.substr(t.length - 1) !== "\\") {
                    w[1] = (w[1] || "").replace(/\\/g, "");
                    y = f.find[x](w, e, A);
                    if (y != null) {
                        z = z.replace(f.match[x], "");
                        break
                    }
                }
            }
        }
        if (!y) {
            y = e.getElementsByTagName("*")
        }
        return {
            set: y,
            expr: z
        }
    };
    b.filter = function(C, B, F, v) {
        var u = C,
        H = [],
        z = B,
        x,
        e,
        y = B && B[0] && q(B[0]);
        while (C && B.length) {
            for (var A in f.filter) {
                if ((x = f.match[A].exec(C)) != null) {
                    var t = f.filter[A],
                    G,
                    E;
                    e = false;
                    if (z == H) {
                        H = []
                    }
                    if (f.preFilter[A]) {
                        x = f.preFilter[A](x, z, F, H, v, y);
                        if (!x) {
                            e = G = true
                        } else {
                            if (x === true) {
                                continue
                            }
                        }
                    }
                    if (x) {
                        for (var w = 0; (E = z[w]) != null; w++) {
                            if (E) {
                                G = t(E, x, w, z);
                                var D = v ^ !!G;
                                if (F && G != null) {
                                    if (D) {
                                        e = true
                                    } else {
                                        z[w] = false
                                    }
                                } else {
                                    if (D) {
                                        H.push(E);
                                        e = true
                                    }
                                }
                            }
                        }
                    }
                    if (G !== undefined) {
                        if (!F) {
                            z = H
                        }
                        C = C.replace(f.match[A], "");
                        if (!e) {
                            return []
                        }
                        break
                    }
                }
            }
            if (C == u) {
                if (e == null) {
                    throw "Syntax error, unrecognized expression: " + C
                } else {
                    break
                }
            }
            u = C
        }
        return z
    };
    var f = b.selectors = {
        order: ["ID", "NAME", "TAG"],
        match: {
            ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
            CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
            NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
            ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
            TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
            CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
            POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
            PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
        },
        leftMatch: {},
        attrMap: {
            "class": "className",
            "for": "htmlFor"
        },
        attrHandle: {
            href: function(e) {
                return e.getAttribute("href")
            }
        },
        relative: {
            "+": function(z, e, y) {
                var w = typeof e === "string",
                A = w && !/\W/.test(e),
                x = w && !A;
                if (A && !y) {
                    e = e.toUpperCase()
                }
                for (var v = 0, u = z.length, t; v < u; v++) {
                    if ((t = z[v])) {
                        while ((t = t.previousSibling) && t.nodeType !== 1) {}
                        z[v] = x || t && t.nodeName === e ? t || false: t === e
                    }
                }
                if (x) {
                    b.filter(e, z, true)
                }
            },
            ">": function(y, t, z) {
                var w = typeof t === "string";
                if (w && !/\W/.test(t)) {
                    t = z ? t: t.toUpperCase();
                    for (var u = 0, e = y.length; u < e; u++) {
                        var x = y[u];
                        if (x) {
                            var v = x.parentNode;
                            y[u] = v.nodeName === t ? v: false
                        }
                    }
                } else {
                    for (var u = 0, e = y.length; u < e; u++) {
                        var x = y[u];
                        if (x) {
                            y[u] = w ? x.parentNode: x.parentNode === t
                        }
                    }
                    if (w) {
                        b.filter(t, y, true)
                    }
                }
            },
            "": function(v, t, x) {
                var u = k++,
                e = s;
                if (!/\W/.test(t)) {
                    var w = t = x ? t: t.toUpperCase();
                    e = o
                }
                e("parentNode", t, u, v, w, x)
            },
            "~": function(v, t, x) {
                var u = k++,
                e = s;
                if (typeof t === "string" && !/\W/.test(t)) {
                    var w = t = x ? t: t.toUpperCase();
                    e = o
                }
                e("previousSibling", t, u, v, w, x)
            }
        },
        find: {
            ID: function(t, u, v) {
                if (typeof u.getElementById !== "undefined" && !v) {
                    var e = u.getElementById(t[1]);
                    return e ? [e] : []
                }
            },
            NAME: function(u, x, y) {
                if (typeof x.getElementsByName !== "undefined") {
                    var t = [],
                    w = x.getElementsByName(u[1]);
                    for (var v = 0, e = w.length; v < e; v++) {
                        if (w[v].getAttribute("name") === u[1]) {
                            t.push(w[v])
                        }
                    }
                    return t.length === 0 ? null: t
                }
            },
            TAG: function(e, t) {
                return t.getElementsByTagName(e[1])
            }
        },
        preFilter: {
            CLASS: function(v, t, u, e, y, z) {
                v = " " + v[1].replace(/\\/g, "") + " ";
                if (z) {
                    return v
                }
                for (var w = 0, x; (x = t[w]) != null; w++) {
                    if (x) {
                        if (y ^ (x.className && (" " + x.className + " ").indexOf(v) >= 0)) {
                            if (!u) {
                                e.push(x)
                            }
                        } else {
                            if (u) {
                                t[w] = false
                            }
                        }
                    }
                }
                return false
            },
            ID: function(e) {
                return e[1].replace(/\\/g, "")
            },
            TAG: function(t, e) {
                for (var u = 0; e[u] === false; u++) {}
                return e[u] && q(e[u]) ? t[1] : t[1].toUpperCase()
            },
            CHILD: function(e) {
                if (e[1] == "nth") {
                    var t = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2] == "even" && "2n" || e[2] == "odd" && "2n+1" || !/\D/.test(e[2]) && "0n+" + e[2] || e[2]);
                    e[2] = (t[1] + (t[2] || 1)) - 0;
                    e[3] = t[3] - 0
                }
                e[0] = k++;
                return e
            },
            ATTR: function(w, t, u, e, x, y) {
                var v = w[1].replace(/\\/g, "");
                if (!y && f.attrMap[v]) {
                    w[1] = f.attrMap[v]
                }
                if (w[2] === "~=") {
                    w[4] = " " + w[4] + " "
                }
                return w
            },
            PSEUDO: function(w, t, u, e, x) {
                if (w[1] === "not") {
                    if ((r.exec(w[3]) || "").length > 1 || /^\w/.test(w[3])) {
                        w[3] = b(w[3], null, null, t)
                    } else {
                        var v = b.filter(w[3], t, u, true ^ x);
                        if (!u) {
                            e.push.apply(e, v)
                        }
                        return false
                    }
                } else {
                    if (f.match.POS.test(w[0]) || f.match.CHILD.test(w[0])) {
                        return true
                    }
                }
                return w
            },
            POS: function(e) {
                e.unshift(true);
                return e
            }
        },
        filters: {
            enabled: function(e) {
                return e.disabled === false && e.type !== "hidden"
            },
            disabled: function(e) {
                return e.disabled === true
            },
            checked: function(e) {
                return e.checked === true
            },
            selected: function(e) {
                e.parentNode.selectedIndex;
                return e.selected === true
            },
            parent: function(e) {
                return !! e.firstChild
            },
            empty: function(e) {
                return ! e.firstChild
            },
            has: function(u, t, e) {
                return !! b(e[3], u).length
            },
            header: function(e) {
                return /h\d/i.test(e.nodeName)
            },
            text: function(e) {
                return "text" === e.type
            },
            radio: function(e) {
                return "radio" === e.type
            },
            checkbox: function(e) {
                return "checkbox" === e.type
            },
            file: function(e) {
                return "file" === e.type
            },
            password: function(e) {
                return "password" === e.type
            },
            submit: function(e) {
                return "submit" === e.type
            },
            image: function(e) {
                return "image" === e.type
            },
            reset: function(e) {
                return "reset" === e.type
            },
            button: function(e) {
                return "button" === e.type || e.nodeName.toUpperCase() === "BUTTON"
            },
            input: function(e) {
                return /input|select|textarea|button/i.test(e.nodeName)
            }
        },
        setFilters: {
            first: function(t, e) {
                return e === 0
            },
            last: function(u, t, e, v) {
                return t === v.length - 1
            },
            even: function(t, e) {
                return e % 2 === 0
            },
            odd: function(t, e) {
                return e % 2 === 1
            },
            lt: function(u, t, e) {
                return t < e[3] - 0
            },
            gt: function(u, t, e) {
                return t > e[3] - 0
            },
            nth: function(u, t, e) {
                return e[3] - 0 == t
            },
            eq: function(u, t, e) {
                return e[3] - 0 == t
            }
        },
        filter: {
            PSEUDO: function(y, u, v, z) {
                var t = u[1],
                w = f.filters[t];
                if (w) {
                    return w(y, v, u, z)
                } else {
                    if (t === "contains") {
                        return (y.textContent || y.innerText || "").indexOf(u[3]) >= 0
                    } else {
                        if (t === "not") {
                            var x = u[3];
                            for (var v = 0, e = x.length; v < e; v++) {
                                if (x[v] === y) {
                                    return false
                                }
                            }
                            return true
                        }
                    }
                }
            },
            CHILD: function(e, v) {
                var y = v[1],
                t = e;
                switch (y) {
                case "only":
                case "first":
                    while ((t = t.previousSibling)) {
                        if (t.nodeType === 1) {
                            return false
                        }
                    }
                    if (y == "first") {
                        return true
                    }
                    t = e;
                case "last":
                    while ((t = t.nextSibling)) {
                        if (t.nodeType === 1) {
                            return false
                        }
                    }
                    return true;
                case "nth":
                    var u = v[2],
                    B = v[3];
                    if (u == 1 && B == 0) {
                        return true
                    }
                    var x = v[0],
                    A = e.parentNode;
                    if (A && (A.sizcache !== x || !e.nodeIndex)) {
                        var w = 0;
                        for (t = A.firstChild; t; t = t.nextSibling) {
                            if (t.nodeType === 1) {
                                t.nodeIndex = ++w
                            }
                        }
                        A.sizcache = x
                    }
                    var z = e.nodeIndex - B;
                    if (u == 0) {
                        return z == 0
                    } else {
                        return (z % u == 0 && z / u >= 0)
                    }
                }
            },
            ID: function(t, e) {
                return t.nodeType === 1 && t.getAttribute("id") === e
            },
            TAG: function(t, e) {
                return (e === "*" && t.nodeType === 1) || t.nodeName === e
            },
            CLASS: function(t, e) {
                return (" " + (t.className || t.getAttribute("class")) + " ").indexOf(e) > -1
            },
            ATTR: function(x, v) {
                var u = v[1],
                e = f.attrHandle[u] ? f.attrHandle[u](x) : x[u] != null ? x[u] : x.getAttribute(u),
                y = e + "",
                w = v[2],
                t = v[4];
                return e == null ? w === "!=": w === "=" ? y === t: w === "*=" ? y.indexOf(t) >= 0: w === "~=" ? (" " + y + " ").indexOf(t) >= 0: !t ? y && e !== false: w === "!=" ? y != t: w === "^=" ? y.indexOf(t) === 0: w === "$=" ? y.substr(y.length - t.length) === t: w === "|=" ? y === t || y.substr(0, t.length + 1) === t + "-": false
            },
            POS: function(w, t, u, x) {
                var e = t[2],
                v = f.setFilters[e];
                if (v) {
                    return v(w, u, t, x)
                }
            }
        }
    };
    var l = f.match.POS;
    for (var n in f.match) {
        f.match[n] = new RegExp(f.match[n].source + /(?![^\[]*\])(?![^\(]*\))/.source);
        f.leftMatch[n] = new RegExp(/(^(?:.|\r|\n)*?)/.source + f.match[n].source)
    }
    var a = function(t, e) {
        t = Array.prototype.slice.call(t, 0);
        if (e) {
            e.push.apply(e, t);
            return e
        }
        return t
    };
    try {
        Array.prototype.slice.call(document.documentElement.childNodes, 0)
    } catch(m) {
        a = function(w, v) {
            var t = v || [];
            if (d.call(w) === "[object Array]") {
                Array.prototype.push.apply(t, w)
            } else {
                if (typeof w.length === "number") {
                    for (var u = 0, e = w.length; u < e; u++) {
                        t.push(w[u])
                    }
                } else {
                    for (var u = 0; w[u]; u++) {
                        t.push(w[u])
                    }
                }
            }
            return t
        }
    }
    var c;
    if (document.documentElement.compareDocumentPosition) {
        c = function(t, e) {
            if (!t.compareDocumentPosition || !e.compareDocumentPosition) {
                if (t == e) {
                    p = true
                }
                return 0
            }
            var u = t.compareDocumentPosition(e) & 4 ? -1: t === e ? 0: 1;
            if (u === 0) {
                p = true
            }
            return u
        }
    } else {
        if ("sourceIndex" in document.documentElement) {
            c = function(t, e) {
                if (!t.sourceIndex || !e.sourceIndex) {
                    if (t == e) {
                        p = true
                    }
                    return 0
                }
                var u = t.sourceIndex - e.sourceIndex;
                if (u === 0) {
                    p = true
                }
                return u
            }
        } else {
            if (document.createRange) {
                c = function(v, t) {
                    if (!v.ownerDocument || !t.ownerDocument) {
                        if (v == t) {
                            p = true
                        }
                        return 0
                    }
                    var u = v.ownerDocument.createRange(),
                    e = t.ownerDocument.createRange();
                    u.setStart(v, 0);
                    u.setEnd(v, 0);
                    e.setStart(t, 0);
                    e.setEnd(t, 0);
                    var w = u.compareBoundaryPoints(Range.START_TO_END, e);
                    if (w === 0) {
                        p = true
                    }
                    return w
                }
            }
        }
    } (function() {
        var t = document.createElement("div"),
        u = "script" + (new Date).getTime();
        t.innerHTML = "<a name='" + u + "'/>";
        var e = document.documentElement;
        e.insertBefore(t, e.firstChild);
        if ( !! document.getElementById(u)) {
            f.find.ID = function(w, x, y) {
                if (typeof x.getElementById !== "undefined" && !y) {
                    var v = x.getElementById(w[1]);
                    return v ? v.id === w[1] || typeof v.getAttributeNode !== "undefined" && v.getAttributeNode("id").nodeValue === w[1] ? [v] : undefined: []
                }
            };
            f.filter.ID = function(x, v) {
                var w = typeof x.getAttributeNode !== "undefined" && x.getAttributeNode("id");
                return x.nodeType === 1 && w && w.nodeValue === v
            }
        }
        e.removeChild(t);
        e = t = null
    })(); (function() {
        var e = document.createElement("div");
        e.appendChild(document.createComment(""));
        if (e.getElementsByTagName("*").length > 0) {
            f.find.TAG = function(t, x) {
                var w = x.getElementsByTagName(t[1]);
                if (t[1] === "*") {
                    var v = [];
                    for (var u = 0; w[u]; u++) {
                        if (w[u].nodeType === 1) {
                            v.push(w[u])
                        }
                    }
                    w = v
                }
                return w
            }
        }
        e.innerHTML = "<a href='#'></a>";
        if (e.firstChild && typeof e.firstChild.getAttribute !== "undefined" && e.firstChild.getAttribute("href") !== "#") {
            f.attrHandle.href = function(t) {
                return t.getAttribute("href", 2)
            }
        }
        e = null
    })();
    if (document.querySelectorAll) { (function() {
            var e = b,
            u = document.createElement("div");
            u.innerHTML = "<p class='TEST'></p>";
            if (u.querySelectorAll && u.querySelectorAll(".TEST").length === 0) {
                return
            }
            b = function(y, x, v, w) {
                x = x || document;
                if (!w && x.nodeType === 9 && !q(x)) {
                    try {
                        return a(x.querySelectorAll(y), v)
                    } catch(z) {}
                }
                return e(y, x, v, w)
            };
            for (var t in e) {
                b[t] = e[t]
            }
            u = null
        })()
    }
    if (document.getElementsByClassName && document.documentElement.getElementsByClassName) { (function() {
            var e = document.createElement("div");
            e.innerHTML = "<div class='test e'></div><div class='test'></div>";
            if (e.getElementsByClassName("e").length === 0) {
                return
            }
            e.lastChild.className = "e";
            if (e.getElementsByClassName("e").length === 1) {
                return
            }
            f.order.splice(1, 0, "CLASS");
            f.find.CLASS = function(t, u, v) {
                if (typeof u.getElementsByClassName !== "undefined" && !v) {
                    return u.getElementsByClassName(t[1])
                }
            };
            e = null
        })()
    }
    function o(t, y, x, C, z, B) {
        var A = t == "previousSibling" && !B;
        for (var v = 0, u = C.length; v < u; v++) {
            var e = C[v];
            if (e) {
                if (A && e.nodeType === 1) {
                    e.sizcache = x;
                    e.sizset = v
                }
                e = e[t];
                var w = false;
                while (e) {
                    if (e.sizcache === x) {
                        w = C[e.sizset];
                        break
                    }
                    if (e.nodeType === 1 && !B) {
                        e.sizcache = x;
                        e.sizset = v
                    }
                    if (e.nodeName === y) {
                        w = e;
                        break
                    }
                    e = e[t]
                }
                C[v] = w
            }
        }
    }
    function s(t, y, x, C, z, B) {
        var A = t == "previousSibling" && !B;
        for (var v = 0, u = C.length; v < u; v++) {
            var e = C[v];
            if (e) {
                if (A && e.nodeType === 1) {
                    e.sizcache = x;
                    e.sizset = v
                }
                e = e[t];
                var w = false;
                while (e) {
                    if (e.sizcache === x) {
                        w = C[e.sizset];
                        break
                    }
                    if (e.nodeType === 1) {
                        if (!B) {
                            e.sizcache = x;
                            e.sizset = v
                        }
                        if (typeof y !== "string") {
                            if (e === y) {
                                w = true;
                                break
                            }
                        } else {
                            if (b.filter(y, [e]).length > 0) {
                                w = e;
                                break
                            }
                        }
                    }
                    e = e[t]
                }
                C[v] = w
            }
        }
    }
    var h = document.compareDocumentPosition ?
    function(t, e) {
        return t.compareDocumentPosition(e) & 16
    }: function(t, e) {
        return t !== e && (t.contains ? t.contains(e) : true)
    };
    var q = function(e) {
        return e.nodeType === 9 && e.documentElement.nodeName !== "HTML" || !!e.ownerDocument && e.ownerDocument.documentElement.nodeName !== "HTML"
    };
    var g = function(e, z) {
        var v = [],
        w = "",
        x,
        u = z.nodeType ? [z] : z;
        while ((x = f.match.PSEUDO.exec(e))) {
            w += x[0];
            e = e.replace(f.match.PSEUDO, "")
        }
        e = f.relative[e] ? e + "*": e;
        for (var y = 0, t = u.length; y < t; y++) {
            b(e, u[y], v)
        }
        return b.filter(w, v)
    };
    window.Sizzle = b
})();
Prototype._original_property = window.Sizzle; (function(c) {
    var d = Prototype.Selector.extendElements;
    function a(e, f) {
        return d(c(e, f || document))
    }
    function b(f, e) {
        return c.matches(e, [f]).length == 1
    }
    Prototype.Selector.engine = c;
    Prototype.Selector.select = a;
    Prototype.Selector.match = b
})(Sizzle);
window.Sizzle = Prototype._original_property;
delete Prototype._original_property;
var Form = {
    reset: function(a) {
        a = $(a);
        a.reset();
        return a
    },
    serializeElements: function(h, d) {
        if (typeof d != "object") {
            d = {
                hash: !!d
            }
        } else {
            if (Object.isUndefined(d.hash)) {
                d.hash = true
            }
        }
        var e,
        g,
        a = false,
        f = d.submit,
        b,
        c;
        if (d.hash) {
            c = {};
            b = function(j, k, l) {
                if (k in j) {
                    if (!Object.isArray(j[k])) {
                        j[k] = [j[k]]
                    }
                    j[k].push(l)
                } else {
                    j[k] = l
                }
                return j
            }
        } else {
            c = "";
            b = function(j, k, l) {
                return j + (j ? "&": "") + encodeURIComponent(k) + "=" + encodeURIComponent(l)
            }
        }
        return h.inject(c,
        function(j, k) {
            if (!k.disabled && k.name) {
                e = k.name;
                g = $(k).getValue();
                if (g != null && k.type != "file" && (k.type != "submit" || (!a && f !== false && (!f || e == f) && (a = true)))) {
                    j = b(j, e, g)
                }
            }
            return j
        })
    }
};
Form.Methods = {
    serialize: function(b, a) {
        return Form.serializeElements(Form.getElements(b), a)
    },
    getElements: function(e) {
        var f = $(e).getElementsByTagName("*"),
        d,
        a = [],
        c = Form.Element.Serializers;
        for (var b = 0; d = f[b]; b++) {
            a.push(d)
        }
        return a.inject([],
        function(g, h) {
            if (c[h.tagName.toLowerCase()]) {
                g.push(Element.extend(h))
            }
            return g
        })
    },
    getInputs: function(g, c, d) {
        g = $(g);
        var a = g.getElementsByTagName("input");
        if (!c && !d) {
            return $A(a).map(Element.extend)
        }
        for (var e = 0, h = [], f = a.length; e < f; e++) {
            var b = a[e];
            if ((c && b.type != c) || (d && b.name != d)) {
                continue
            }
            h.push(Element.extend(b))
        }
        return h
    },
    disable: function(a) {
        a = $(a);
        Form.getElements(a).invoke("disable");
        return a
    },
    enable: function(a) {
        a = $(a);
        Form.getElements(a).invoke("enable");
        return a
    },
    findFirstElement: function(b) {
        var c = $(b).getElements().findAll(function(d) {
            return "hidden" != d.type && !d.disabled
        });
        var a = c.findAll(function(d) {
            return d.hasAttribute("tabIndex") && d.tabIndex >= 0
        }).sortBy(function(d) {
            return d.tabIndex
        }).first();
        return a ? a: c.find(function(d) {
            return /^(?:input|select|textarea)$/i.test(d.tagName)
        })
    },
    focusFirstElement: function(b) {
        b = $(b);
        var a = b.findFirstElement();
        if (a) {
            a.activate()
        }
        return b
    },
    request: function(b, a) {
        b = $(b),
        a = Object.clone(a || {});
        var d = a.parameters,
        c = b.readAttribute("action") || "";
        if (c.blank()) {
            c = window.location.href
        }
        a.parameters = b.serialize(true);
        if (d) {
            if (Object.isString(d)) {
                d = d.toQueryParams()
            }
            Object.extend(a.parameters, d)
        }
        if (b.hasAttribute("method") && !a.method) {
            a.method = b.method
        }
        return new Ajax.Request(c, a)
    }
};
Form.Element = {
    focus: function(a) {
        $(a).focus();
        return a
    },
    select: function(a) {
        $(a).select();
        return a
    }
};
Form.Element.Methods = {
    serialize: function(a) {
        a = $(a);
        if (!a.disabled && a.name) {
            var b = a.getValue();
            if (b != undefined) {
                var c = {};
                c[a.name] = b;
                return Object.toQueryString(c)
            }
        }
        return ""
    },
    getValue: function(a) {
        a = $(a);
        var b = a.tagName.toLowerCase();
        return Form.Element.Serializers[b](a)
    },
    setValue: function(a, b) {
        a = $(a);
        var c = a.tagName.toLowerCase();
        Form.Element.Serializers[c](a, b);
        return a
    },
    clear: function(a) {
        $(a).value = "";
        return a
    },
    present: function(a) {
        return $(a).value != ""
    },
    activate: function(a) {
        a = $(a);
        try {
            a.focus();
            if (a.select && (a.tagName.toLowerCase() != "input" || !(/^(?:button|reset|submit)$/i.test(a.type)))) {
                a.select()
            }
        } catch(b) {}
        return a
    },
    disable: function(a) {
        a = $(a);
        a.disabled = true;
        return a
    },
    enable: function(a) {
        a = $(a);
        a.disabled = false;
        return a
    }
};
var Field = Form.Element;
var $F = Form.Element.Methods.getValue;
Form.Element.Serializers = (function() {
    function b(h, j) {
        switch (h.type.toLowerCase()) {
        case "checkbox":
        case "radio":
            return f(h, j);
        default:
            return e(h, j)
        }
    }
    function f(h, j) {
        if (Object.isUndefined(j)) {
            return h.checked ? h.value: null
        } else {
            h.checked = !!j
        }
    }
    function e(h, j) {
        if (Object.isUndefined(j)) {
            return h.value
        } else {
            h.value = j
        }
    }
    function a(k, n) {
        if (Object.isUndefined(n)) {
            return (k.type === "select-one" ? c: d)(k)
        }
        var j,
        l,
        o = !Object.isArray(n);
        for (var h = 0, m = k.length; h < m; h++) {
            j = k.options[h];
            l = this.optionValue(j);
            if (o) {
                if (l == n) {
                    j.selected = true;
                    return
                }
            } else {
                j.selected = n.include(l)
            }
        }
    }
    function c(j) {
        var h = j.selectedIndex;
        return h >= 0 ? g(j.options[h]) : null
    }
    function d(l) {
        var h,
        m = l.length;
        if (!m) {
            return null
        }
        for (var k = 0, h = []; k < m; k++) {
            var j = l.options[k];
            if (j.selected) {
                h.push(g(j))
            }
        }
        return h
    }
    function g(h) {
        return Element.hasAttribute(h, "value") ? h.value: h.text
    }
    return {
        input: b,
        inputSelector: f,
        textarea: e,
        select: a,
        selectOne: c,
        selectMany: d,
        optionValue: g,
        button: e
    }
})();
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
    initialize: function($super, a, b, c) {
        $super(c, b);
        this.element = $(a);
        this.lastValue = this.getValue()
    },
    execute: function() {
        var a = this.getValue();
        if (Object.isString(this.lastValue) && Object.isString(a) ? this.lastValue != a: String(this.lastValue) != String(a)) {
            this.callback(this.element, a);
            this.lastValue = a
        }
    }
});
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
    getValue: function() {
        return Form.Element.getValue(this.element)
    }
});
Form.Observer = Class.create(Abstract.TimedObserver, {
    getValue: function() {
        return Form.serialize(this.element)
    }
});
Abstract.EventObserver = Class.create({
    initialize: function(a, b) {
        this.element = $(a);
        this.callback = b;
        this.lastValue = this.getValue();
        if (this.element.tagName.toLowerCase() == "form") {
            this.registerFormCallbacks()
        } else {
            this.registerCallback(this.element)
        }
    },
    onElementEvent: function() {
        var a = this.getValue();
        if (this.lastValue != a) {
            this.callback(this.element, a);
            this.lastValue = a
        }
    },
    registerFormCallbacks: function() {
        Form.getElements(this.element).each(this.registerCallback, this)
    },
    registerCallback: function(a) {
        if (a.type) {
            switch (a.type.toLowerCase()) {
            case "checkbox":
            case "radio":
                Event.observe(a, "click", this.onElementEvent.bind(this));
                break;
            default:
                Event.observe(a, "change", this.onElementEvent.bind(this));
                break
            }
        }
    }
});
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
    getValue: function() {
        return Form.Element.getValue(this.element)
    }
});
Form.EventObserver = Class.create(Abstract.EventObserver, {
    getValue: function() {
        return Form.serialize(this.element)
    }
}); (function() {
    var D = {
        KEY_BACKSPACE: 8,
        KEY_TAB: 9,
        KEY_RETURN: 13,
        KEY_ESC: 27,
        KEY_LEFT: 37,
        KEY_UP: 38,
        KEY_RIGHT: 39,
        KEY_DOWN: 40,
        KEY_DELETE: 46,
        KEY_HOME: 36,
        KEY_END: 35,
        KEY_PAGEUP: 33,
        KEY_PAGEDOWN: 34,
        KEY_INSERT: 45,
        cache: {}
    };
    var f = document.documentElement;
    var E = "onmouseenter" in f && "onmouseleave" in f;
    var a = function(F) {
        return false
    };
    if (window.attachEvent) {
        if (window.addEventListener) {
            a = function(F) {
                return ! (F instanceof window.Event)
            }
        } else {
            a = function(F) {
                return true
            }
        }
    }
    var s;
    function B(G, F) {
        return G.which ? (G.which === F + 1) : (G.button === F)
    }
    var p = {
        0: 1,
        1: 4,
        2: 2
    };
    function z(G, F) {
        return G.button === p[F]
    }
    function C(G, F) {
        switch (F) {
        case 0:
            return G.which == 1 && !G.metaKey;
        case 1:
            return G.which == 2 || (G.which == 1 && G.metaKey);
        case 2:
            return G.which == 3;
        default:
            return false
        }
    }
    if (window.attachEvent) {
        if (!window.addEventListener) {
            s = z
        } else {
            s = function(G, F) {
                return a(G) ? z(G, F) : B(G, F)
            }
        }
    } else {
        if (Prototype.Browser.WebKit) {
            s = C
        } else {
            s = B
        }
    }
    function w(F) {
        return s(F, 0)
    }
    function u(F) {
        return s(F, 1)
    }
    function o(F) {
        return s(F, 2)
    }
    function d(H) {
        H = D.extend(H);
        var G = H.target,
        F = H.type,
        I = H.currentTarget;
        if (I && I.tagName) {
            if (F === "load" || F === "error" || (F === "click" && I.tagName.toLowerCase() === "input" && I.type === "radio")) {
                G = I
            }
        }
        if (G.nodeType == Node.TEXT_NODE) {
            G = G.parentNode
        }
        return Element.extend(G)
    }
    function q(G, H) {
        var F = D.element(G);
        if (!H) {
            return F
        }
        while (F) {
            if (Object.isElement(F) && Prototype.Selector.match(F, H)) {
                return Element.extend(F)
            }
            F = F.parentNode
        }
    }
    function t(F) {
        return {
            x: c(F),
            y: b(F)
        }
    }
    function c(H) {
        var G = document.documentElement,
        F = document.body || {
            scrollLeft: 0
        };
        return H.pageX || (H.clientX + (G.scrollLeft || F.scrollLeft) - (G.clientLeft || 0))
    }
    function b(H) {
        var G = document.documentElement,
        F = document.body || {
            scrollTop: 0
        };
        return H.pageY || (H.clientY + (G.scrollTop || F.scrollTop) - (G.clientTop || 0))
    }
    function r(F) {
        D.extend(F);
        F.preventDefault();
        F.stopPropagation();
        F.stopped = true
    }
    D.Methods = {
        isLeftClick: w,
        isMiddleClick: u,
        isRightClick: o,
        element: d,
        findElement: q,
        pointer: t,
        pointerX: c,
        pointerY: b,
        stop: r
    };
    var y = Object.keys(D.Methods).inject({},
    function(F, G) {
        F[G] = D.Methods[G].methodize();
        return F
    });
    if (window.attachEvent) {
        function j(G) {
            var F;
            switch (G.type) {
            case "mouseover":
            case "mouseenter":
                F = G.fromElement;
                break;
            case "mouseout":
            case "mouseleave":
                F = G.toElement;
                break;
            default:
                return null
            }
            return Element.extend(F)
        }
        var v = {
            stopPropagation: function() {
                this.cancelBubble = true
            },
            preventDefault: function() {
                this.returnValue = false
            },
            inspect: function() {
                return "[object Event]"
            }
        };
        D.extend = function(G, F) {
            if (!G) {
                return false
            }
            if (!a(G)) {
                return G
            }
            if (G._extendedByPrototype) {
                return G
            }
            G._extendedByPrototype = Prototype.emptyFunction;
            var H = D.pointer(G);
            Object.extend(G, {
                target: G.srcElement || F,
                relatedTarget: j(G),
                pageX: H.x,
                pageY: H.y
            });
            Object.extend(G, y);
            Object.extend(G, v);
            return G
        }
    } else {
        D.extend = Prototype.K
    }
    if (window.addEventListener) {
        D.prototype = window.Event.prototype || document.createEvent("HTMLEvents").__proto__;
        Object.extend(D.prototype, y)
    }
    function n(J, I, K) {
        var H = Element.retrieve(J, "prototype_event_registry");
        if (Object.isUndefined(H)) {
            e.push(J);
            H = Element.retrieve(J, "prototype_event_registry", $H())
        }
        if (H === undefined) return false;
        var F = H.get(I);
        if (Object.isUndefined(F)) {
            F = [];
            H.set(I, F)
        }
        if (F.pluck("handler").include(K)) {
            return false;
        }
        var G;
        if (I.include(":")) {
            G = function(L) {
                if (Object.isUndefined(L.eventName)) {
                    return false
                }
                if (L.eventName !== I) {
                    return false
                }
                D.extend(L, J);
                K.call(J, L)
            }
        } else {
            if (!E && (I === "mouseenter" || I === "mouseleave")) {
                if (I === "mouseenter" || I === "mouseleave") {
                    G = function(M) {
                        D.extend(M, J);
                        var L = M.relatedTarget;
                        while (L && L !== J) {
                            try {
                                L = L.parentNode
                            } catch(N) {
                                L = J
                            }
                        }
                        if (L === J) {
                            return
                        }
                        K.call(J, M)
                    }
                }
            } else {
                G = function(L) {
                    D.extend(L, J);
                    K.call(J, L)
                }
            }
        }
        G.handler = K;
        F.push(G);
        return G
    }
    function h() {
        for (var F = 0, G = e.length; F < G; F++) {
            D.stopObserving(e[F]);
            e[F] = null
        }
    }
    var e = [];
    if (Prototype.Browser.IE) {
        window.attachEvent("onunload", h)
    }
    if (Prototype.Browser.WebKit) {
        window.addEventListener("unload", Prototype.emptyFunction, false)
    }
    var m = Prototype.K,
    g = {
        mouseenter: "mouseover",
        mouseleave: "mouseout"
    };
    if (!E) {
        m = function(F) {
            return (g[F] || F)
        }
    }
    function x(I, H, J) {
        I = $(I);
        var G = n(I, H, J);
        if (!G) {
            return I
        }
        if (H.include(":")) {
            if (I.addEventListener) {
                I.addEventListener("dataavailable", G, false)
            } else {
                I.attachEvent("ondataavailable", G);
                I.attachEvent("onlosecapture", G)
            }
        } else {
            var F = m(H);
            if (I.addEventListener) {
                I.addEventListener(F, G, false)
            } else {
                I.attachEvent("on" + F, G)
            }
        }
        return I
    }
    function l(L, I, M) {
        L = $(L);
        var H = Element.retrieve(L, "prototype_event_registry");
        if (!H) {
            return L
        }
        if (!I) {
            H.each(function(O) {
                var N = O.key;
                l(L, N)
            });
            return L
        }
        var J = H.get(I);
        if (!J) {
            return L
        }
        if (!M) {
            J.each(function(N) {
                l(L, I, N.handler)
            });
            return L
        }
        var K = J.length,
        G;
        while (K--) {
            if (J[K].handler === M) {
                G = J[K];
                break
            }
        }
        if (!G) {
            return L
        }
        if (I.include(":")) {
            if (L.removeEventListener) {
                L.removeEventListener("dataavailable", G, false)
            } else {
                L.detachEvent("ondataavailable", G);
                L.detachEvent("onlosecapture", G)
            }
        } else {
            var F = m(I);
            if (L.removeEventListener) {
                L.removeEventListener(F, G, false)
            } else {
                L.detachEvent("on" + F, G)
            }
        }
        H.set(I, J.without(G));
        return L
    }
    function A(I, H, G, F) {
        I = $(I);
        if (Object.isUndefined(F)) {
            F = true
        }
        if (I == document && document.createEvent && !I.dispatchEvent) {
            I = document.documentElement
        }
        var J;
        if (document.createEvent) {
            J = document.createEvent("HTMLEvents");
            J.initEvent("dataavailable", F, true)
        } else {
            J = document.createEventObject();
            J.eventType = F ? "ondataavailable": "onlosecapture"
        }
        J.eventName = H;
        J.memo = G || {};
        if (document.createEvent) {
            I.dispatchEvent(J)
        } else {
            I.fireEvent(J.eventType, J)
        }
        return D.extend(J)
    }
    D.Handler = Class.create({
        initialize: function(H, G, F, I) {
            this.element = $(H);
            this.eventName = G;
            this.selector = F;
            this.callback = I;
            this.handler = this.handleEvent.bind(this)
        },
        start: function() {
            D.observe(this.element, this.eventName, this.handler);
            return this
        },
        stop: function() {
            D.stopObserving(this.element, this.eventName, this.handler);
            return this
        },
        handleEvent: function(G) {
            var F = D.findElement(G, this.selector);
            if (F) {
                this.callback.call(this.element, G, F)
            }
        }
    });
    function k(H, G, F, I) {
        H = $(H);
        if (Object.isFunction(F) && Object.isUndefined(I)) {
            I = F,
            F = null
        }
        return new D.Handler(H, G, F, I).start()
    }
    Object.extend(D, D.Methods);
    Object.extend(D, {
        fire: A,
        observe: x,
        stopObserving: l,
        on: k
    });
    Element.addMethods({
        fire: A,
        observe: x,
        stopObserving: l,
        on: k
    });
    Object.extend(document, {
        fire: A.methodize(),
        observe: x.methodize(),
        stopObserving: l.methodize(),
        on: k.methodize(),
        loaded: false
    });
    if (window.Event) {
        Object.extend(window.Event, D)
    } else {
        window.Event = D
    }
})(); (function() {
    var d;
    function a() {
        if (document.loaded) {
            return
        }
        if (d) {
            window.clearTimeout(d)
        }
        document.loaded = true;
        document.fire("dom:loaded")
    }
    function c() {
        if (document.readyState === "complete") {
            document.stopObserving("readystatechange", c);
            a()
        }
    }
    function b() {
        try {
            document.documentElement.doScroll("left")
        } catch(f) {
            d = b.defer();
            return
        }
        a()
    }
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", a, false)
    } else {
        document.observe("readystatechange", c);
        if (window == top) {
            d = b.defer()
        }
    }
    Event.observe(window, "load", a)
})();
Element.addMethods();
Hash.toQueryString = Object.toQueryString;
var Toggle = {
    display: Element.toggle
};
Element.Methods.childOf = Element.Methods.descendantOf;
var Insertion = {
    Before: function(a, b) {
        return Element.insert(a, {
            before: b
        })
    },
    Top: function(a, b) {
        return Element.insert(a, {
            top: b
        })
    },
    Bottom: function(a, b) {
        return Element.insert(a, {
            bottom: b
        })
    },
    After: function(a, b) {
        return Element.insert(a, {
            after: b
        })
    }
};
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
var Position = {
    includeScrollOffsets: false,
    prepare: function() {
        this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
        this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    },
    within: function(b, a, c) {
        if (this.includeScrollOffsets) {
            return this.withinIncludingScrolloffsets(b, a, c)
        }
        this.xcomp = a;
        this.ycomp = c;
        this.offset = Element.cumulativeOffset(b);
        return (c >= this.offset[1] && c < this.offset[1] + b.offsetHeight && a >= this.offset[0] && a < this.offset[0] + b.offsetWidth)
    },
    withinIncludingScrolloffsets: function(b, a, d) {
        var c = Element.cumulativeScrollOffset(b);
        this.xcomp = a + c[0] - this.deltaX;
        this.ycomp = d + c[1] - this.deltaY;
        this.offset = Element.cumulativeOffset(b);
        return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + b.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + b.offsetWidth)
    },
    overlap: function(b, a) {
        if (!b) {
            return 0
        }
        if (b == "vertical") {
            return ((this.offset[1] + a.offsetHeight) - this.ycomp) / a.offsetHeight
        }
        if (b == "horizontal") {
            return ((this.offset[0] + a.offsetWidth) - this.xcomp) / a.offsetWidth
        }
    },
    cumulativeOffset: Element.Methods.cumulativeOffset,
    positionedOffset: Element.Methods.positionedOffset,
    absolutize: function(a) {
        Position.prepare();
        return Element.absolutize(a)
    },
    relativize: function(a) {
        Position.prepare();
        return Element.relativize(a)
    },
    realOffset: Element.Methods.cumulativeScrollOffset,
    offsetParent: Element.Methods.getOffsetParent,
    page: Element.Methods.viewportOffset,
    clone: function(b, c, a) {
        a = a || {};
        return Element.clonePosition(c, b, a)
    }
};
if (!document.getElementsByClassName) {
    document.getElementsByClassName = function(b) {
        function a(c) {
            return c.blank() ? null: "[contains(concat(' ', @class, ' '), ' " + c + " ')]"
        }
        b.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
        function(c, e) {
            e = e.toString().strip();
            var d = /\s/.test(e) ? $w(e).map(a).join("") : a(e);
            return d ? document._getElementsByXPath(".//*" + d, c) : []
        }: function(e, f) {
            f = f.toString().strip();
            var g = [],
            h = (/\s/.test(f) ? $w(f) : null);
            if (!h && !f) {
                return g
            }
            var c = $(e).getElementsByTagName("*");
            f = " " + f + " ";
            for (var d = 0, k, j; k = c[d]; d++) {
                if (k.className && (j = " " + k.className + " ") && (j.include(f) || (h && h.all(function(l) {
                    return ! l.toString().blank() && j.include(" " + l + " ")
                })))) {
                    g.push(Element.extend(k))
                }
            }
            return g
        };
        return function(d, c) {
            return $(c || document.body).getElementsByClassName(d)
        }
    } (Element.Methods)
}
Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
    initialize: function(a) {
        this.element = $(a)
    },
    _each: function(a) {
        this.element.className.split(/\s+/).select(function(b) {
            return b.length > 0
        })._each(a)
    },
    set: function(a) {
        this.element.className = a
    },
    add: function(a) {
        if (this.include(a)) {
            return
        }
        this.set($A(this).concat(a).join(" "))
    },
    remove: function(a) {
        if (!this.include(a)) {
            return
        }
        this.set($A(this).without(a).join(" "))
    },
    toString: function() {
        return $A(this).join(" ")
    }
};
Object.extend(Element.ClassNames.prototype, Enumerable); (function() {
    window.Selector = Class.create({
        initialize: function(a) {
            this.expression = a.strip()
        },
        findElements: function(a) {
            return Prototype.Selector.select(this.expression, a)
        },
        match: function(a) {
            return Prototype.Selector.match(a, this.expression)
        },
        toString: function() {
            return this.expression
        },
        inspect: function() {
            return "#<Selector: " + this.expression + ">"
        }
    });
    Object.extend(Selector, {
        matchElements: function(f, g) {
            var a = Prototype.Selector.match,
            d = [];
            for (var c = 0, e = f.length; c < e; c++) {
                var b = f[c];
                if (a(b, g)) {
                    d.push(Element.extend(b))
                }
            }
            return d
        },
        findElement: function(f, g, b) {
            b = b || 0;
            var a = 0,
            d;
            for (var c = 0, e = f.length; c < e; c++) {
                d = f[c];
                if (Prototype.Selector.match(d, g) && b === a++) {
                    return Element.extend(d)
                }
            }
        },
        findChildElements: function(b, c) {
            var a = c.toArray().join(", ");
            return Prototype.Selector.select(a, b || document)
        }
    })
})();
var Scriptaculous = {
    Version: "1.9.0",
    REQUIRED_PROTOTYPE: "1.6.0.3",
    load: function() {
        function a(b) {
            var c = b.replace(/_.*|\./g, "");
            c = parseInt(c + "0".times(4 - c.length));
            return b.indexOf("_") > -1 ? c - 1: c
        }
        if ((typeof Prototype == "undefined") || (typeof Element == "undefined") || (typeof Element.Methods == "undefined") || (a(Prototype.Version) < a(Scriptaculous.REQUIRED_PROTOTYPE))) {
            throw ("script.aculo.us requires the Prototype JavaScript framework >= " + Scriptaculous.REQUIRED_PROTOTYPE)
        }
    }
};
Scriptaculous.load();
var Builder = {
    NODEMAP: {
        AREA: "map",
        CAPTION: "table",
        COL: "table",
        COLGROUP: "table",
        LEGEND: "fieldset",
        OPTGROUP: "select",
        OPTION: "select",
        PARAM: "object",
        TBODY: "table",
        TD: "table",
        TFOOT: "table",
        TH: "table",
        THEAD: "table",
        TR: "table"
    },
    node: function(a) {
        a = a.toUpperCase();
        var g = this.NODEMAP[a] || "div";
        var b = document.createElement(g);
        try {
            b.innerHTML = "<" + a + "></" + a + ">"
        } catch(f) {}
        var d = b.firstChild || null;
        if (d && (d.tagName.toUpperCase() != a)) {
            d = d.getElementsByTagName(a)[0]
        }
        if (!d) {
            d = document.createElement(a)
        }
        if (!d) {
            return
        }
        if (arguments[1]) {
            if (this._isStringOrNumber(arguments[1]) || (arguments[1] instanceof Array) || arguments[1].tagName) {
                this._children(d, arguments[1])
            } else {
                var c = this._attributes(arguments[1]);
                if (c.length) {
                    try {
                        b.innerHTML = "<" + a + " " + c + "></" + a + ">"
                    } catch(f) {}
                    d = b.firstChild || null;
                    if (!d) {
                        d = document.createElement(a);
                        for (attr in arguments[1]) {
                            d[attr == "class" ? "className": attr] = arguments[1][attr]
                        }
                    }
                    if (d.tagName.toUpperCase() != a) {
                        d = b.getElementsByTagName(a)[0]
                    }
                }
            }
        }
        if (arguments[2]) {
            this._children(d, arguments[2])
        }
        return $(d)
    },
    _text: function(a) {
        return document.createTextNode(a)
    },
    ATTR_MAP: {
        className: "class",
        htmlFor: "for"
    },
    _attributes: function(a) {
        var b = [];
        for (attribute in a) {
            b.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + '="' + a[attribute].toString().escapeHTML().gsub(/"/, "&quot;") + '"')
        }
        return b.join(" ")
    },
    _children: function(b, a) {
        if (a.tagName) {
            b.appendChild(a);
            return
        }
        if (typeof a == "object") {
            a.flatten().each(function(c) {
                if (typeof c == "object") {
                    b.appendChild(c)
                } else {
                    if (Builder._isStringOrNumber(c)) {
                        b.appendChild(Builder._text(c))
                    }
                }
            })
        } else {
            if (Builder._isStringOrNumber(a)) {
                b.appendChild(Builder._text(a))
            }
        }
    },
    _isStringOrNumber: function(a) {
        return (typeof a == "string" || typeof a == "number")
    },
    build: function(b) {
        var a = this.node("div");
        $(a).update(b.strip());
        return a.down()
    },
    dump: function(b) {
        if (typeof b != "object" && typeof b != "function") {
            b = window
        }
        var a = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
        a.each(function(c) {
            b[c] = function() {
                return Builder.node.apply(Builder, [c].concat($A(arguments)))
            }
        })
    }
};
String.prototype.parseColor = function() {
    var a = "#";
    if (this.slice(0, 4) == "rgb(") {
        var c = this.slice(4, this.length - 1).split(",");
        var b = 0;
        do {
            a += parseInt(c[b]).toColorPart()
        }
        while (++b < 3)
    } else {
        if (this.slice(0, 1) == "#") {
            if (this.length == 4) {
                for (var b = 1; b < 4; b++) {
                    a += (this.charAt(b) + this.charAt(b)).toLowerCase()
                }
            }
            if (this.length == 7) {
                a = this.toLowerCase()
            }
        }
    }
    return (a.length == 7 ? a: (arguments[0] || this))
};
Element.collectTextNodes = function(a) {
    return $A($(a).childNodes).collect(function(b) {
        return (b.nodeType == 3 ? b.nodeValue: (b.hasChildNodes() ? Element.collectTextNodes(b) : ""))
    }).flatten().join("")
};
Element.collectTextNodesIgnoreClass = function(a, b) {
    return $A($(a).childNodes).collect(function(c) {
        return (c.nodeType == 3 ? c.nodeValue: ((c.hasChildNodes() && !Element.hasClassName(c, b)) ? Element.collectTextNodesIgnoreClass(c, b) : ""))
    }).flatten().join("")
};
Element.setContentZoom = function(a, b) {
    a = $(a);
    a.setStyle({
        fontSize: (b / 100) + "em"
    });
    if (Prototype.Browser.WebKit) {
        window.scrollBy(0, 0)
    }
    return a
};
Element.getInlineOpacity = function(a) {
    return $(a).style.opacity || ""
};
Element.forceRerendering = function(a) {
    try {
        a = $(a);
        var c = document.createTextNode(" ");
        a.appendChild(c);
        a.removeChild(c)
    } catch(b) {}
};
var Effect = {
    _elementDoesNotExistError: {
        name: "ElementDoesNotExistError",
        message: "The specified DOM element does not exist, but is required for this effect to operate"
    },
    Transitions: {
        linear: Prototype.K,
        sinoidal: function(a) {
            return ( - Math.cos(a * Math.PI) / 2) + 0.5
        },
        reverse: function(a) {
            return 1 - a
        },
        flicker: function(a) {
            var a = (( - Math.cos(a * Math.PI) / 4) + 0.75) + Math.random() / 4;
            return a > 1 ? 1: a
        },
        wobble: function(a) {
            return ( - Math.cos(a * Math.PI * (9 * a)) / 2) + 0.5
        },
        pulse: function(b, a) {
            return ( - Math.cos((b * ((a || 5) - 0.5) * 2) * Math.PI) / 2) + 0.5
        },
        spring: function(a) {
            return 1 - (Math.cos(a * 4.5 * Math.PI) * Math.exp( - a * 6))
        },
        none: function(a) {
            return 0
        },
        full: function(a) {
            return 1
        }
    },
    DefaultOptions: {
        duration: 1,
        fps: 100,
        sync: false,
        from: 0,
        to: 1,
        delay: 0,
        queue: "parallel"
    },
    tagifyText: function(a) {
        var b = "position:relative";
        if (Prototype.Browser.IE) {
            b += ";zoom:1"
        }
        a = $(a);
        $A(a.childNodes).each(function(c) {
            if (c.nodeType == 3) {
                c.nodeValue.toArray().each(function(d) {
                    a.insertBefore(new Element("span", {
                        style: b
                    }).update(d == " " ? String.fromCharCode(160) : d), c)
                });
                Element.remove(c)
            }
        })
    },
    multiple: function(b, c) {
        var e;
        if (((typeof b == "object") || Object.isFunction(b)) && (b.length)) {
            e = b
        } else {
            e = $(b).childNodes
        }
        var a = Object.extend({
            speed: 0.1,
            delay: 0
        },
        arguments[2] || {});
        var d = a.delay;
        $A(e).each(function(g, f) {
            new c(g, Object.extend(a, {
                delay: f * a.speed + d
            }))
        })
    },
    PAIRS: {
        slide: ["SlideDown", "SlideUp"],
        blind: ["BlindDown", "BlindUp"],
        appear: ["Appear", "Fade"]
    },
    toggle: function(b, c, a) {
        b = $(b);
        c = (c || "appear").toLowerCase();
        return Effect[Effect.PAIRS[c][b.visible() ? 1: 0]](b, Object.extend({
            queue: {
                position: "end",
                scope: (b.id || "global"),
                limit: 1
            }
        },
        a || {}))
    }
};
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
Effect.ScopedQueue = Class.create(Enumerable, {
    initialize: function() {
        this.effects = [];
        this.interval = null
    },
    _each: function(a) {
        this.effects._each(a)
    },
    add: function(b) {
        var c = new Date().getTime();
        var a = Object.isString(b.options.queue) ? b.options.queue: b.options.queue.position;
        switch (a) {
        case "front":
            this.effects.findAll(function(d) {
                return d.state == "idle"
            }).each(function(d) {
                d.startOn += b.finishOn;
                d.finishOn += b.finishOn
            });
            break;
        case "with-last":
            c = this.effects.pluck("startOn").max() || c;
            break;
        case "end":
            c = this.effects.pluck("finishOn").max() || c;
            break
        }
        b.startOn += c;
        b.finishOn += c;
        if (!b.options.queue.limit || (this.effects.length < b.options.queue.limit)) {
            this.effects.push(b)
        }
        if (!this.interval) {
            this.interval = setInterval(this.loop.bind(this), 15)
        }
    },
    remove: function(a) {
        this.effects = this.effects.reject(function(b) {
            return b == a
        });
        if (this.effects.length == 0) {
            clearInterval(this.interval);
            this.interval = null
        }
    },
    loop: function() {
        var c = new Date().getTime();
        for (var b = 0, a = this.effects.length; b < a; b++) {
            this.effects[b] && this.effects[b].loop(c)
        }
    }
});
Effect.Queues = {
    instances: $H(),
    get: function(a) {
        if (!Object.isString(a)) {
            return a
        }
        return this.instances.get(a) || this.instances.set(a, new Effect.ScopedQueue())
    }
};
Effect.Queue = Effect.Queues.get("global");
Effect.Base = Class.create({
    position: null,
    start: function(a) {
        if (a && a.transition === false) {
            a.transition = Effect.Transitions.linear
        }
        this.options = Object.extend(Object.extend({},
        Effect.DefaultOptions), a || {});
        this.currentFrame = 0;
        this.state = "idle";
        this.startOn = this.options.delay * 1000;
        this.finishOn = this.startOn + (this.options.duration * 1000);
        this.fromToDelta = this.options.to - this.options.from;
        this.totalTime = this.finishOn - this.startOn;
        this.totalFrames = this.options.fps * this.options.duration;
        this.render = (function() {
            function b(d, c) {
                if (d.options[c + "Internal"]) {
                    d.options[c + "Internal"](d)
                }
                if (d.options[c]) {
                    d.options[c](d)
                }
            }
            return function(c) {
                if (this.state === "idle") {
                    this.state = "running";
                    b(this, "beforeSetup");
                    if (this.setup) {
                        this.setup()
                    }
                    b(this, "afterSetup")
                }
                if (this.state === "running") {
                    c = (this.options.transition(c) * this.fromToDelta) + this.options.from;
                    this.position = c;
                    b(this, "beforeUpdate");
                    if (this.update) {
                        this.update(c)
                    }
                    b(this, "afterUpdate")
                }
            }
        })();
        this.event("beforeStart");
        if (!this.options.sync) {
            Effect.Queues.get(Object.isString(this.options.queue) ? "global": this.options.queue.scope).add(this)
        }
    },
    loop: function(c) {
        if (c >= this.startOn) {
            if (c >= this.finishOn) {
                this.render(1);
                this.cancel();
                this.event("beforeFinish");
                if (this.finish) {
                    this.finish()
                }
                this.event("afterFinish");
                return
            }
            var b = (c - this.startOn) / this.totalTime,
            a = (b * this.totalFrames).round();
            if (a > this.currentFrame) {
                this.render(b);
                this.currentFrame = a
            }
        }
    },
    cancel: function() {
        if (!this.options.sync) {
            Effect.Queues.get(Object.isString(this.options.queue) ? "global": this.options.queue.scope).remove(this)
        }
        this.state = "finished"
    },
    event: function(a) {
        if (this.options[a + "Internal"]) {
            this.options[a + "Internal"](this)
        }
        if (this.options[a]) {
            this.options[a](this)
        }
    },
    inspect: function() {
        var a = $H();
        for (property in this) {
            if (!Object.isFunction(this[property])) {
                a.set(property, this[property])
            }
        }
        return "#<Effect:" + a.inspect() + ",options:" + $H(this.options).inspect() + ">"
    }
});
Effect.Parallel = Class.create(Effect.Base, {
    initialize: function(a) {
        this.effects = a || [];
        this.start(arguments[1])
    },
    update: function(a) {
        this.effects.invoke("render", a)
    },
    finish: function(a) {
        this.effects.each(function(b) {
            b.render(1);
            b.cancel();
            b.event("beforeFinish");
            if (b.finish) {
                b.finish(a)
            }
            b.event("afterFinish")
        })
    }
});
Effect.Tween = Class.create(Effect.Base, {
    initialize: function(c, f, e) {
        c = Object.isString(c) ? $(c) : c;
        var b = $A(arguments),
        d = b.last(),
        a = b.length == 5 ? b[3] : null;
        this.method = Object.isFunction(d) ? d.bind(c) : Object.isFunction(c[d]) ? c[d].bind(c) : function(g) {
            c[d] = g
        };
        this.start(Object.extend({
            from: f,
            to: e
        },
        a || {}))
    },
    update: function(a) {
        this.method(a)
    }
});
Effect.Event = Class.create(Effect.Base, {
    initialize: function() {
        this.start(Object.extend({
            duration: 0
        },
        arguments[0] || {}))
    },
    update: Prototype.emptyFunction
});
Effect.Opacity = Class.create(Effect.Base, {
    initialize: function(b) {
        this.element = $(b);
        if (!this.element) {
            throw (Effect._elementDoesNotExistError)
        }
        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
            this.element.setStyle({
                zoom: 1
            })
        }
        var a = Object.extend({
            from: this.element.getOpacity() || 0,
            to: 1
        },
        arguments[1] || {});
        this.start(a)
    },
    update: function(a) {
        this.element.setOpacity(a)
    }
});
Effect.Move = Class.create(Effect.Base, {
    initialize: function(b) {
        this.element = $(b);
        if (!this.element) {
            throw (Effect._elementDoesNotExistError)
        }
        var a = Object.extend({
            x: 0,
            y: 0,
            mode: "relative"
        },
        arguments[1] || {});
        this.start(a)
    },
    setup: function() {
        this.element.makePositioned();
        this.originalLeft = parseFloat(this.element.getStyle("left") || "0");
        this.originalTop = parseFloat(this.element.getStyle("top") || "0");
        if (this.options.mode == "absolute") {
            this.options.x = this.options.x - this.originalLeft;
            this.options.y = this.options.y - this.originalTop
        }
    },
    update: function(a) {
        this.element.setStyle({
            left: (this.options.x * a + this.originalLeft).round() + "px",
            top: (this.options.y * a + this.originalTop).round() + "px"
        })
    }
});
Effect.MoveBy = function(b, a, c) {
    return new Effect.Move(b, Object.extend({
        x: c,
        y: a
    },
    arguments[3] || {}))
};
Effect.Scale = Class.create(Effect.Base, {
    initialize: function(b, c) {
        this.element = $(b);
        if (!this.element) {
            throw (Effect._elementDoesNotExistError)
        }
        var a = Object.extend({
            scaleX: true,
            scaleY: true,
            scaleContent: true,
            scaleFromCenter: false,
            scaleMode: "box",
            scaleFrom: 100,
            scaleTo: c
        },
        arguments[2] || {});
        this.start(a)
    },
    setup: function() {
        this.restoreAfterFinish = this.options.restoreAfterFinish || false;
        this.elementPositioning = this.element.getStyle("position");
        this.originalStyle = {}; ["top", "left", "width", "height", "fontSize"].each(function(b) {
            this.originalStyle[b] = this.element.style[b]
        }.bind(this));
        this.originalTop = this.element.offsetTop;
        this.originalLeft = this.element.offsetLeft;
        var a = this.element.getStyle("font-size") || "100%"; ["em", "px", "%", "pt"].each(function(b) {
            if (a.indexOf(b) > 0) {
                this.fontSize = parseFloat(a);
                this.fontSizeType = b
            }
        }.bind(this));
        this.factor = (this.options.scaleTo - this.options.scaleFrom) / 100;
        this.dims = null;
        if (this.options.scaleMode == "box") {
            this.dims = [this.element.offsetHeight, this.element.offsetWidth]
        }
        if (/^content/.test(this.options.scaleMode)) {
            this.dims = [this.element.scrollHeight, this.element.scrollWidth]
        }
        if (!this.dims) {
            this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth]
        }
    },
    update: function(a) {
        var b = (this.options.scaleFrom / 100) + (this.factor * a);
        if (this.options.scaleContent && this.fontSize) {
            this.element.setStyle({
                fontSize: this.fontSize * b + this.fontSizeType
            })
        }
        this.setDimensions(this.dims[0] * b, this.dims[1] * b)
    },
    finish: function(a) {
        if (this.restoreAfterFinish) {
            this.element.setStyle(this.originalStyle)
        }
    },
    setDimensions: function(a, e) {
        var f = {};
        if (this.options.scaleX) {
            f.width = e.round() + "px"
        }
        if (this.options.scaleY) {
            f.height = a.round() + "px"
        }
        if (this.options.scaleFromCenter) {
            var c = (a - this.dims[0]) / 2;
            var b = (e - this.dims[1]) / 2;
            if (this.elementPositioning == "absolute") {
                if (this.options.scaleY) {
                    f.top = this.originalTop - c + "px"
                }
                if (this.options.scaleX) {
                    f.left = this.originalLeft - b + "px"
                }
            } else {
                if (this.options.scaleY) {
                    f.top = -c + "px"
                }
                if (this.options.scaleX) {
                    f.left = -b + "px"
                }
            }
        }
        this.element.setStyle(f)
    }
});
Effect.Highlight = Class.create(Effect.Base, {
    initialize: function(b) {
        this.element = $(b);
        if (!this.element) {
            throw (Effect._elementDoesNotExistError)
        }
        var a = Object.extend({
            startcolor: "#ffff99"
        },
        arguments[1] || {});
        this.start(a)
    },
    setup: function() {
        if (this.element.getStyle("display") == "none") {
            this.cancel();
            return
        }
        this.oldStyle = {};
        if (!this.options.keepBackgroundImage) {
            this.oldStyle.backgroundImage = this.element.getStyle("background-image");
            this.element.setStyle({
                backgroundImage: "none"
            })
        }
        if (!this.options.endcolor) {
            this.options.endcolor = this.element.getStyle("background-color").parseColor("#ffffff")
        }
        if (!this.options.restorecolor) {
            this.options.restorecolor = this.element.getStyle("background-color")
        }
        this._base = $R(0, 2).map(function(a) {
            return parseInt(this.options.startcolor.slice(a * 2 + 1, a * 2 + 3), 16)
        }.bind(this));
        this._delta = $R(0, 2).map(function(a) {
            return parseInt(this.options.endcolor.slice(a * 2 + 1, a * 2 + 3), 16) - this._base[a]
        }.bind(this))
    },
    update: function(a) {
        this.element.setStyle({
            backgroundColor: $R(0, 2).inject("#",
            function(b, c, d) {
                return b + ((this._base[d] + (this._delta[d] * a)).round().toColorPart())
            }.bind(this))
        })
    },
    finish: function() {
        this.element.setStyle(Object.extend(this.oldStyle, {
            backgroundColor: this.options.restorecolor
        }))
    }
});
Effect.ScrollTo = function(c) {
    var b = arguments[1] || {},
    a = document.viewport.getScrollOffsets(),
    d = $(c).cumulativeOffset();
    if (b.offset) {
        d[1] += b.offset
    }
    return new Effect.Tween(null, a.top, d[1], b,
    function(e) {
        scrollTo(a.left, e.round())
    })
};
Effect.Fade = function(c) {
    c = $(c);
    var a = c.getInlineOpacity();
    var b = Object.extend({
        from: c.getOpacity() || 1,
        to: 0,
        afterFinishInternal: function(d) {
            if (d.options.to != 0) {
                return
            }
            d.element.hide().setStyle({
                opacity: a
            })
        }
    },
    arguments[1] || {});
    return new Effect.Opacity(c, b)
};
Effect.Appear = function(b) {
    b = $(b);
    var a = Object.extend({
        from: (b.getStyle("display") == "none" ? 0: b.getOpacity() || 0),
        to: 1,
        afterFinishInternal: function(c) {
            c.element.forceRerendering()
        },
        beforeSetup: function(c) {
            c.element.setOpacity(c.options.from).show()
        }
    },
    arguments[1] || {});
    return new Effect.Opacity(b, a)
};
Effect.Puff = function(b) {
    b = $(b);
    var a = {
        opacity: b.getInlineOpacity(),
        position: b.getStyle("position"),
        top: b.style.top,
        left: b.style.left,
        width: b.style.width,
        height: b.style.height
    };
    return new Effect.Parallel([new Effect.Scale(b, 200, {
        sync: true,
        scaleFromCenter: true,
        scaleContent: true,
        restoreAfterFinish: true
    }), new Effect.Opacity(b, {
        sync: true,
        to: 0
    })], Object.extend({
        duration: 1,
        beforeSetupInternal: function(c) {
            Position.absolutize(c.effects[0].element)
        },
        afterFinishInternal: function(c) {
            c.effects[0].element.hide().setStyle(a)
        }
    },
    arguments[1] || {}))
};
Effect.BlindUp = function(a) {
    a = $(a);
    a.makeClipping();
    return new Effect.Scale(a, 0, Object.extend({
        scaleContent: false,
        scaleX: false,
        restoreAfterFinish: true,
        afterFinishInternal: function(b) {
            b.element.hide().undoClipping()
        }
    },
    arguments[1] || {}))
};
Effect.BlindDown = function(b) {
    b = $(b);
    var a = b.getDimensions();
    return new Effect.Scale(b, 100, Object.extend({
        scaleContent: false,
        scaleX: false,
        scaleFrom: 0,
        scaleMode: {
            originalHeight: a.height,
            originalWidth: a.width
        },
        restoreAfterFinish: true,
        afterSetup: function(c) {
            c.element.makeClipping().setStyle({
                height: "0px"
            }).show()
        },
        afterFinishInternal: function(c) {
            c.element.undoClipping()
        }
    },
    arguments[1] || {}))
};
Effect.SwitchOff = function(b) {
    b = $(b);
    var a = b.getInlineOpacity();
    return new Effect.Appear(b, Object.extend({
        duration: 0.4,
        from: 0,
        transition: Effect.Transitions.flicker,
        afterFinishInternal: function(c) {
            new Effect.Scale(c.element, 1, {
                duration: 0.3,
                scaleFromCenter: true,
                scaleX: false,
                scaleContent: false,
                restoreAfterFinish: true,
                beforeSetup: function(d) {
                    d.element.makePositioned().makeClipping()
                },
                afterFinishInternal: function(d) {
                    d.element.hide().undoClipping().undoPositioned().setStyle({
                        opacity: a
                    })
                }
            })
        }
    },
    arguments[1] || {}))
};
Effect.DropOut = function(b) {
    b = $(b);
    var a = {
        top: b.getStyle("top"),
        left: b.getStyle("left"),
        opacity: b.getInlineOpacity()
    };
    return new Effect.Parallel([new Effect.Move(b, {
        x: 0,
        y: 100,
        sync: true
    }), new Effect.Opacity(b, {
        sync: true,
        to: 0
    })], Object.extend({
        duration: 0.5,
        beforeSetup: function(c) {
            c.effects[0].element.makePositioned()
        },
        afterFinishInternal: function(c) {
            c.effects[0].element.hide().undoPositioned().setStyle(a)
        }
    },
    arguments[1] || {}))
};
Effect.Shake = function(d) {
    d = $(d);
    var b = Object.extend({
        distance: 20,
        duration: 0.5
    },
    arguments[1] || {});
    var e = parseFloat(b.distance);
    var c = parseFloat(b.duration) / 10;
    var a = {
        top: d.getStyle("top"),
        left: d.getStyle("left")
    };
    return new Effect.Move(d, {
        x: e,
        y: 0,
        duration: c,
        afterFinishInternal: function(f) {
            new Effect.Move(f.element, {
                x: -e * 2,
                y: 0,
                duration: c * 2,
                afterFinishInternal: function(g) {
                    new Effect.Move(g.element, {
                        x: e * 2,
                        y: 0,
                        duration: c * 2,
                        afterFinishInternal: function(h) {
                            new Effect.Move(h.element, {
                                x: -e * 2,
                                y: 0,
                                duration: c * 2,
                                afterFinishInternal: function(j) {
                                    new Effect.Move(j.element, {
                                        x: e * 2,
                                        y: 0,
                                        duration: c * 2,
                                        afterFinishInternal: function(k) {
                                            new Effect.Move(k.element, {
                                                x: -e,
                                                y: 0,
                                                duration: c,
                                                afterFinishInternal: function(l) {
                                                    l.element.undoPositioned().setStyle(a)
                                                }
                                            })
                                        }
                                    })
                                }
                            })
                        }
                    })
                }
            })
        }
    })
};
Effect.SlideDown = function(c) {
    c = $(c).cleanWhitespace();
    var a = c.down().getStyle("bottom");
    var b = c.getDimensions();
    return new Effect.Scale(c, 100, Object.extend({
        scaleContent: false,
        scaleX: false,
        scaleFrom: window.opera ? 0: 1,
        scaleMode: {
            originalHeight: b.height,
            originalWidth: b.width
        },
        restoreAfterFinish: true,
        afterSetup: function(d) {
            d.element.makePositioned();
            d.element.down().makePositioned();
            if (window.opera) {
                d.element.setStyle({
                    top: ""
                })
            }
            d.element.makeClipping().setStyle({
                height: "0px"
            }).show()
        },
        afterUpdateInternal: function(d) {
            d.element.down().setStyle({
                bottom: (d.dims[0] - d.element.clientHeight) + "px"
            })
        },
        afterFinishInternal: function(d) {
            d.element.undoClipping().undoPositioned();
            d.element.down().undoPositioned().setStyle({
                bottom: a
            })
        }
    },
    arguments[1] || {}))
};
Effect.SlideUp = function(c) {
    c = $(c).cleanWhitespace();
    var a = c.down().getStyle("bottom");
    var b = c.getDimensions();
    return new Effect.Scale(c, window.opera ? 0: 1, Object.extend({
        scaleContent: false,
        scaleX: false,
        scaleMode: "box",
        scaleFrom: 100,
        scaleMode: {
            originalHeight: b.height,
            originalWidth: b.width
        },
        restoreAfterFinish: true,
        afterSetup: function(d) {
            d.element.makePositioned();
            d.element.down().makePositioned();
            if (window.opera) {
                d.element.setStyle({
                    top: ""
                })
            }
            d.element.makeClipping().show()
        },
        afterUpdateInternal: function(d) {
            d.element.down().setStyle({
                bottom: (d.dims[0] - d.element.clientHeight) + "px"
            })
        },
        afterFinishInternal: function(d) {
            d.element.hide().undoClipping().undoPositioned();
            d.element.down().undoPositioned().setStyle({
                bottom: a
            })
        }
    },
    arguments[1] || {}))
};
Effect.Squish = function(a) {
    return new Effect.Scale(a, window.opera ? 1: 0, {
        restoreAfterFinish: true,
        beforeSetup: function(b) {
            b.element.makeClipping()
        },
        afterFinishInternal: function(b) {
            b.element.hide().undoClipping()
        }
    })
};
Effect.Grow = function(c) {
    c = $(c);
    var b = Object.extend({
        direction: "center",
        moveTransition: Effect.Transitions.sinoidal,
        scaleTransition: Effect.Transitions.sinoidal,
        opacityTransition: Effect.Transitions.full
    },
    arguments[1] || {});
    var a = {
        top: c.style.top,
        left: c.style.left,
        height: c.style.height,
        width: c.style.width,
        opacity: c.getInlineOpacity()
    };
    var g = c.getDimensions();
    var h,
    f;
    var e,
    d;
    switch (b.direction) {
    case "top-left":
        h = f = e = d = 0;
        break;
    case "top-right":
        h = g.width;
        f = d = 0;
        e = -g.width;
        break;
    case "bottom-left":
        h = e = 0;
        f = g.height;
        d = -g.height;
        break;
    case "bottom-right":
        h = g.width;
        f = g.height;
        e = -g.width;
        d = -g.height;
        break;
    case "center":
        h = g.width / 2;
        f = g.height / 2;
        e = -g.width / 2;
        d = -g.height / 2;
        break
    }
    return new Effect.Move(c, {
        x: h,
        y: f,
        duration: 0.01,
        beforeSetup: function(j) {
            j.element.hide().makeClipping().makePositioned()
        },
        afterFinishInternal: function(j) {
            new Effect.Parallel([new Effect.Opacity(j.element, {
                sync: true,
                to: 1,
                from: 0,
                transition: b.opacityTransition
            }), new Effect.Move(j.element, {
                x: e,
                y: d,
                sync: true,
                transition: b.moveTransition
            }), new Effect.Scale(j.element, 100, {
                scaleMode: {
                    originalHeight: g.height,
                    originalWidth: g.width
                },
                sync: true,
                scaleFrom: window.opera ? 1: 0,
                transition: b.scaleTransition,
                restoreAfterFinish: true
            })], Object.extend({
                beforeSetup: function(k) {
                    k.effects[0].element.setStyle({
                        height: "0px"
                    }).show()
                },
                afterFinishInternal: function(k) {
                    k.effects[0].element.undoClipping().undoPositioned().setStyle(a)
                }
            },
            b))
        }
    })
};
Effect.Shrink = function(c) {
    c = $(c);
    var b = Object.extend({
        direction: "center",
        moveTransition: Effect.Transitions.sinoidal,
        scaleTransition: Effect.Transitions.sinoidal,
        opacityTransition: Effect.Transitions.none
    },
    arguments[1] || {});
    var a = {
        top: c.style.top,
        left: c.style.left,
        height: c.style.height,
        width: c.style.width,
        opacity: c.getInlineOpacity()
    };
    var f = c.getDimensions();
    var e,
    d;
    switch (b.direction) {
    case "top-left":
        e = d = 0;
        break;
    case "top-right":
        e = f.width;
        d = 0;
        break;
    case "bottom-left":
        e = 0;
        d = f.height;
        break;
    case "bottom-right":
        e = f.width;
        d = f.height;
        break;
    case "center":
        e = f.width / 2;
        d = f.height / 2;
        break
    }
    return new Effect.Parallel([new Effect.Opacity(c, {
        sync: true,
        to: 0,
        from: 1,
        transition: b.opacityTransition
    }), new Effect.Scale(c, window.opera ? 1: 0, {
        sync: true,
        transition: b.scaleTransition,
        restoreAfterFinish: true
    }), new Effect.Move(c, {
        x: e,
        y: d,
        sync: true,
        transition: b.moveTransition
    })], Object.extend({
        beforeStartInternal: function(g) {
            g.effects[0].element.makePositioned().makeClipping()
        },
        afterFinishInternal: function(g) {
            g.effects[0].element.hide().undoClipping().undoPositioned().setStyle(a)
        }
    },
    b))
};
Effect.Pulsate = function(c) {
    c = $(c);
    var b = arguments[1] || {},
    a = c.getInlineOpacity(),
    e = b.transition || Effect.Transitions.linear,
    d = function(f) {
        return 1 - e(( - Math.cos((f * (b.pulses || 5) * 2) * Math.PI) / 2) + 0.5)
    };
    return new Effect.Opacity(c, Object.extend(Object.extend({
        duration: 2,
        from: 0,
        afterFinishInternal: function(f) {
            f.element.setStyle({
                opacity: a
            })
        }
    },
    b), {
        transition: d
    }))
};
Effect.Fold = function(b) {
    b = $(b);
    var a = {
        top: b.style.top,
        left: b.style.left,
        width: b.style.width,
        height: b.style.height
    };
    b.makeClipping();
    return new Effect.Scale(b, 5, Object.extend({
        scaleContent: false,
        scaleX: false,
        afterFinishInternal: function(c) {
            new Effect.Scale(b, 1, {
                scaleContent: false,
                scaleY: false,
                afterFinishInternal: function(d) {
                    d.element.hide().undoClipping().setStyle(a)
                }
            })
        }
    },
    arguments[1] || {}))
};
Effect.Morph = Class.create(Effect.Base, {
    initialize: function(c) {
        this.element = $(c);
        if (!this.element) {
            throw (Effect._elementDoesNotExistError)
        }
        var a = Object.extend({
            style: {}
        },
        arguments[1] || {});
        if (!Object.isString(a.style)) {
            this.style = $H(a.style)
        } else {
            if (a.style.include(":")) {
                this.style = a.style.parseStyle()
            } else {
                this.element.addClassName(a.style);
                this.style = $H(this.element.getStyles());
                this.element.removeClassName(a.style);
                var b = this.element.getStyles();
                this.style = this.style.reject(function(d) {
                    return d.value == b[d.key]
                });
                a.afterFinishInternal = function(d) {
                    d.element.addClassName(d.options.style);
                    d.transforms.each(function(e) {
                        d.element.style[e.style] = ""
                    })
                }
            }
        }
        this.start(a)
    },
    setup: function() {
        function a(b) {
            if (!b || ["rgba(0, 0, 0, 0)", "transparent"].include(b)) {
                b = "#ffffff"
            }
            b = b.parseColor();
            return $R(0, 2).map(function(c) {
                return parseInt(b.slice(c * 2 + 1, c * 2 + 3), 16)
            })
        }
        this.transforms = this.style.map(function(g) {
            var f = g[0],
            e = g[1],
            d = null;
            if (e.parseColor("#zzzzzz") != "#zzzzzz") {
                e = e.parseColor();
                d = "color"
            } else {
                if (f == "opacity") {
                    e = parseFloat(e);
                    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
                        this.element.setStyle({
                            zoom: 1
                        })
                    }
                } else {
                    if (Element.CSS_LENGTH.test(e)) {
                        var c = e.match(/^([\+\-]?[0-9\.]+)(.*)$/);
                        e = parseFloat(c[1]);
                        d = (c.length == 3) ? c[2] : null
                    }
                }
            }
            var b = this.element.getStyle(f);
            return {
                style: f.camelize(),
                originalValue: d == "color" ? a(b) : parseFloat(b || 0),
                targetValue: d == "color" ? a(e) : e,
                unit: d
            }
        }.bind(this)).reject(function(b) {
            return ((b.originalValue == b.targetValue) || (b.unit != "color" && (isNaN(b.originalValue) || isNaN(b.targetValue))))
        })
    },
    update: function(a) {
        var d = {},
        b,
        c = this.transforms.length;
        while (c--) {
            d[(b = this.transforms[c]).style] = b.unit == "color" ? "#" + (Math.round(b.originalValue[0] + (b.targetValue[0] - b.originalValue[0]) * a)).toColorPart() + (Math.round(b.originalValue[1] + (b.targetValue[1] - b.originalValue[1]) * a)).toColorPart() + (Math.round(b.originalValue[2] + (b.targetValue[2] - b.originalValue[2]) * a)).toColorPart() : (b.originalValue + (b.targetValue - b.originalValue) * a).toFixed(3) + (b.unit === null ? "": b.unit)
        }
        this.element.setStyle(d, true)
    }
});
Effect.Transform = Class.create({
    initialize: function(a) {
        this.tracks = [];
        this.options = arguments[1] || {};
        this.addTracks(a)
    },
    addTracks: function(a) {
        a.each(function(b) {
            b = $H(b);
            var c = b.values().first();
            this.tracks.push($H({
                ids: b.keys().first(),
                effect: Effect.Morph,
                options: {
                    style: c
                }
            }))
        }.bind(this));
        return this
    },
    play: function() {
        return new Effect.Parallel(this.tracks.map(function(a) {
            var d = a.get("ids"),
            c = a.get("effect"),
            b = a.get("options");
            var e = [$(d) || $$(d)].flatten();
            return e.map(function(f) {
                return new c(f, Object.extend({
                    sync: true
                },
                b))
            })
        }).flatten(), this.options)
    }
});
Element.CSS_PROPERTIES = $w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth borderRightColor borderRightStyle borderRightWidth borderSpacing borderTopColor borderTopStyle borderTopWidth bottom clip color fontSize fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop markerOffset maxHeight maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft paddingRight paddingTop right textIndent top width wordSpacing zIndex");
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.__parseStyleElement = document.createElement("div");
String.prototype.parseStyle = function() {
    var b,
    a = $H();
    if (Prototype.Browser.WebKit) {
        b = new Element("div", {
            style: this
        }).style
    } else {
        String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
        b = String.__parseStyleElement.childNodes[0].style
    }
    Element.CSS_PROPERTIES.each(function(c) {
        if (b[c]) {
            a.set(c, b[c])
        }
    });
    if (Prototype.Browser.IE && this.include("opacity")) {
        a.set("opacity", this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1])
    }
    return a
};
if (document.defaultView && document.defaultView.getComputedStyle) {
    Element.getStyles = function(b) {
        var a = document.defaultView.getComputedStyle($(b), null);
        return Element.CSS_PROPERTIES.inject({},
        function(c, d) {
            c[d] = a[d];
            return c
        })
    }
} else {
    Element.getStyles = function(b) {
        b = $(b);
        var a = b.currentStyle,
        c;
        c = Element.CSS_PROPERTIES.inject({},
        function(d, e) {
            d[e] = a[e];
            return d
        });
        if (!c.opacity) {
            c.opacity = b.getOpacity()
        }
        return c
    }
}
Effect.Methods = {
    morph: function(a, b) {
        a = $(a);
        new Effect.Morph(a, Object.extend({
            style: b
        },
        arguments[2] || {}));
        return a
    },
    visualEffect: function(c, e, b) {
        c = $(c);
        var d = e.dasherize().camelize(),
        a = d.charAt(0).toUpperCase() + d.substring(1);
        new Effect[a](c, b);
        return c
    },
    highlight: function(b, a) {
        b = $(b);
        new Effect.Highlight(b, a);
        return b
    }
};
$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown pulsate shake puff squish switchOff dropOut").each(function(a) {
    Effect.Methods[a] = function(c, b) {
        c = $(c);
        Effect[a.charAt(0).toUpperCase() + a.substring(1)](c, b);
        return c
    }
});
$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(a) {
    Effect.Methods[a] = Element[a]
});
Element.addMethods(Effect.Methods);
if (Object.isUndefined(Effect)) {
    throw ("dragdrop.js requires including script.aculo.us' effects.js library")
}
var Droppables = {
    drops: [],
    remove: function(a) {
        this.drops = this.drops.reject(function(b) {
            return b.element == $(a)
        })
    },
    add: function(b) {
        b = $(b);
        var a = Object.extend({
            greedy: true,
            hoverclass: null,
            tree: false
        },
        arguments[1] || {});
        if (a.containment) {
            a._containers = [];
            var c = a.containment;
            if (Object.isArray(c)) {
                c.each(function(d) {
                    a._containers.push($(d))
                })
            } else {
                a._containers.push($(c))
            }
        }
        if (a.accept) {
            a.accept = [a.accept].flatten()
        }
        Element.makePositioned(b);
        a.element = b;
        this.drops.push(a)
    },
    findDeepestChild: function(a) {
        deepest = a[0];
        for (i = 1; i < a.length; ++i) {
            if (Element.isParent(a[i].element, deepest.element)) {
                deepest = a[i]
            }
        }
        return deepest
    },
    isContained: function(b, a) {
        var c;
        if (a.tree) {
            c = b.treeNode
        } else {
            c = b.parentNode
        }
        return a._containers.detect(function(d) {
            return c == d
        })
    },
    isAffected: function(a, c, b) {
        return ((b.element != c) && ((!b._containers) || this.isContained(c, b)) && ((!b.accept) || (Element.classNames(c).detect(function(d) {
            return b.accept.include(d)
        }))) && Position.within(b.element, a[0], a[1]))
    },
    deactivate: function(a) {
        if (a.hoverclass) {
            Element.removeClassName(a.element, a.hoverclass)
        }
        this.last_active = null
    },
    activate: function(a) {
        if (a.hoverclass) {
            Element.addClassName(a.element, a.hoverclass)
        }
        this.last_active = a
    },
    show: function(a, c) {
        if (!this.drops.length) {
            return
        }
        var b,
        d = [];
        this.drops.each(function(e) {
            if (Droppables.isAffected(a, c, e)) {
                d.push(e)
            }
        });
        if (d.length > 0) {
            b = Droppables.findDeepestChild(d)
        }
        if (this.last_active && this.last_active != b) {
            this.deactivate(this.last_active)
        }
        if (b) {
            Position.within(b.element, a[0], a[1]);
            if (b.onHover) {
                b.onHover(c, b.element, Position.overlap(b.overlap, b.element))
            }
            if (b != this.last_active) {
                Droppables.activate(b)
            }
        }
    },
    fire: function(b, a) {
        if (!this.last_active) {
            return
        }
        Position.prepare();
        if (this.isAffected([Event.pointerX(b), Event.pointerY(b)], a, this.last_active)) {
            if (this.last_active.onDrop) {
                this.last_active.onDrop(a, this.last_active.element, b);
                return true
            }
        }
    },
    reset: function() {
        if (this.last_active) {
            this.deactivate(this.last_active)
        }
    }
};
var Draggables = {
    drags: [],
    observers: [],
    register: function(a) {
        if (this.drags.length == 0) {
            this.eventMouseUp = this.endDrag.bindAsEventListener(this);
            this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
            this.eventKeypress = this.keyPress.bindAsEventListener(this);
            Event.observe(document, "mouseup", this.eventMouseUp);
            Event.observe(document, "mousemove", this.eventMouseMove);
            Event.observe(document, "keypress", this.eventKeypress)
        }
        this.drags.push(a)
    },
    unregister: function(a) {
        this.drags = this.drags.reject(function(b) {
            return b == a
        });
        if (this.drags.length == 0) {
            Event.stopObserving(document, "mouseup", this.eventMouseUp);
            Event.stopObserving(document, "mousemove", this.eventMouseMove);
            Event.stopObserving(document, "keypress", this.eventKeypress)
        }
    },
    activate: function(a) {
        if (a.options.delay) {
            this._timeout = setTimeout(function() {
                Draggables._timeout = null;
                window.focus();
                Draggables.activeDraggable = a
            }.bind(this), a.options.delay)
        } else {
            window.focus();
            this.activeDraggable = a
        }
    },
    deactivate: function() {
        this.activeDraggable = null
    },
    updateDrag: function(a) {
        if (!this.activeDraggable) {
            return
        }
        var b = [Event.pointerX(a), Event.pointerY(a)];
        if (this._lastPointer && (this._lastPointer.inspect() == b.inspect())) {
            return
        }
        this._lastPointer = b;
        this.activeDraggable.updateDrag(a, b)
    },
    endDrag: function(a) {
        if (this._timeout) {
            clearTimeout(this._timeout);
            this._timeout = null
        }
        if (!this.activeDraggable) {
            return
        }
        this._lastPointer = null;
        this.activeDraggable.endDrag(a);
        this.activeDraggable = null
    },
    keyPress: function(a) {
        if (this.activeDraggable) {
            this.activeDraggable.keyPress(a)
        }
    },
    addObserver: function(a) {
        this.observers.push(a);
        this._cacheObserverCallbacks()
    },
    removeObserver: function(a) {
        this.observers = this.observers.reject(function(b) {
            return b.element == a
        });
        this._cacheObserverCallbacks()
    },
    notify: function(b, a, c) {
        if (this[b + "Count"] > 0) {
            this.observers.each(function(d) {
                if (d[b]) {
                    d[b](b, a, c)
                }
            })
        }
        if (a.options[b]) {
            a.options[b](a, c)
        }
    },
    _cacheObserverCallbacks: function() { ["onStart", "onEnd", "onDrag"].each(function(a) {
            Draggables[a + "Count"] = Draggables.observers.select(function(b) {
                return b[a]
            }).length
        })
    }
};
var Draggable = Class.create({
    initialize: function(b) {
        var c = {
            handle: false,
            reverteffect: function(f, e, d) {
                var g = Math.sqrt(Math.abs(e ^ 2) + Math.abs(d ^ 2)) * 0.02;
                new Effect.Move(f, {
                    x: -d,
                    y: -e,
                    duration: g,
                    queue: {
                        scope: "_draggable",
                        position: "end"
                    }
                })
            },
            endeffect: function(e) {
                var d = Object.isNumber(e._opacity) ? e._opacity: 1;
                new Effect.Opacity(e, {
                    duration: 0.2,
                    from: 0.7,
                    to: d,
                    queue: {
                        scope: "_draggable",
                        position: "end"
                    },
                    afterFinish: function() {
                        Draggable._dragging[e] = false
                    }
                })
            },
            zindex: 1000,
            revert: false,
            quiet: false,
            scroll: false,
            scrollSensitivity: 20,
            scrollSpeed: 15,
            snap: false,
            delay: 0
        };
        if (!arguments[1] || Object.isUndefined(arguments[1].endeffect)) {
            Object.extend(c, {
                starteffect: function(d) {
                    d._opacity = Element.getOpacity(d);
                    Draggable._dragging[d] = true;
                    new Effect.Opacity(d, {
                        duration: 0.2,
                        from: d._opacity,
                        to: 0.7
                    })
                }
            })
        }
        var a = Object.extend(c, arguments[1] || {});
        this.element = $(b);
        if (a.handle && Object.isString(a.handle)) {
            this.handle = this.element.down("." + a.handle, 0)
        }
        if (!this.handle) {
            this.handle = $(a.handle)
        }
        if (!this.handle) {
            this.handle = this.element
        }
        if (a.scroll && !a.scroll.scrollTo && !a.scroll.outerHTML) {
            a.scroll = $(a.scroll);
            this._isScrollChild = Element.childOf(this.element, a.scroll)
        }
        Element.makePositioned(this.element);
        this.options = a;
        this.dragging = false;
        this.eventMouseDown = this.initDrag.bindAsEventListener(this);
        Event.observe(this.handle, "mousedown", this.eventMouseDown);
        Draggables.register(this)
    },
    destroy: function() {
        Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
        Draggables.unregister(this)
    },
    currentDelta: function() {
        return ([parseInt(Element.getStyle(this.element, "left") || "0"), parseInt(Element.getStyle(this.element, "top") || "0")])
    },
    initDrag: function(a) {
        if (!Object.isUndefined(Draggable._dragging[this.element]) && Draggable._dragging[this.element]) {
            return
        }
        if (Event.isLeftClick(a)) {
            var c = Event.element(a);
            if ((tag_name = c.tagName.toUpperCase()) && (tag_name == "INPUT" || tag_name == "SELECT" || tag_name == "OPTION" || tag_name == "BUTTON" || tag_name == "TEXTAREA")) {
                return
            }
            var b = [Event.pointerX(a), Event.pointerY(a)];
            var d = this.element.cumulativeOffset();
            this.offset = [0, 1].map(function(e) {
                return (b[e] - d[e])
            });
            Draggables.activate(this);
            Event.stop(a)
        }
    },
    startDrag: function(b) {
        this.dragging = true;
        if (!this.delta) {
            this.delta = this.currentDelta()
        }
        if (this.options.zindex) {
            this.originalZ = parseInt(Element.getStyle(this.element, "z-index") || 0);
            this.element.style.zIndex = this.options.zindex
        }
        if (this.options.ghosting) {
            this._clone = this.element.cloneNode(true);
            this._originallyAbsolute = (this.element.getStyle("position") == "absolute");
            if (!this._originallyAbsolute) {
                Position.absolutize(this.element)
            }
            this.element.parentNode.insertBefore(this._clone, this.element)
        }
        if (this.options.scroll) {
            if (this.options.scroll == window) {
                var a = this._getWindowScroll(this.options.scroll);
                this.originalScrollLeft = a.left;
                this.originalScrollTop = a.top
            } else {
                this.originalScrollLeft = this.options.scroll.scrollLeft;
                this.originalScrollTop = this.options.scroll.scrollTop
            }
        }
        Draggables.notify("onStart", this, b);
        if (this.options.starteffect) {
            this.options.starteffect(this.element)
        }
    },
    updateDrag: function(event, pointer) {
        if (!this.dragging) {
            this.startDrag(event)
        }
        if (!this.options.quiet) {
            Position.prepare();
            Droppables.show(pointer, this.element)
        }
        Draggables.notify("onDrag", this, event);
        this.draw(pointer);
        if (this.options.change) {
            this.options.change(this)
        }
        if (this.options.scroll) {
            this.stopScrolling();
            var p;
            if (this.options.scroll == window) {
                with(this._getWindowScroll(this.options.scroll)) {
                    p = [left, top, left + width, top + height]
                }
            } else {
                p = Position.page(this.options.scroll).toArray();
                p[0] += this.options.scroll.scrollLeft + Position.deltaX;
                p[1] += this.options.scroll.scrollTop + Position.deltaY;
                p.push(p[0] + this.options.scroll.offsetWidth);
                p.push(p[1] + this.options.scroll.offsetHeight)
            }
            var speed = [0, 0];
            if (pointer[0] < (p[0] + this.options.scrollSensitivity)) {
                speed[0] = pointer[0] - (p[0] + this.options.scrollSensitivity)
            }
            if (pointer[1] < (p[1] + this.options.scrollSensitivity)) {
                speed[1] = pointer[1] - (p[1] + this.options.scrollSensitivity)
            }
            if (pointer[0] > (p[2] - this.options.scrollSensitivity)) {
                speed[0] = pointer[0] - (p[2] - this.options.scrollSensitivity)
            }
            if (pointer[1] > (p[3] - this.options.scrollSensitivity)) {
                speed[1] = pointer[1] - (p[3] - this.options.scrollSensitivity)
            }
            this.startScrolling(speed)
        }
        if (Prototype.Browser.WebKit) {
            window.scrollBy(0, 0)
        }
        Event.stop(event)
    },
    finishDrag: function(b, f) {
        this.dragging = false;
        if (this.options.quiet) {
            Position.prepare();
            var e = [Event.pointerX(b), Event.pointerY(b)];
            Droppables.show(e, this.element)
        }
        if (this.options.ghosting) {
            if (!this._originallyAbsolute) {
                Position.relativize(this.element)
            }
            delete this._originallyAbsolute;
            Element.remove(this._clone);
            this._clone = null
        }
        var g = false;
        if (f) {
            g = Droppables.fire(b, this.element);
            if (!g) {
                g = false
            }
        }
        if (g && this.options.onDropped) {
            this.options.onDropped(this.element)
        }
        Draggables.notify("onEnd", this, b);
        var a = this.options.revert;
        if (a && Object.isFunction(a)) {
            a = a(this.element)
        }
        var c = this.currentDelta();
        if (a && this.options.reverteffect) {
            if (g == 0 || a != "failure") {
                this.options.reverteffect(this.element, c[1] - this.delta[1], c[0] - this.delta[0])
            }
        } else {
            this.delta = c
        }
        if (this.options.zindex) {
            this.element.style.zIndex = this.originalZ
        }
        if (this.options.endeffect) {
            this.options.endeffect(this.element)
        }
        Draggables.deactivate(this);
        Droppables.reset()
    },
    keyPress: function(a) {
        if (a.keyCode != Event.KEY_ESC) {
            return
        }
        this.finishDrag(a, false);
        Event.stop(a)
    },
    endDrag: function(a) {
        if (!this.dragging) {
            return
        }
        this.stopScrolling();
        this.finishDrag(a, true);
        Event.stop(a)
    },
    draw: function(a) {
        var g = this.element.cumulativeOffset();
        if (this.options.ghosting) {
            var c = Position.realOffset(this.element);
            g[0] += c[0] - Position.deltaX;
            g[1] += c[1] - Position.deltaY
        }
        var f = this.currentDelta();
        g[0] -= f[0];
        g[1] -= f[1];
        if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
            g[0] -= this.options.scroll.scrollLeft - this.originalScrollLeft;
            g[1] -= this.options.scroll.scrollTop - this.originalScrollTop
        }
        var e = [0, 1].map(function(d) {
            return (a[d] - g[d] - this.offset[d])
        }.bind(this));
        if (this.options.snap) {
            if (Object.isFunction(this.options.snap)) {
                e = this.options.snap(e[0], e[1], this)
            } else {
                if (Object.isArray(this.options.snap)) {
                    e = e.map(function(d, h) {
                        return (d / this.options.snap[h]).round() * this.options.snap[h]
                    }.bind(this))
                } else {
                    e = e.map(function(d) {
                        return (d / this.options.snap).round() * this.options.snap
                    }.bind(this))
                }
            }
        }
        var b = this.element.style;
        if ((!this.options.constraint) || (this.options.constraint == "horizontal")) {
            b.left = e[0] + "px"
        }
        if ((!this.options.constraint) || (this.options.constraint == "vertical")) {
            b.top = e[1] + "px"
        }
        if (b.visibility == "hidden") {
            b.visibility = ""
        }
    },
    stopScrolling: function() {
        if (this.scrollInterval) {
            clearInterval(this.scrollInterval);
            this.scrollInterval = null;
            Draggables._lastScrollPointer = null
        }
    },
    startScrolling: function(a) {
        if (! (a[0] || a[1])) {
            return
        }
        this.scrollSpeed = [a[0] * this.options.scrollSpeed, a[1] * this.options.scrollSpeed];
        this.lastScrolled = new Date();
        this.scrollInterval = setInterval(this.scroll.bind(this), 10)
    },
    scroll: function() {
        var current = new Date();
        var delta = current - this.lastScrolled;
        this.lastScrolled = current;
        if (this.options.scroll == window) {
            with(this._getWindowScroll(this.options.scroll)) {
                if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
                    var d = delta / 1000;
                    this.options.scroll.scrollTo(left + d * this.scrollSpeed[0], top + d * this.scrollSpeed[1])
                }
            }
        } else {
            this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
            this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000
        }
        Position.prepare();
        Droppables.show(Draggables._lastPointer, this.element);
        Draggables.notify("onDrag", this);
        if (this._isScrollChild) {
            Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
            Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
            Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
            if (Draggables._lastScrollPointer[0] < 0) {
                Draggables._lastScrollPointer[0] = 0
            }
            if (Draggables._lastScrollPointer[1] < 0) {
                Draggables._lastScrollPointer[1] = 0
            }
            this.draw(Draggables._lastScrollPointer)
        }
        if (this.options.change) {
            this.options.change(this)
        }
    },
    _getWindowScroll: function(w) {
        var T,
        L,
        W,
        H;
        with(w.document) {
            if (w.document.documentElement && documentElement.scrollTop) {
                T = documentElement.scrollTop;
                L = documentElement.scrollLeft
            } else {
                if (w.document.body) {
                    T = body.scrollTop;
                    L = body.scrollLeft
                }
            }
            if (w.innerWidth) {
                W = w.innerWidth;
                H = w.innerHeight
            } else {
                if (w.document.documentElement && documentElement.clientWidth) {
                    W = documentElement.clientWidth;
                    H = documentElement.clientHeight
                } else {
                    W = body.offsetWidth;
                    H = body.offsetHeight
                }
            }
        }
        return {
            top: T,
            left: L,
            width: W,
            height: H
        }
    }
});
Draggable._dragging = {};
var SortableObserver = Class.create({
    initialize: function(b, a) {
        this.element = $(b);
        this.observer = a;
        this.lastValue = Sortable.serialize(this.element)
    },
    onStart: function() {
        this.lastValue = Sortable.serialize(this.element)
    },
    onEnd: function() {
        Sortable.unmark();
        if (this.lastValue != Sortable.serialize(this.element)) {
            this.observer(this.element)
        }
    }
});
var Sortable = {
    SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
    sortables: {},
    _findRootElement: function(a) {
        while (a.tagName.toUpperCase() != "BODY") {
            if (a.id && Sortable.sortables[a.id]) {
                return a
            }
            a = a.parentNode
        }
    },
    options: function(a) {
        a = Sortable._findRootElement($(a));
        if (!a) {
            return
        }
        return Sortable.sortables[a.id]
    },
    destroy: function(a) {
        a = $(a);
        var b = Sortable.sortables[a.id];
        if (b) {
            Draggables.removeObserver(b.element);
            b.droppables.each(function(c) {
                Droppables.remove(c)
            });
            b.draggables.invoke("destroy");
            delete Sortable.sortables[b.element.id]
        }
    },
    create: function(c) {
        c = $(c);
        var b = Object.extend({
            element: c,
            tag: "li",
            dropOnEmpty: false,
            tree: false,
            treeTag: "ul",
            overlap: "vertical",
            constraint: "vertical",
            containment: c,
            handle: false,
            only: false,
            delay: 0,
            hoverclass: null,
            ghosting: false,
            quiet: false,
            scroll: false,
            scrollSensitivity: 20,
            scrollSpeed: 15,
            format: this.SERIALIZE_RULE,
            elements: false,
            handles: false,
            onChange: Prototype.emptyFunction,
            onUpdate: Prototype.emptyFunction
        },
        arguments[1] || {});
        this.destroy(c);
        var a = {
            revert: true,
            quiet: b.quiet,
            scroll: b.scroll,
            scrollSpeed: b.scrollSpeed,
            scrollSensitivity: b.scrollSensitivity,
            delay: b.delay,
            ghosting: b.ghosting,
            constraint: b.constraint,
            handle: b.handle
        };
        if (b.starteffect) {
            a.starteffect = b.starteffect
        }
        if (b.reverteffect) {
            a.reverteffect = b.reverteffect
        } else {
            if (b.ghosting) {
                a.reverteffect = function(f) {
                    f.style.top = 0;
                    f.style.left = 0
                }
            }
        }
        if (b.endeffect) {
            a.endeffect = b.endeffect
        }
        if (b.zindex) {
            a.zindex = b.zindex
        }
        var d = {
            overlap: b.overlap,
            containment: b.containment,
            tree: b.tree,
            hoverclass: b.hoverclass,
            onHover: Sortable.onHover
        };
        var e = {
            onHover: Sortable.onEmptyHover,
            overlap: b.overlap,
            containment: b.containment,
            hoverclass: b.hoverclass
        };
        Element.cleanWhitespace(c);
        b.draggables = [];
        b.droppables = [];
        if (b.dropOnEmpty || b.tree) {
            Droppables.add(c, e);
            b.droppables.push(c)
        } (b.elements || this.findElements(c, b) || []).each(function(h, f) {
            var g = b.handles ? $(b.handles[f]) : (b.handle ? $(h).select("." + b.handle)[0] : h);
            b.draggables.push(new Draggable(h, Object.extend(a, {
                handle: g
            })));
            Droppables.add(h, d);
            if (b.tree) {
                h.treeNode = c
            }
            b.droppables.push(h)
        });
        if (b.tree) { (Sortable.findTreeElements(c, b) || []).each(function(f) {
                Droppables.add(f, e);
                f.treeNode = c;
                b.droppables.push(f)
            })
        }
        this.sortables[c.identify()] = b;
        Draggables.addObserver(new SortableObserver(c, b.onUpdate))
    },
    findElements: function(b, a) {
        return Element.findChildren(b, a.only, a.tree ? true: false, a.tag)
    },
    findTreeElements: function(b, a) {
        return Element.findChildren(b, a.only, a.tree ? true: false, a.treeTag)
    },
    onHover: function(e, d, a) {
        if (Element.isParent(d, e)) {
            return
        }
        if (a > 0.33 && a < 0.66 && Sortable.options(d).tree) {
            return
        } else {
            if (a > 0.5) {
                Sortable.mark(d, "before");
                if (d.previousSibling != e) {
                    var b = e.parentNode;
                    e.style.visibility = "hidden";
                    d.parentNode.insertBefore(e, d);
                    if (d.parentNode != b) {
                        Sortable.options(b).onChange(e)
                    }
                    Sortable.options(d.parentNode).onChange(e)
                }
            } else {
                Sortable.mark(d, "after");
                var c = d.nextSibling || null;
                if (c != e) {
                    var b = e.parentNode;
                    e.style.visibility = "hidden";
                    d.parentNode.insertBefore(e, c);
                    if (d.parentNode != b) {
                        Sortable.options(b).onChange(e)
                    }
                    Sortable.options(d.parentNode).onChange(e)
                }
            }
        }
    },
    onEmptyHover: function(e, g, h) {
        var j = e.parentNode;
        var a = Sortable.options(g);
        if (!Element.isParent(g, e)) {
            var f;
            var c = Sortable.findElements(g, {
                tag: a.tag,
                only: a.only
            });
            var b = null;
            if (c) {
                var d = Element.offsetSize(g, a.overlap) * (1 - h);
                for (f = 0; f < c.length; f += 1) {
                    if (d - Element.offsetSize(c[f], a.overlap) >= 0) {
                        d -= Element.offsetSize(c[f], a.overlap)
                    } else {
                        if (d - (Element.offsetSize(c[f], a.overlap) / 2) >= 0) {
                            b = f + 1 < c.length ? c[f + 1] : null;
                            break
                        } else {
                            b = c[f];
                            break
                        }
                    }
                }
            }
            g.insertBefore(e, b);
            Sortable.options(j).onChange(e);
            a.onChange(e)
        }
    },
    unmark: function() {
        if (Sortable._marker) {
            Sortable._marker.hide()
        }
    },
    mark: function(b, a) {
        var d = Sortable.options(b.parentNode);
        if (d && !d.ghosting) {
            return
        }
        if (!Sortable._marker) {
            Sortable._marker = ($("dropmarker") || Element.extend(document.createElement("DIV"))).hide().addClassName("dropmarker").setStyle({
                position: "absolute"
            });
            document.getElementsByTagName("body").item(0).appendChild(Sortable._marker)
        }
        var c = b.cumulativeOffset();
        Sortable._marker.setStyle({
            left: c[0] + "px",
            top: c[1] + "px"
        });
        if (a == "after") {
            if (d.overlap == "horizontal") {
                Sortable._marker.setStyle({
                    left: (c[0] + b.clientWidth) + "px"
                })
            } else {
                Sortable._marker.setStyle({
                    top: (c[1] + b.clientHeight) + "px"
                })
            }
        }
        Sortable._marker.show()
    },
    _tree: function(e, b, f) {
        var d = Sortable.findElements(e, b) || [];
        for (var c = 0; c < d.length; ++c) {
            var a = d[c].id.match(b.format);
            if (!a) {
                continue
            }
            var g = {
                id: encodeURIComponent(a ? a[1] : null),
                element: e,
                parent: f,
                children: [],
                position: f.children.length,
                container: $(d[c]).down(b.treeTag)
            };
            if (g.container) {
                this._tree(g.container, b, g)
            }
            f.children.push(g)
        }
        return f
    },
    tree: function(d) {
        d = $(d);
        var c = this.options(d);
        var b = Object.extend({
            tag: c.tag,
            treeTag: c.treeTag,
            only: c.only,
            name: d.id,
            format: c.format
        },
        arguments[1] || {});
        var a = {
            id: null,
            parent: null,
            children: [],
            container: d,
            position: 0
        };
        return Sortable._tree(d, b, a)
    },
    _constructIndex: function(b) {
        var a = "";
        do {
            if (b.id) {
                a = "[" + b.position + "]" + a
            }
        }
        while ((b = b.parent) != null);
        return a
    },
    sequence: function(b) {
        b = $(b);
        var a = Object.extend(this.options(b), arguments[1] || {});
        return $(this.findElements(b, a) || []).map(function(c) {
            return c.id.match(a.format) ? c.id.match(a.format)[1] : ""
        })
    },
    setSequence: function(b, c) {
        b = $(b);
        var a = Object.extend(this.options(b), arguments[2] || {});
        var d = {};
        this.findElements(b, a).each(function(e) {
            if (e.id.match(a.format)) {
                d[e.id.match(a.format)[1]] = [e, e.parentNode]
            }
            e.parentNode.removeChild(e)
        });
        c.each(function(e) {
            var f = d[e];
            if (f) {
                f[1].appendChild(f[0]);
                delete d[e]
            }
        })
    },
    serialize: function(c) {
        c = $(c);
        var b = Object.extend(Sortable.options(c), arguments[1] || {});
        var a = encodeURIComponent((arguments[1] && arguments[1].name) ? arguments[1].name: c.id);
        if (b.tree) {
            return Sortable.tree(c, arguments[1]).children.map(function(d) {
                return [a + Sortable._constructIndex(d) + "[id]=" + encodeURIComponent(d.id)].concat(d.children.map(arguments.callee))
            }).flatten().join("&")
        } else {
            return Sortable.sequence(c, arguments[1]).map(function(d) {
                return a + "[]=" + encodeURIComponent(d)
            }).join("&")
        }
    }
};
Element.isParent = function(b, a) {
    if (!b.parentNode || b == a) {
        return false
    }
    if (b.parentNode == a) {
        return true
    }
    return Element.isParent(b.parentNode, a)
};
Element.findChildren = function(d, b, a, c) {
    if (!d.hasChildNodes()) {
        return null
    }
    c = c.toUpperCase();
    if (b) {
        b = [b].flatten()
    }
    var e = [];
    $A(d.childNodes).each(function(g) {
        if (g.tagName && g.tagName.toUpperCase() == c && (!b || (Element.classNames(g).detect(function(h) {
            return b.include(h)
        })))) {
            e.push(g)
        }
        if (a) {
            var f = Element.findChildren(g, b, a, c);
            if (f) {
                e.push(f)
            }
        }
    });
    return (e.length > 0 ? e.flatten() : [])
};
Element.offsetSize = function(a, b) {
    return a["offset" + ((b == "vertical" || b == "height") ? "Height": "Width")]
};
if (typeof Effect == "undefined") {
    throw ("controls.js requires including script.aculo.us' effects.js library")
}
var Autocompleter = {};
Autocompleter.Base = Class.create({
    baseInitialize: function(b, c, a) {
        b = $(b);
        this.element = b;
        this.update = $(c);
        this.hasFocus = false;
        this.changed = false;
        this.active = false;
        this.index = 0;
        this.entryCount = 0;
        this.oldElementValue = this.element.value;
        if (this.setOptions) {
            this.setOptions(a)
        } else {
            this.options = a || {}
        }
        this.options.paramName = this.options.paramName || this.element.name;
        this.options.tokens = this.options.tokens || [];
        this.options.frequency = this.options.frequency || 0.4;
        this.options.minChars = this.options.minChars || 1;
        this.options.onShow = this.options.onShow ||
        function(d, e) {
            if (!e.style.position || e.style.position == "absolute") {
                e.style.position = "absolute";
                Position.clone(d, e, {
                    setHeight: false,
                    offsetTop: d.offsetHeight
                })
            }
            Effect.Appear(e, {
                duration: 0.15
            })
        };
        this.options.onHide = this.options.onHide ||
        function(d, e) {
            new Effect.Fade(e, {
                duration: 0.15
            })
        };
        if (typeof(this.options.tokens) == "string") {
            this.options.tokens = new Array(this.options.tokens)
        }
        if (!this.options.tokens.include("\n")) {
            this.options.tokens.push("\n")
        }
        this.observer = null;
        this.element.setAttribute("autocomplete", "off");
        Element.hide(this.update);
        Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
        Event.observe(this.element, "keydown", this.onKeyPress.bindAsEventListener(this))
    },
    show: function() {
        if (Element.getStyle(this.update, "display") == "none") {
            this.options.onShow(this.element, this.update)
        }
        if (!this.iefix && (Prototype.Browser.IE) && (Element.getStyle(this.update, "position") == "absolute")) {
            new Insertion.After(this.update, '<iframe id="' + this.update.id + '_iefix" style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
            this.iefix = $(this.update.id + "_iefix")
        }
        if (this.iefix) {
            setTimeout(this.fixIEOverlapping.bind(this), 50)
        }
    },
    fixIEOverlapping: function() {
        Position.clone(this.update, this.iefix, {
            setTop: (!this.update.style.height)
        });
        this.iefix.style.zIndex = 1;
        this.update.style.zIndex = 2;
        Element.show(this.iefix)
    },
    hide: function() {
        this.stopIndicator();
        if (Element.getStyle(this.update, "display") != "none") {
            this.options.onHide(this.element, this.update)
        }
        if (this.iefix) {
            Element.hide(this.iefix)
        }
    },
    startIndicator: function() {
        if (this.options.indicator) {
            Element.show(this.options.indicator)
        }
    },
    stopIndicator: function() {
        if (this.options.indicator) {
            Element.hide(this.options.indicator)
        }
    },
    onKeyPress: function(a) {
        if (this.active) {
            switch (a.keyCode) {
            case Event.KEY_TAB:
            case Event.KEY_RETURN:
                this.selectEntry();
                Event.stop(a);
            case Event.KEY_ESC:
                this.hide();
                this.active = false;
                Event.stop(a);
                return;
            case Event.KEY_LEFT:
            case Event.KEY_RIGHT:
                return;
            case Event.KEY_UP:
                this.markPrevious();
                this.render();
                Event.stop(a);
                return;
            case Event.KEY_DOWN:
                this.markNext();
                this.render();
                Event.stop(a);
                return
            }
        } else {
            if (a.keyCode == Event.KEY_TAB || a.keyCode == Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && a.keyCode == 0)) {
                return
            }
        }
        this.changed = true;
        this.hasFocus = true;
        if (this.observer) {
            clearTimeout(this.observer)
        }
        this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency * 1000)
    },
    activate: function() {
        this.changed = false;
        this.hasFocus = true;
        this.getUpdatedChoices()
    },
    onHover: function(b) {
        var a = Event.findElement(b, "LI");
        if (this.index != a.autocompleteIndex) {
            this.index = a.autocompleteIndex;
            this.render()
        }
        Event.stop(b)
    },
    onClick: function(b) {
        var a = Event.findElement(b, "LI");
        this.index = a.autocompleteIndex;
        this.selectEntry();
        this.hide()
    },
    onBlur: function(a) {
        setTimeout(this.hide.bind(this), 250);
        this.hasFocus = false;
        this.active = false
    },
    render: function() {
        if (this.entryCount > 0) {
            for (var a = 0; a < this.entryCount; a++) {
                this.index == a ? Element.addClassName(this.getEntry(a), "selected") : Element.removeClassName(this.getEntry(a), "selected")
            }
            if (this.hasFocus) {
                this.show();
                this.active = true
            }
        } else {
            this.active = false;
            this.hide()
        }
    },
    markPrevious: function() {
        if (this.index > 0) {
            this.index--
        } else {
            this.index = this.entryCount - 1
        }
        this.getEntry(this.index).scrollIntoView(true)
    },
    markNext: function() {
        if (this.index < this.entryCount - 1) {
            this.index++
        } else {
            this.index = 0
        }
        this.getEntry(this.index).scrollIntoView(false)
    },
    getEntry: function(a) {
        return this.update.firstChild.childNodes[a]
    },
    getCurrentEntry: function() {
        return this.getEntry(this.index)
    },
    selectEntry: function() {
        this.active = false;
        this.updateElement(this.getCurrentEntry())
    },
    updateElement: function(f) {
        if (this.options.updateElement) {
            this.options.updateElement(f);
            return
        }
        var d = "";
        if (this.options.select) {
            var a = $(f).select("." + this.options.select) || [];
            if (a.length > 0) {
                d = Element.collectTextNodes(a[0], this.options.select)
            }
        } else {
            d = Element.collectTextNodesIgnoreClass(f, "informal")
        }
        var c = this.getTokenBounds();
        if (c[0] != -1) {
            var e = this.element.value.substr(0, c[0]);
            var b = this.element.value.substr(c[0]).match(/^\s+/);
            if (b) {
                e += b[0]
            }
            this.element.value = e + d + this.element.value.substr(c[1])
        } else {
            this.element.value = d
        }
        this.oldElementValue = this.element.value;
        this.element.focus();
        if (this.options.afterUpdateElement) {
            this.options.afterUpdateElement(this.element, f)
        }
    },
    updateChoices: function(c) {
        if (!this.changed && this.hasFocus) {
            this.update.innerHTML = c;
            Element.cleanWhitespace(this.update);
            Element.cleanWhitespace(this.update.down());
            if (this.update.firstChild && this.update.down().childNodes) {
                this.entryCount = this.update.down().childNodes.length;
                for (var a = 0; a < this.entryCount; a++) {
                    var b = this.getEntry(a);
                    b.autocompleteIndex = a;
                    this.addObservers(b)
                }
            } else {
                this.entryCount = 0
            }
            this.stopIndicator();
            this.index = 0;
            if (this.entryCount == 1 && this.options.autoSelect) {
                this.selectEntry();
                this.hide()
            } else {
                this.render()
            }
        }
    },
    addObservers: function(a) {
        Event.observe(a, "mouseover", this.onHover.bindAsEventListener(this));
        Event.observe(a, "click", this.onClick.bindAsEventListener(this))
    },
    onObserverEvent: function() {
        this.changed = false;
        this.tokenBounds = null;
        if (this.getToken().length >= this.options.minChars) {
            this.getUpdatedChoices()
        } else {
            this.active = false;
            this.hide()
        }
        this.oldElementValue = this.element.value
    },
    getToken: function() {
        var a = this.getTokenBounds();
        return this.element.value.substring(a[0], a[1]).strip()
    },
    getTokenBounds: function() {
        if (null != this.tokenBounds) {
            return this.tokenBounds
        }
        var e = this.element.value;
        if (e.strip().empty()) {
            return [ - 1, 0]
        }
        var f = arguments.callee.getFirstDifferencePos(e, this.oldElementValue);
        var h = (f == this.oldElementValue.length ? 1: 0);
        var d = -1,
        c = e.length;
        var g;
        for (var b = 0, a = this.options.tokens.length; b < a; ++b) {
            g = e.lastIndexOf(this.options.tokens[b], f + h - 1);
            if (g > d) {
                d = g
            }
            g = e.indexOf(this.options.tokens[b], f + h);
            if ( - 1 != g && g < c) {
                c = g
            }
        }
        return (this.tokenBounds = [d + 1, c])
    }
});
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(c, a) {
    var d = Math.min(c.length, a.length);
    for (var b = 0; b < d; ++b) {
        if (c[b] != a[b]) {
            return b
        }
    }
    return d
};
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
    initialize: function(c, d, b, a) {
        this.baseInitialize(c, d, a);
        this.options.asynchronous = true;
        this.options.onComplete = this.onComplete.bind(this);
        this.options.defaultParams = this.options.parameters || null;
        this.url = b
    },
    getUpdatedChoices: function() {
        this.startIndicator();
        var a = encodeURIComponent(this.options.paramName) + "=" + encodeURIComponent(this.getToken());
        this.options.parameters = this.options.callback ? this.options.callback(this.element, a) : a;
        if (this.options.defaultParams) {
            this.options.parameters += "&" + this.options.defaultParams
        }
        new Ajax.Request(this.url, this.options)
    },
    onComplete: function(a) {
        this.updateChoices(a.responseText)
    }
});
Autocompleter.Local = Class.create(Autocompleter.Base, {
    initialize: function(b, d, c, a) {
        this.baseInitialize(b, d, a);
        this.options.array = c
    },
    getUpdatedChoices: function() {
        this.updateChoices(this.options.selector(this))
    },
    setOptions: function(a) {
        this.options = Object.extend({
            choices: 10,
            partialSearch: true,
            partialChars: 2,
            ignoreCase: true,
            fullSearch: false,
            selector: function(b) {
                var d = [];
                var c = [];
                var h = b.getToken();
                var g = 0;
                for (var e = 0; e < b.options.array.length && d.length < b.options.choices; e++) {
                    var f = b.options.array[e];
                    var j = b.options.ignoreCase ? f.toLowerCase().indexOf(h.toLowerCase()) : f.indexOf(h);
                    while (j != -1) {
                        if (j == 0 && f.length != h.length) {
                            d.push("<li><strong>" + f.substr(0, h.length) + "</strong>" + f.substr(h.length) + "</li>");
                            break
                        } else {
                            if (h.length >= b.options.partialChars && b.options.partialSearch && j != -1) {
                                if (b.options.fullSearch || /\s/.test(f.substr(j - 1, 1))) {
                                    c.push("<li>" + f.substr(0, j) + "<strong>" + f.substr(j, h.length) + "</strong>" + f.substr(j + h.length) + "</li>");
                                    break
                                }
                            }
                        }
                        j = b.options.ignoreCase ? f.toLowerCase().indexOf(h.toLowerCase(), j + 1) : f.indexOf(h, j + 1)
                    }
                }
                if (c.length) {
                    d = d.concat(c.slice(0, b.options.choices - d.length))
                }
                return "<ul>" + d.join("") + "</ul>"
            }
        },
        a || {})
    }
});
Field.scrollFreeActivate = function(a) {
    setTimeout(function() {
        Field.activate(a)
    },
    1)
};
Ajax.InPlaceEditor = Class.create({
    initialize: function(c, b, a) {
        this.url = b;
        this.element = c = $(c);
        this.prepareOptions();
        this._controls = {};
        arguments.callee.dealWithDeprecatedOptions(a);
        Object.extend(this.options, a || {});
        if (!this.options.formId && this.element.id) {
            this.options.formId = this.element.id + "-inplaceeditor";
            if ($(this.options.formId)) {
                this.options.formId = ""
            }
        }
        if (this.options.externalControl) {
            this.options.externalControl = $(this.options.externalControl)
        }
        if (!this.options.externalControl) {
            this.options.externalControlOnly = false
        }
        this._originalBackground = this.element.getStyle("background-color") || "transparent";
        this.element.title = this.options.clickToEditText;
        this._boundCancelHandler = this.handleFormCancellation.bind(this);
        this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
        this._boundFailureHandler = this.handleAJAXFailure.bind(this);
        this._boundSubmitHandler = this.handleFormSubmission.bind(this);
        this._boundWrapperHandler = this.wrapUp.bind(this);
        this.registerListeners()
    },
    checkForEscapeOrReturn: function(a) {
        if (!this._editing || a.ctrlKey || a.altKey || a.shiftKey) {
            return
        }
        if (Event.KEY_ESC == a.keyCode) {
            this.handleFormCancellation(a)
        } else {
            if (Event.KEY_RETURN == a.keyCode) {
                this.handleFormSubmission(a)
            }
        }
    },
    createControl: function(g, c, b) {
        var e = this.options[g + "Control"];
        var f = this.options[g + "Text"];
        if ("button" == e) {
            var a = document.createElement("input");
            a.type = "submit";
            a.value = f;
            a.className = "editor_" + g + "_button";
            if ("cancel" == g) {
                a.onclick = this._boundCancelHandler
            }
            this._form.appendChild(a);
            this._controls[g] = a
        } else {
            if ("link" == e) {
                var d = document.createElement("a");
                d.href = "#";
                d.appendChild(document.createTextNode(f));
                d.onclick = "cancel" == g ? this._boundCancelHandler: this._boundSubmitHandler;
                d.className = "editor_" + g + "_link";
                if (b) {
                    d.className += " " + b
                }
                this._form.appendChild(d);
                this._controls[g] = d
            }
        }
    },
    createEditField: function() {
        var c = (this.options.loadTextURL ? this.options.loadingText: this.getText());
        var b;
        if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
            b = document.createElement("input");
            b.type = "text";
            var a = this.options.size || this.options.cols || 0;
            if (0 < a) {
                b.size = a
            }
        } else {
            b = document.createElement("textarea");
            b.rows = (1 >= this.options.rows ? this.options.autoRows: this.options.rows);
            b.cols = this.options.cols || 40
        }
        b.name = this.options.paramName;
        b.value = c;
        b.className = "editor_field";
        if (this.options.submitOnBlur) {
            b.onblur = this._boundSubmitHandler
        }
        this._controls.editor = b;
        if (this.options.loadTextURL) {
            this.loadExternalText()
        }
        this._form.appendChild(this._controls.editor)
    },
    createForm: function() {
        var b = this;
        function a(d, e) {
            var c = b.options["text" + d + "Controls"];
            if (!c || e === false) {
                return
            }
            b._form.appendChild(document.createTextNode(c))
        }
        this._form = $(document.createElement("form"));
        this._form.id = this.options.formId;
        this._form.addClassName(this.options.formClassName);
        this._form.onsubmit = this._boundSubmitHandler;
        this.createEditField();
        if ("textarea" == this._controls.editor.tagName.toLowerCase()) {
            this._form.appendChild(document.createElement("br"))
        }
        if (this.options.onFormCustomization) {
            this.options.onFormCustomization(this, this._form)
        }
        a("Before", this.options.okControl || this.options.cancelControl);
        this.createControl("ok", this._boundSubmitHandler);
        a("Between", this.options.okControl && this.options.cancelControl);
        this.createControl("cancel", this._boundCancelHandler, "editor_cancel");
        a("After", this.options.okControl || this.options.cancelControl)
    },
    destroy: function() {
        if (this._oldInnerHTML) {
            this.element.innerHTML = this._oldInnerHTML
        }
        this.leaveEditMode();
        this.unregisterListeners()
    },
    enterEditMode: function(a) {
        if (this._saving || this._editing) {
            return
        }
        this._editing = true;
        this.triggerCallback("onEnterEditMode");
        if (this.options.externalControl) {
            this.options.externalControl.hide()
        }
        this.element.hide();
        this.createForm();
        this.element.parentNode.insertBefore(this._form, this.element);
        if (!this.options.loadTextURL) {
            this.postProcessEditField()
        }
        if (a) {
            Event.stop(a)
        }
    },
    enterHover: function(a) {
        if (this.options.hoverClassName) {
            this.element.addClassName(this.options.hoverClassName)
        }
        if (this._saving) {
            return
        }
        this.triggerCallback("onEnterHover")
    },
    getText: function() {
        return this.element.innerHTML.unescapeHTML()
    },
    handleAJAXFailure: function(a) {
        this.triggerCallback("onFailure", a);
        if (this._oldInnerHTML) {
            this.element.innerHTML = this._oldInnerHTML;
            this._oldInnerHTML = null
        }
    },
    handleFormCancellation: function(a) {
        this.wrapUp();
        if (a) {
            Event.stop(a)
        }
    },
    handleFormSubmission: function(d) {
        var b = this._form;
        var c = $F(this._controls.editor);
        this.prepareSubmission();
        var f = this.options.callback(b, c) || "";
        if (Object.isString(f)) {
            f = f.toQueryParams()
        }
        f.editorId = this.element.id;
        if (this.options.htmlResponse) {
            var a = Object.extend({
                evalScripts: true
            },
            this.options.ajaxOptions);
            Object.extend(a, {
                parameters: f,
                onComplete: this._boundWrapperHandler,
                onFailure: this._boundFailureHandler
            });
            new Ajax.Updater({
                success: this.element
            },
            this.url, a)
        } else {
            var a = Object.extend({
                method: "get"
            },
            this.options.ajaxOptions);
            Object.extend(a, {
                parameters: f,
                onComplete: this._boundWrapperHandler,
                onFailure: this._boundFailureHandler
            });
            new Ajax.Request(this.url, a)
        }
        if (d) {
            Event.stop(d)
        }
    },
    leaveEditMode: function() {
        this.element.removeClassName(this.options.savingClassName);
        this.removeForm();
        this.leaveHover();
        this.element.style.backgroundColor = this._originalBackground;
        this.element.show();
        if (this.options.externalControl) {
            this.options.externalControl.show()
        }
        this._saving = false;
        this._editing = false;
        this._oldInnerHTML = null;
        this.triggerCallback("onLeaveEditMode")
    },
    leaveHover: function(a) {
        if (this.options.hoverClassName) {
            this.element.removeClassName(this.options.hoverClassName)
        }
        if (this._saving) {
            return
        }
        this.triggerCallback("onLeaveHover")
    },
    loadExternalText: function() {
        this._form.addClassName(this.options.loadingClassName);
        this._controls.editor.disabled = true;
        var a = Object.extend({
            method: "get"
        },
        this.options.ajaxOptions);
        Object.extend(a, {
            parameters: "editorId=" + encodeURIComponent(this.element.id),
            onComplete: Prototype.emptyFunction,
            onSuccess: function(c) {
                this._form.removeClassName(this.options.loadingClassName);
                var b = c.responseText;
                if (this.options.stripLoadedTextTags) {
                    b = b.stripTags()
                }
                this._controls.editor.value = b;
                this._controls.editor.disabled = false;
                this.postProcessEditField()
            }.bind(this),
            onFailure: this._boundFailureHandler
        });
        new Ajax.Request(this.options.loadTextURL, a)
    },
    postProcessEditField: function() {
        var a = this.options.fieldPostCreation;
        if (a) {
            $(this._controls.editor)["focus" == a ? "focus": "activate"]()
        }
    },
    prepareOptions: function() {
        this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
        Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); [this._extraDefaultOptions].flatten().compact().each(function(a) {
            Object.extend(this.options, a)
        }.bind(this))
    },
    prepareSubmission: function() {
        this._saving = true;
        this.removeForm();
        this.leaveHover();
        this.showSaving()
    },
    registerListeners: function() {
        this._listeners = {};
        var a;
        $H(Ajax.InPlaceEditor.Listeners).each(function(b) {
            a = this[b.value].bind(this);
            this._listeners[b.key] = a;
            if (!this.options.externalControlOnly) {
                this.element.observe(b.key, a)
            }
            if (this.options.externalControl) {
                this.options.externalControl.observe(b.key, a)
            }
        }.bind(this))
    },
    removeForm: function() {
        if (!this._form) {
            return
        }
        this._form.remove();
        this._form = null;
        this._controls = {}
    },
    showSaving: function() {
        this._oldInnerHTML = this.element.innerHTML;
        this.element.innerHTML = this.options.savingText;
        this.element.addClassName(this.options.savingClassName);
        this.element.style.backgroundColor = this._originalBackground;
        this.element.show()
    },
    triggerCallback: function(b, a) {
        if ("function" == typeof this.options[b]) {
            this.options[b](this, a)
        }
    },
    unregisterListeners: function() {
        $H(this._listeners).each(function(a) {
            if (!this.options.externalControlOnly) {
                this.element.stopObserving(a.key, a.value)
            }
            if (this.options.externalControl) {
                this.options.externalControl.stopObserving(a.key, a.value)
            }
        }.bind(this))
    },
    wrapUp: function(a) {
        this.leaveEditMode();
        this._boundComplete(a, this.element)
    }
});
Object.extend(Ajax.InPlaceEditor.prototype, {
    dispose: Ajax.InPlaceEditor.prototype.destroy
});
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
    initialize: function($super, c, b, a) {
        this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
        $super(c, b, a)
    },
    createEditField: function() {
        var a = document.createElement("select");
        a.name = this.options.paramName;
        a.size = 1;
        this._controls.editor = a;
        this._collection = this.options.collection || [];
        if (this.options.loadCollectionURL) {
            this.loadCollection()
        } else {
            this.checkForExternalText()
        }
        this._form.appendChild(this._controls.editor)
    },
    loadCollection: function() {
        this._form.addClassName(this.options.loadingClassName);
        this.showLoadingText(this.options.loadingCollectionText);
        var options = Object.extend({
            method: "get"
        },
        this.options.ajaxOptions);
        Object.extend(options, {
            parameters: "editorId=" + encodeURIComponent(this.element.id),
            onComplete: Prototype.emptyFunction,
            onSuccess: function(transport) {
                var js = transport.responseText.strip();
                if (!/^\[.*\]$/.test(js)) {
                    throw ("Server returned an invalid collection representation.")
                }
                this._collection = eval(js);
                this.checkForExternalText()
            }.bind(this),
            onFailure: this.onFailure
        });
        new Ajax.Request(this.options.loadCollectionURL, options)
    },
    showLoadingText: function(b) {
        this._controls.editor.disabled = true;
        var a = this._controls.editor.firstChild;
        if (!a) {
            a = document.createElement("option");
            a.value = "";
            this._controls.editor.appendChild(a);
            a.selected = true
        }
        a.update((b || "").stripScripts().stripTags())
    },
    checkForExternalText: function() {
        this._text = this.getText();
        if (this.options.loadTextURL) {
            this.loadExternalText()
        } else {
            this.buildOptionList()
        }
    },
    loadExternalText: function() {
        this.showLoadingText(this.options.loadingText);
        var a = Object.extend({
            method: "get"
        },
        this.options.ajaxOptions);
        Object.extend(a, {
            parameters: "editorId=" + encodeURIComponent(this.element.id),
            onComplete: Prototype.emptyFunction,
            onSuccess: function(b) {
                this._text = b.responseText.strip();
                this.buildOptionList()
            }.bind(this),
            onFailure: this.onFailure
        });
        new Ajax.Request(this.options.loadTextURL, a)
    },
    buildOptionList: function() {
        this._form.removeClassName(this.options.loadingClassName);
        this._collection = this._collection.map(function(d) {
            return 2 === d.length ? d: [d, d].flatten()
        });
        var b = ("value" in this.options) ? this.options.value: this._text;
        var a = this._collection.any(function(d) {
            return d[0] == b
        }.bind(this));
        this._controls.editor.update("");
        var c;
        this._collection.each(function(e, d) {
            c = document.createElement("option");
            c.value = e[0];
            c.selected = a ? e[0] == b: 0 == d;
            c.appendChild(document.createTextNode(e[1]));
            this._controls.editor.appendChild(c)
        }.bind(this));
        this._controls.editor.disabled = false;
        Field.scrollFreeActivate(this._controls.editor)
    }
});
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(a) {
    if (!a) {
        return
    }
    function b(c, d) {
        if (c in a || d === undefined) {
            return
        }
        a[c] = d
    }
    b("cancelControl", (a.cancelLink ? "link": (a.cancelButton ? "button": a.cancelLink == a.cancelButton == false ? false: undefined)));
    b("okControl", (a.okLink ? "link": (a.okButton ? "button": a.okLink == a.okButton == false ? false: undefined)));
    b("highlightColor", a.highlightcolor);
    b("highlightEndColor", a.highlightendcolor)
};
Object.extend(Ajax.InPlaceEditor, {
    DefaultOptions: {
        ajaxOptions: {},
        autoRows: 3,
        cancelControl: "link",
        cancelText: "cancel",
        clickToEditText: "Click to edit",
        externalControl: null,
        externalControlOnly: false,
        fieldPostCreation: "activate",
        formClassName: "inplaceeditor-form",
        formId: null,
        highlightColor: "#ffff99",
        highlightEndColor: "#ffffff",
        hoverClassName: "",
        htmlResponse: true,
        loadingClassName: "inplaceeditor-loading",
        loadingText: "Loading...",
        okControl: "button",
        okText: "ok",
        paramName: "value",
        rows: 1,
        savingClassName: "inplaceeditor-saving",
        savingText: "Saving...",
        size: 0,
        stripLoadedTextTags: false,
        submitOnBlur: false,
        textAfterControls: "",
        textBeforeControls: "",
        textBetweenControls: ""
    },
    DefaultCallbacks: {
        callback: function(a) {
            return Form.serialize(a)
        },
        onComplete: function(b, a) {
            new Effect.Highlight(a, {
                startcolor: this.options.highlightColor,
                keepBackgroundImage: true
            })
        },
        onEnterEditMode: null,
        onEnterHover: function(a) {
            a.element.style.backgroundColor = a.options.highlightColor;
            if (a._effect) {
                a._effect.cancel()
            }
        },
        onFailure: function(b, a) {
            alert("Error communication with the server: " + b.responseText.stripTags())
        },
        onFormCustomization: null,
        onLeaveEditMode: null,
        onLeaveHover: function(a) {
            a._effect = new Effect.Highlight(a.element, {
                startcolor: a.options.highlightColor,
                endcolor: a.options.highlightEndColor,
                restorecolor: a._originalBackground,
                keepBackgroundImage: true
            })
        }
    },
    Listeners: {
        click: "enterEditMode",
        keydown: "checkForEscapeOrReturn",
        mouseover: "enterHover",
        mouseout: "leaveHover"
    }
});
Ajax.InPlaceCollectionEditor.DefaultOptions = {
    loadingCollectionText: "Loading options..."
};
Form.Element.DelayedObserver = Class.create({
    initialize: function(b, a, c) {
        this.delay = a || 0.5;
        this.element = $(b);
        this.callback = c;
        this.timer = null;
        this.lastValue = $F(this.element);
        Event.observe(this.element, "keyup", this.delayedListener.bindAsEventListener(this))
    },
    delayedListener: function(a) {
        if (this.lastValue == $F(this.element)) {
            return
        }
        if (this.timer) {
            clearTimeout(this.timer)
        }
        this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
        this.lastValue = $F(this.element)
    },
    onTimerEvent: function() {
        this.timer = null;
        this.callback(this.element, $F(this.element))
    }
});
if (!Control) {
    var Control = {}
}
Control.Slider = Class.create({
    initialize: function(d, a, b) {
        var c = this;
        if (Object.isArray(d)) {
            this.handles = d.collect(function(f) {
                return $(f)
            })
        } else {
            this.handles = [$(d)]
        }
        this.track = $(a);
        this.options = b || {};
        this.axis = this.options.axis || "horizontal";
        this.increment = this.options.increment || 1;
        this.step = parseInt(this.options.step || "1");
        this.range = this.options.range || $R(0, 1);
        this.value = 0;
        this.values = this.handles.map(function() {
            return 0
        });
        this.spans = this.options.spans ? this.options.spans.map(function(e) {
            return $(e)
        }) : false;
        this.options.startSpan = $(this.options.startSpan || null);
        this.options.endSpan = $(this.options.endSpan || null);
        this.restricted = this.options.restricted || false;
        this.maximum = this.options.maximum || this.range.end;
        this.minimum = this.options.minimum || this.range.start;
        this.alignX = parseInt(this.options.alignX || "0");
        this.alignY = parseInt(this.options.alignY || "0");
        this.trackLength = this.maximumOffset() - this.minimumOffset();
        this.handleLength = this.isVertical() ? (this.handles[0].offsetHeight != 0 ? this.handles[0].offsetHeight: this.handles[0].style.height.replace(/px$/, "")) : (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth: this.handles[0].style.width.replace(/px$/, ""));
        this.active = false;
        this.dragging = false;
        this.disabled = false;
        if (this.options.disabled) {
            this.setDisabled()
        }
        this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
        if (this.allowedValues) {
            this.minimum = this.allowedValues.min();
            this.maximum = this.allowedValues.max()
        }
        this.eventMouseDown = this.startDrag.bindAsEventListener(this);
        this.eventMouseUp = this.endDrag.bindAsEventListener(this);
        this.eventMouseMove = this.update.bindAsEventListener(this);
        this.handles.each(function(f, e) {
            e = c.handles.length - 1 - e;
            c.setValue(parseFloat((Object.isArray(c.options.sliderValue) ? c.options.sliderValue[e] : c.options.sliderValue) || c.range.start), e);
            f.makePositioned().observe("mousedown", c.eventMouseDown)
        });
        this.track.observe("mousedown", this.eventMouseDown);
        document.observe("mouseup", this.eventMouseUp);
        document.observe("mousemove", this.eventMouseMove);
        this.initialized = true
    },
    dispose: function() {
        var a = this;
        Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
        Event.stopObserving(document, "mouseup", this.eventMouseUp);
        Event.stopObserving(document, "mousemove", this.eventMouseMove);
        this.handles.each(function(b) {
            Event.stopObserving(b, "mousedown", a.eventMouseDown)
        })
    },
    setDisabled: function() {
        this.disabled = true
    },
    setEnabled: function() {
        this.disabled = false
    },
    getNearestValue: function(a) {
        if (this.allowedValues) {
            if (a >= this.allowedValues.max()) {
                return (this.allowedValues.max())
            }
            if (a <= this.allowedValues.min()) {
                return (this.allowedValues.min())
            }
            var c = Math.abs(this.allowedValues[0] - a);
            var b = this.allowedValues[0];
            this.allowedValues.each(function(d) {
                var e = Math.abs(d - a);
                if (e <= c) {
                    b = d;
                    c = e
                }
            });
            return b
        }
        if (a > this.range.end) {
            return this.range.end
        }
        if (a < this.range.start) {
            return this.range.start
        }
        return a
    },
    setValue: function(b, a) {
        if (!this.active) {
            this.activeHandleIdx = a || 0;
            this.activeHandle = this.handles[this.activeHandleIdx];
            this.updateStyles()
        }
        a = a || this.activeHandleIdx || 0;
        if (this.initialized && this.restricted) {
            if ((a > 0) && (b < this.values[a - 1])) {
                b = this.values[a - 1]
            }
            if ((a < (this.handles.length - 1)) && (b > this.values[a + 1])) {
                b = this.values[a + 1]
            }
        }
        b = this.getNearestValue(b);
        this.values[a] = b;
        this.value = this.values[0];
        this.handles[a].style[this.isVertical() ? "top": "left"] = this.translateToPx(b);
        this.drawSpans();
        if (!this.dragging || !this.event) {
            this.updateFinished()
        }
    },
    setValueBy: function(b, a) {
        this.setValue(this.values[a || this.activeHandleIdx || 0] + b, a || this.activeHandleIdx || 0)
    },
    translateToPx: function(a) {
        return Math.round(((this.trackLength - this.handleLength) / (this.range.end - this.range.start)) * (a - this.range.start)) + "px"
    },
    translateToValue: function(a) {
        return ((a / (this.trackLength - this.handleLength) * (this.range.end - this.range.start)) + this.range.start)
    },
    getRange: function(b) {
        var a = this.values.sortBy(Prototype.K);
        b = b || 0;
        return $R(a[b], a[b + 1])
    },
    minimumOffset: function() {
        return (this.isVertical() ? this.alignY: this.alignX)
    },
    maximumOffset: function() {
        return (this.isVertical() ? (this.track.offsetHeight != 0 ? this.track.offsetHeight: this.track.style.height.replace(/px$/, "")) - this.alignY: (this.track.offsetWidth != 0 ? this.track.offsetWidth: this.track.style.width.replace(/px$/, "")) - this.alignX)
    },
    isVertical: function() {
        return (this.axis == "vertical")
    },
    drawSpans: function() {
        var a = this;
        if (this.spans) {
            $R(0, this.spans.length - 1).each(function(b) {
                a.setSpan(a.spans[b], a.getRange(b))
            })
        }
        if (this.options.startSpan) {
            this.setSpan(this.options.startSpan, $R(0, this.values.length > 1 ? this.getRange(0).min() : this.value))
        }
        if (this.options.endSpan) {
            this.setSpan(this.options.endSpan, $R(this.values.length > 1 ? this.getRange(this.spans.length - 1).max() : this.value, this.maximum))
        }
    },
    setSpan: function(b, a) {
        if (this.isVertical()) {
            b.style.top = this.translateToPx(a.start);
            b.style.height = this.translateToPx(a.end - a.start + this.range.start)
        } else {
            b.style.left = this.translateToPx(a.start);
            b.style.width = this.translateToPx(a.end - a.start + this.range.start)
        }
    },
    updateStyles: function() {
        this.handles.each(function(a) {
            Element.removeClassName(a, "selected")
        });
        Element.addClassName(this.activeHandle, "selected")
    },
    startDrag: function(c) {
        if (Event.isLeftClick(c)) {
            if (!this.disabled) {
                this.active = true;
                var d = Event.element(c);
                var e = [Event.pointerX(c), Event.pointerY(c)];
                var a = d;
                if (a == this.track) {
                    var b = this.track.cumulativeOffset();
                    this.event = c;
                    this.setValue(this.translateToValue((this.isVertical() ? e[1] - b[1] : e[0] - b[0]) - (this.handleLength / 2)));
                    var b = this.activeHandle.cumulativeOffset();
                    this.offsetX = (e[0] - b[0]);
                    this.offsetY = (e[1] - b[1])
                } else {
                    while ((this.handles.indexOf(d) == -1) && d.parentNode) {
                        d = d.parentNode
                    }
                    if (this.handles.indexOf(d) != -1) {
                        this.activeHandle = d;
                        this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
                        this.updateStyles();
                        var b = this.activeHandle.cumulativeOffset();
                        this.offsetX = (e[0] - b[0]);
                        this.offsetY = (e[1] - b[1])
                    }
                }
            }
            Event.stop(c)
        }
    },
    update: function(a) {
        if (this.active) {
            if (!this.dragging) {
                this.dragging = true
            }
            this.draw(a);
            if (Prototype.Browser.WebKit) {
                window.scrollBy(0, 0)
            }
            Event.stop(a)
        }
    },
    draw: function(b) {
        var c = [Event.pointerX(b), Event.pointerY(b)];
        var a = this.track.cumulativeOffset();
        c[0] -= this.offsetX + a[0];
        c[1] -= this.offsetY + a[1];
        this.event = b;
        this.setValue(this.translateToValue(this.isVertical() ? c[1] : c[0]));
        if (this.initialized && this.options.onSlide) {
            this.options.onSlide(this.values.length > 1 ? this.values: this.value, this)
        }
    },
    endDrag: function(a) {
        if (this.active && this.dragging) {
            this.finishDrag(a, true);
            Event.stop(a)
        }
        this.active = false;
        this.dragging = false
    },
    finishDrag: function(a, b) {
        this.active = false;
        this.dragging = false;
        this.updateFinished()
    },
    updateFinished: function() {
        if (this.initialized && this.options.onChange) {
            this.options.onChange(this.values.length > 1 ? this.values: this.value, this)
        }
        this.event = null
    }
});
Sound = {
    tracks: {},
    _enabled: true,
    template: new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
    enable: function() {
        Sound._enabled = true
    },
    disable: function() {
        Sound._enabled = false
    },
    play: function(b) {
        if (!Sound._enabled) {
            return
        }
        var a = Object.extend({
            track: "global",
            url: b,
            replace: false
        },
        arguments[1] || {});
        if (a.replace && this.tracks[a.track]) {
            $R(0, this.tracks[a.track].id).each(function(d) {
                var c = $("sound_" + a.track + "_" + d);
                c.Stop && c.Stop();
                c.remove()
            });
            this.tracks[a.track] = null
        }
        if (!this.tracks[a.track]) {
            this.tracks[a.track] = {
                id: 0
            }
        } else {
            this.tracks[a.track].id++
        }
        a.id = this.tracks[a.track].id;
        $$("body")[0].insert(Prototype.Browser.IE ? new Element("bgsound", {
            id: "sound_" + a.track + "_" + a.id,
            src: a.url,
            loop: 1,
            autostart: true
        }) : Sound.template.evaluate(a))
    }
};
if (Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0) {
    if (navigator.plugins && $A(navigator.plugins).detect(function(a) {
        return a.name.indexOf("QuickTime") != -1
    })) {
        Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
    } else {
        if (navigator.plugins && $A(navigator.plugins).detect(function(a) {
            return a.name.indexOf("Windows Media") != -1
        })) {
            Sound.template = new Template('<object id="sound_#{track}_#{id}" type="application/x-mplayer2" data="#{url}"></object>')
        } else {
            if (navigator.plugins && $A(navigator.plugins).detect(function(a) {
                return a.name.indexOf("RealPlayer") != -1
            })) {
                Sound.template = new Template('<embed type="audio/x-pn-realaudio-plugin" style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>')
            } else {
                Sound.play = function() {}
            }
        }
    }
};
