//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006-2007 Valerio Proietti, <http://mad4milk.net>, MIT Style License.

var MooTools = {
    "version": "1.2b1",
    "build": "1.2b1"
};
var Native = function(J){
    J = J ||
    {};
    var F = J.afterImplement ||
    function(){
    };
    var G = J.generics;
    G = (G !== false);
    var H = J.legacy;
    var E = J.initialize;
    var B = J.protect;
    var A = J.name;
    var C = E || H;
    C.constructor = Native;
    C.$family = {
        name: "native"
    };
    if (H && E) {
        C.prototype = H.prototype;
    }
    C.prototype.constructor = C;
    if (A) {
        var D = A.toLowerCase();
        C.prototype.$family = {
            name: D
        };
        Native.typize(C, D);
    }
    var I = function(M, K, N, L){
        if (!B || L || !M.prototype[K]) {
            M.prototype[K] = N;
        }
        if (G) {
            Native.genericize(M, K, B);
        }
        F.call(M, K, N);
        return M;
    };
    C.implement = function(L, K, N){
        if (typeof L == "string") {
            return I(this, L, K, N);
        }
        for (var M in L) {
            I(this, M, L[M], K);
        }
        return this;
    };
    C.alias = function(K, M, L){
        K = this.prototype[K];
        if (K) {
            I(this, M, K, L);
        }
        return this;
    };
    return C;
};
Native.implement = function(D, C){
    for (var B = 0, A = D.length; B < A; B++) {
        D[B].implement(C);
    }
};
Native.genericize = function(B, C, A){
    if ((!A || !B[C]) && typeof B.prototype[C] == "function") {
        B[C] = function(){
            var D = Array.prototype.slice.call(arguments);
            return B.prototype[C].apply(D.shift(), D);
        };
    }
};
Native.typize = function(A, B){
    if (!A.type) {
        A.type = function(C){
            return ($type(C) === B);
        };
    }
};
(function(B){
    for (var A in B) {
        Native.typize(B[A], A.toLowerCase());
    }
})({
    "Boolean": Boolean,
    "Native": Native,
    "Object": Object
});
(function(B){
    for (var A in B) {
        new Native({
            name: A,
            initialize: B[A],
            protect: true
        });
    }
})({
    "String": String,
    "Function": Function,
    "Number": Number,
    "Array": Array,
    "RegExp": RegExp,
    "Date": Date
});
(function(C, B){
    for (var D = 0, A = B.length; D < A; D++) {
        Native.genericize(C, B[D], true);
    }
    return arguments.callee;
})(Array, ["pop", "push", "reverse", "shift", "sort", "splice", "unshift", "concat", "join", "slice", "toString", "valueOf", "indexOf", "lastIndexOf"])(String, ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"]);
function $chk(A){
    return !!(A || A === 0);
}

function $clear(A){
    clearTimeout(A);
    clearInterval(A);
    return null;
}

function $defined(A){
    return (A != undefined);
}

function $empty(){
}

function $arguments(A){
    return function(){
        return arguments[A];
    };
}

function $lambda(A){
    return (typeof A == "function") ? A : function(){
        return A;
    };
}

function $extend(C, A){
    for (var B in (A ||
    {})) {
		//try{
        C[B] = A[B];
		//}
		//catch(err){
		//	return C;
		//}
    }
    return C;
}

function $merge(){
    var E = {};
    for (var D = 0, A = arguments.length; D < A; D++) {
        for (var C in arguments[D]) {
            var B = arguments[D][C];
            var F = E[C];
            if (F && $type(B) == "object" && $type(F) == "object") {
                E[C] = $merge(F, B);
            }
            else {
                E[C] = B;
            }
        }
    }
    return E;
}

function $pick(){
    for (var B = 0, A = arguments.length; B < A; B++) {
        if ($defined(arguments[B])) {
            return arguments[B];
        }
    }
    return null;
}

function $random(B, A){
    return Math.floor(Math.random() * (A - B + 1) + B);
}

function $splat(B){
    var A = $type(B);
    return (A) ? ((A != "array" && A != "arguments") ? [B] : B) : [];
}

var $time = Date.now ||
function(){
    return new Date().getTime();
};
function $try(B, D, A){
    try {
        return B.apply(D, $splat(A));
    } 
    catch (C) {
        return false;
    }
}

function $type(A){
    if (A == undefined) {
        return false;
    }
    if (A.$family) {
        return (A.$family.name == "number" && !isFinite(A)) ? false : A.$family.name;
    }
    if (A.nodeName) {
        switch (A.nodeType) {
            case 1:
                return "element";
            case 3:
                return (/\S/).test(A.nodeValue) ? "textnode" : "whitespace";
        }
    }
    else {
        if (typeof A.length == "number") {
            return (A.callee) ? "arguments" : "collection";
        }
    }
    return typeof A;
}

var Hash = new Native({
    name: "Hash",
    initialize: function(A){
        if ($type(A) == "hash") {
            return $merge(A);
        }
        for (var B in A) {
            if (!this[B]) {
                this[B] = A[B];
            }
        }
        return this;
    }
});
Hash.implement({
    forEach: function(B, C){
        for (var A in this) {
            if (this.hasOwnProperty(A)) {
                B.call(C, this[A], A, this);
            }
        }
    }
});
Hash.alias("forEach", "each");
function $H(A){
    return new Hash(A);
}

Array.implement({
    forEach: function(C, D){
        for (var B = 0, A = this.length; B < A; B++) {
            C.call(D, this[B], B, this);
        }
    }
});
Array.alias("forEach", "each");
function $A(C){
    if ($type(C) == "collection") {
        var D = [];
        for (var B = 0, A = C.length; B < A; B++) {
            D[B] = C[B];
        }
        return D;
    }
    return Array.prototype.slice.call(C);
}

function $each(C, B, D){
    var A = $type(C);
    ((A == "arguments" || A == "collection" || A == "array") ? Array : Hash).each(C, B, D);
}

$A = function(D, F, C){
    if (Browser.Engine.trident && $type(D) == "collection") {
        F = F || 0;
        if (F < 0) {
            F = D.length + F;
        }
        C = C || (D.length - F);
        var E = [];
        for (var B = 0; B < C; B++) {
            E[B] = D[F++];
        }
        return E;
    }
    F = (F || 0) + ((F < 0) ? D.length : 0);
    var A = ((!$chk(C)) ? D.length : C) + F;
    return Array.prototype.slice.call(D, F, A);
};
(function(){
    var B = [Array, Function, String, RegExp, Number];
    for (var C = 0, A = B.length; C < A; C++) {
        B[C].extend = B[C].implement;
    }
})();
var Browser = new Hash({
    Engine: {
        "name": "unknown",
        "version": ""
    },
    Platform: {
        "name": (navigator.platform.match(/mac|win|linux|nix/i) || ["other"])[0].toLowerCase()
    },
    Features: {
        "xhr": !!(window.XMLHttpRequest),
        "xpath": !!(document.evaluate)
    }
});
if (window.opera) {
    Browser.Engine.name = "presto";
}
else {
    if (window.ActiveXObject) {
        Browser.Engine = {
            "name": "trident",
            "version": (Browser.Features.xhr) ? 5 : 4
        };
    }
    else {
        if (!navigator.taintEnabled) {
            Browser.Engine = {
                "name": "webkit",
                "version": (Browser.Features.xpath) ? 420 : 419
            };
        }
        else {
            if (document.getBoxObjectFor != null) {
                Browser.Engine.name = "gecko";
            }
        }
    }
}
Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true;
Browser.Platform[Browser.Platform.name] = true;
function $exec(B){
    if (window.execScript) {
        window.execScript(B);
    }
    else {
        var A = document.createElement("script");
        A.setAttribute("type", "text/javascript");
        A.text = B;
        document.head.appendChild(A);
        document.head.removeChild(A);
    }
    return B;
}

Native.UID = 0;
var Window = new Native({
    name: "Window",
    legacy: window.Window,
    initialize: function(A){
        if (!A.Element) {
            A.Element = $empty;
            if (Browser.Engine.webkit) {
                A.document.createElement("iframe");
            }
            A.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};
        }
        A.uid = Native.UID++;
        return $extend(A, Window.Prototype);
    },
    afterImplement: function(B, A){
        window[B] = Window.Prototype[B] = A;
    }
});
Window.Prototype = {
    $family: {
        name: "window"
    }
};
new Window(window);
var Document = new Native({
    name: "Document",
    legacy: window.Document,
    initialize: function(A){
        A.head = A.getElementsByTagName("head")[0];
        A.html = A.getElementsByTagName("html")[0];
        A.window = A.defaultView || A.parentWindow;
        if (Browser.Engine.trident4) {
            $try(function(){
                A.execCommand("BackgroundImageCache", false, true);
            });
        }
        A.uid = Native.UID++;
        return $extend(A, Document.Prototype);
    },
    afterImplement: function(B, A){
        document[B] = Document.Prototype[B] = A;
    }
});
Document.Prototype = {
    $family: {
        name: "document"
    }
};
new Document(document);
window.extend = document.extend = function(A){
    for (var B in A) {
        this[B] = A[B];
    }
};
window.extend(Browser.Engine);
window.ie = window.trident;
window.ie6 = window.trident4;
window.ie7 = window.trident5;
Array.implement({
    every: function(C, D){
        for (var B = 0, A = this.length; B < A; B++) {
            if (!C.call(D, this[B], B, this)) {
                return false;
            }
        }
        return true;
    },
    filter: function(D, E){
        var C = [];
        for (var B = 0, A = this.length; B < A; B++) {
            if (D.call(E, this[B], B, this)) {
                C.push(this[B]);
            }
        }
        return C;
    },
    indexOf: function(C, D){
        var A = this.length;
        for (var B = (D < 0) ? Math.max(0, A + D) : D || 0; B < A; B++) {
            if (this[B] === C) {
                return B;
            }
        }
        return -1;
    },
    map: function(D, E){
        var C = [];
        for (var B = 0, A = this.length; B < A; B++) {
            C[B] = D.call(E, this[B], B, this);
        }
        return C;
    },
    some: function(C, D){
        for (var B = 0, A = this.length; B < A; B++) {
            if (C.call(D, this[B], B, this)) {
                return true;
            }
        }
        return false;
    },
    associate: function(C){
        var D = {}, B = Math.min(this.length, C.length);
        for (var A = 0; A < B; A++) {
            D[C[A]] = this[A];
        }
        return D;
    },
    link: function(C){
        var A = {};
        for (var E = 0, B = this.length; E < B; E++) {
            for (var D in C) {
                if (C[D](this[E])) {
                    A[D] = this[E];
                    delete C[D];
                    break;
                }
            }
        }
        return A;
    },
    contains: function(A, B){
        return this.indexOf(A, B) != -1;
    },
    extend: function(C){
        for (var B = 0, A = C.length; B < A; B++) {
            this.push(C[B]);
        }
        return this;
    },
    getLast: function(){
        return (this.length) ? this[this.length - 1] : null;
    },
    getRandom: function(){
        return (this.length) ? this[$random(0, this.length - 1)] : null;
    },
    include: function(A){
        if (!this.contains(A)) {
            this.push(A);
        }
        return this;
    },
    merge: function(C){
        for (var B = 0, A = C.length; B < A; B++) {
            this.include(C[B]);
        }
        return this;
    },
    remove: function(B){
        for (var A = this.length; A--; A) {
            if (this[A] === B) {
                this.splice(A, 1);
            }
        }
        return this;
    },
    empty: function(){
        this.length = 0;
        return this;
    },
    flatten: function(){
        var D = [];
        for (var B = 0, A = this.length; B < A; B++) {
            var C = $type(this[B]);
            if (!C) {
                continue;
            }
            D = D.concat((C == "array" || C == "collection" || C == "arguments") ? Array.flatten(this[B]) : this[B]);
        }
        return D;
    },
    hexToRgb: function(C){
        if (this.length != 3) {
            return null;
        }
        var A = [];
        for (var B = 0; B < 3; B++) {
            A.push(((this[B].length == 1) ? this[B] + this[B] : this[B]).toInt(16));
        }
        return C ? A : "rgb(" + String(A) + ")";
    },
    rgbToHex: function(D){
        if (this.length < 3) {
            return null;
        }
        if (this.length == 4 && this[3] == 0 && !D) {
            return "transparent";
        }
        var B = [];
        for (var A = 0; A < 3; A++) {
            var C = (this[A] - 0).toString(16);
            B.push((C.length == 1) ? "0" + C : C);
        }
        return D ? B : "#" + B.join("");
    }
});
Array.implement({
    copy: function(B, A){
        return $A(this, B, A);
    }
});
Function.implement({
    extend: function(A){
        for (var B in A) {
            this[B] = A[B];
        }
    },
    create: function(B){
        var A = this;
        B = B ||
        {};
        return function(D){
            var C = B.arguments;
            C = $defined(C) ? $splat(C) : Array.slice(arguments, (B.event) ? 1 : 0);
            if (B.event) {
                C =[D||window.event]   .extend(C);
            }
            var E = function(){
                return A.apply(B.bind || null, C);
            };
            if (B.delay) {
                return setTimeout(E, B.delay);
            }
            if (B.periodical) {
                return setInterval(E, B.periodical);
            }
            if (B.attempt) {
                return $try(E);
            }
            return E();
        };
    },
    pass: function(A, B){
        return this.create({
            "arguments": A,
            "bind": B
        });
    },
    attempt: function(A, B){
        return this.create({
            "arguments": A,
            "bind": B,
            "attempt": true
        })();
    },
    bind: function(B, A){
        return this.create({
            "bind": B,
            "arguments": A
        });
    },
    bindWithEvent: function(B, A){
        return this.create({
            "bind": B,
            "event": true,
            "arguments": A
        });
    },
    delay: function(B, C, A){
        return this.create({
            "delay": B,
            "bind": C,
            "arguments": A
        })();
    },
    periodical: function(A, C, B){
        return this.create({
            "periodical": A,
            "bind": C,
            "arguments": B
        })();
    },
    run: function(A, B){
        return this.apply(B, $splat(A));
    }
});
Function.extend({
    bindAsEventListener: function(B, A){
        return this.create({
            "bind": B,
            "event": true,
            "arguments": A
        });
    }
});
Function.empty = $empty;
Number.implement({
    limit: function(B, A){
        return Math.min(A, Math.max(B, this));
    },
    round: function(A){
        A = Math.pow(10, A || 0);
        return Math.round(this * A) / A;
    },
    times: function(B, C){
        for (var A = 0; A < this; A++) {
            B.call(C, A, this);
        }
    },
    toFloat: function(){
        return parseFloat(this);
    },
    toInt: function(A){
        return parseInt(this, A || 10);
    }
});
Number.alias("times", "each");
(function(B){
    var A = {};
    B.each(function(C){
        if (!Number[C]) {
            A[C] = function(){
                return Math[C].apply(null, [this].concat($A(arguments)));
            };
        }
    });
    Number.implement(A);
})(["abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "exp", "floor", "log", "max", "min", "pow", "sin", "sqrt", "tan"]);
String.implement({
    test: function(A, B){
        return (($type(A) == "string") ? new RegExp(A, B) : A).test(this);
    },
    contains: function(A, B){
        return (B) ? (B + this + B).indexOf(B + A + B) > -1 : this.indexOf(A) > -1;
    },
    trim: function(){
        return this.replace(/^\s+|\s+$/g, "");
    },
    clean: function(){
        return this.replace(/\s{2,}/g, " ").trim();
    },
    camelCase: function(){
        return this.replace(/-\D/g, function(A){
            return A.charAt(1).toUpperCase();
        });
    },
    hyphenate: function(){
        return this.replace(/[A-Z]/g, function(A){
            return ("-" + A.charAt(0).toLowerCase());
        });
    },
    capitalize: function(){
        return this.replace(/\b[a-z]/g, function(A){
            return A.toUpperCase();
        });
    },
    escapeRegExp: function(){
        return this.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
    },
    toInt: function(A){
        return parseInt(this, A || 10);
    },
    toFloat: function(){
        return parseFloat(this);
    },
    hexToRgb: function(B){
        var A = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
        return (A) ? A.slice(1).hexToRgb(B) : null;
    },
    rgbToHex: function(B){
        var A = this.match(/\d{1,3}/g);
        return (A) ? A.rgbToHex(B) : null;
    },
    stripScripts: function(C){
        var A = "";
        var B = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
            A += arguments[1] + "\n";
            return "";
        });
        if (C && A) {
            $exec(A);
        }
        return B;
    }
});
Hash.implement({
    has: Object.prototype.hasOwnProperty,
    keyOf: function(B){
        for (var A in this) {
            if (this.hasOwnProperty(A) && this[A] === B) {
                return A;
            }
        }
        return null;
    },
    hasValue: function(A){
        return (Hash.keyOf(this, A) !== null);
    },
    extend: function(A){
        Hash.each(A, function(C, B){
            Hash.set(this, B, C);
        }, this);
        return this;
    },
    merge: function(A){
        Hash.each(A, function(C, B){
            Hash.include(this, B, C);
        }, this);
        return this;
    },
    remove: function(A){
        if (this.hasOwnProperty(A)) {
            delete this[A];
        }
        return this;
    },
    get: function(A){
        return (this.hasOwnProperty(A)) ? this[A] : null;
    },
    set: function(A, B){
        if (!this[A] || this.hasOwnProperty(A)) {
            this[A] = B;
        }
        return this;
    },
    empty: function(){
        Hash.each(this, function(B, A){
            delete this[A];
        }, this);
        return this;
    },
    include: function(B, C){
        var A = this[B];
        if (!$defined(A)) {
            this[B] = C;
        }
        return this;
    },
    map: function(B, C){
        var A = new Hash;
        Hash.each(this, function(E, D){
            A.set(D, B.call(C, E, D, this));
        }, this);
        return A;
    },
    filter: function(B, C){
        var A = new Hash;
        Hash.each(this, function(E, D){
            if (B.call(C, E, D, this)) {
                A.set(D, E);
            }
        }, this);
        return A;
    },
    every: function(B, C){
        for (var A in this) {
            if (this.hasOwnProperty(A) && !B.call(C, this[A], A)) {
                return false;
            }
        }
        return true;
    },
    some: function(B, C){
        for (var A in this) {
            if (this.hasOwnProperty(A) && B.call(C, this[A], A)) {
                return true;
            }
        }
        return false;
    },
    getClean: function(){
        var A = {};
        Hash.each(this, function(C, B){
            A[B] = C;
        });
        return A;
    },
    getKeys: function(){
        var A = [];
        Hash.each(this, function(C, B){
            A.push(B);
        });
        return A;
    },
    getValues: function(){
        var A = [];
        Hash.each(this, function(B){
            A.push(B);
        });
        return A;
    },
    toQueryString: function(){
        var A = [];
        Hash.each(this, function(C, B){
            $splat(C).each(function(D){
                A.push(B + "=" + encodeURIComponent(D));
            });
        });
        return A.join("&");
    }
});
Hash.alias("keyOf", "indexOf").alias("hasValue", "contains").alias("remove", "erase");
Hash.alias("getKeys", "keys").alias("getValues", "values").alias("has", "hasKey");
var Abstract = Hash;
var Class = new Native({
    name: "Class",
    initialize: function(B){
        B = B ||
        {};
        var A = function(){
            for (var D in this) {
                if ($type(this[D]) == "object") {
                    this[D] = $merge(this[D]);
                }
            }
            ["Implements", "Extends"].each(function(E){
                if (!this[E]) {
                    return;
                }
                Class[E](this, this[E]);
                delete this[E];
            }, this);
            this.constructor = A;
            var C = (arguments[0] !== $empty && this.initialize && $type(this.initialize) == "function") ? this.initialize.apply(this, arguments) : this;
            if (this.options && this.options.initialize) {
                this.options.initialize.call(this);
            }
            return C;
        };
        $extend(A, this);
        A.constructor = Class;
        A.prototype = B;
        return A;
    }
});
Class.implement({
    implement: function(){
        Class.Implements(this.prototype, Array.slice(arguments));
        return this;
    }
});
Class.Implements = function(A, B){
    $splat(B).each(function(C){
        $extend(A, ($type(C) == "class") ? new C($empty) : C);
    });
};
Class.Extends = function(C, A){
    A = new A($empty);
    for (var E in A) {
        var B = A[E];
        var D = C[E];
        C[E] = (function(G, H){
            if ($defined(H) && G != H) {
                var F = $type(H);
                if (F != $type(G)) {
                    return H;
                }
                switch (F) {
                    case "function":
                        return function(){
                            H.parent = this.parent = G.bind(this);
                            return H.apply(this, arguments);
                        };
                    case "object":
                        return $merge(G, H);
                }
            }
            return G;
        })(B, D);
    }
};
Class.prototype.extend = function(A){
    A.Extends = this;
    return new Class(A);
};
Class.empty = $empty;
var Chain = new Class({
    chain: function(){
        this.$chain = (this.$chain || []).extend(arguments);
        return this;
    },
    callChain: function(){
        if (this.$chain && this.$chain.length) {
            this.$chain.shift().apply(this, arguments);
        }
        return this;
    },
    clearChain: function(){
        if (this.$chain) {
            this.$chain.empty();
        }
        return this;
    }
});
var Events = new Class({
    addEvent: function(C, B, A){
        if (B != $empty) {
            this.$events = this.$events ||
            {};
            this.$events[C] = this.$events[C] || [];
            this.$events[C].include(B);
            if (A) {
                B.internal = true;
            }
        }
        return this;
    },
    addEvents: function(A){
        for (var B in A) {
            this.addEvent(B, A[B]);
        }
        return this;
    },
    fireEvent: function(C, B, A){
        if (!this.$events || !this.$events[C]) {
            return this;
        }
        this.$events[C].each(function(D){
            D.create({
                "bind": this,
                "delay": A,
                "arguments": B
            })();
        }, this);
        return this;
    },
    removeEvent: function(B, A){
        if (!this.$events) {
            return this;
        }
        if (this.$events && this.$events[B]) {
            if (!A.internal) {
                this.$events[B].remove(A);
            }
        }
        return this;
    },
    removeEvents: function(C){
        for (var D in this.$events) {
            if (C && C != D) {
                continue;
            }
            var B = this.$events[D];
            for (var A = B.length; A--; A) {
                this.removeEvent(D, B[A]);
            }
        }
        return this;
    }
});
var Options = new Class({
    setOptions: function(){
        this.options = $merge.run([this.options].extend(arguments));
        if (!this.addEvent) {
            return this;
        }
        for (var A in this.options) {
            if ($type(this.options[A]) != "function" || !(/^on[A-Z]/).test(A)) {
                continue;
            }
            this.addEvent(A, this.options[A]);
            delete this.options[A];
        }
        return this;
    }
});
var Element = new Native({
    name: "Element",
    legacy: window.Element,
    initialize: function(B){
        var D = Array.link(arguments, {
            "document": Document.type,
            "properties": Object.type
        });
        var A = D.properties ||
        {}, C = D.document || document;
        if ($type(B) == "string") {
            B = B.toLowerCase();
            if (Browser.Engine.trident && A) {
                ["name", "type", "checked"].each(function(E){
                    if (!A[E]) {
                        return;
                    }
                    B += " " + E + '="' + A[E] + '"';
                    if (E != "checked") {
                        delete A[E];
                    }
                });
                B = "<" + B + ">";
            }
            B = C.createElement(B);
        }
        B = $.element(B);
        return (!A || !B) ? B : B.set(A);
    },
    afterImplement: function(A, B){
        if (!Array[A]) {
            Elements.implement(A, Elements.multi(A));
        }
        Element.Prototype[A] = B;
    }
});
Element.Prototype = {
    $family: {
        name: "element"
    }
};
var TextNode = new Native({
    name: "TextNode",
    initialize: function(B, A){
        return $extend((A || document).createTextNode(B), this);
    }
});
var IFrame = new Native({
    name: "IFrame",
    generics: false,
    initialize: function(){
        Native.UID++;
        var E = Array.link(arguments, {
            properties: Object.type,
            iframe: $defined
        });
        var C = E.properties ||
        {};
        var B = $(E.iframe) || false;
        var D = C.onload || $empty;
        delete C.onload;
        C.id = C.name = $pick(C.id, C.name, B.id, B.name, "IFrame_" + Native.UID);
        ((B = B || new Element("iframe"))).set(C);
        var A = function(){
            var F = $try(function(){
                return B.contentWindow.location.host;
            });
            if (F && F == window.location.host) {
                B.window = B.contentWindow;
                var H = new Window(B.window);
                var G = new Document(B.window.document);
                $extend(H.Element.prototype, Element.Prototype);
            }
            D.call(B.contentWindow);
        };
        (!window.frames[C.id]) ? B.addListener("load", A) : A();
        return B;
    }
});
var Elements = new Native({
    initialize: function(F, B){
        B = $extend({
            ddup: true,
            cash: true
        }, B);
        F = F || [];
        if (B.ddup || B.cash) {
            var G = {};
            var E = [];
            for (var C = 0, A = F.length; C < A; C++) {
                var D = $.element(F[C], !B.cash);
                if (B.ddup) {
                    if (G[D.uid]) {
                        continue;
                    }
                    G[D.uid] = true;
                }
                E.push(D);
            }
            F = E;
        }
        return (B.cash) ? $extend(F, this) : F;
    }
});
Elements.implement({
    filterBy: function(A){
        if (!A) {
            return this;
        }
        return new Elements(this.filter(($type(A) == "string") ? function(B){
            return B.match(A);
        }
 : A));
    }
});
Elements.multi = function(A){
    return function(){
        var B = [];
        var F = true;
        for (var D = 0, C = this.length; D < C; D++) {
            var E = this[D][A].apply(this[D], arguments);
            B.push(E);
            if (F) {
                F = ($type(E) == "element");
            }
        }
        return (F) ? new Elements(B) : B;
    };
};
Window.implement({
    $: function(B, C){
        if (B && B.$attributes) {
            return B;
        }
        var A = $type(B);
        return ($[A]) ? $[A](B, C, this.document) : null;
    },
    $$: function(A){
        if (arguments.length == 1 && typeof A == "string") {
            return this.document.getElements(A);
        }
        var F = [];
        var C = Array.flatten(arguments);
        for (var D = 0, B = C.length; D < B; D++) {
            var E = C[D];
            switch ($type(E)) {
                case "element":
                    E = [E];
                    break;
                case "string":
                    E = this.document.getElements(E, true);
                    break;
                default:
                    E = false;
            }
            if (E) {
                F.extend(E);
            }
        }
        return new Elements(F);
    }
});
$.string = function(C, A, B){
    C = (B || document).getElementById(C);
    return (C) ? $.element(C, A) : null;
};
$.element = function(A, B){
    A.uid = A.uid || [Native.UID++];
    if (!B && Garbage.collect(A) && !A.$family) {
        $extend(A, Element.Prototype);
    }
    return A;
};
$.textnode = function(A, B){
    return (B || A.$family) ? A : $extend(A, TextNode.prototype);
};
$.window = $.document = $arguments(0);
Native.implement([Element, Document], {
    getElement: function(A, B){
        return $(this.getElements(A, true)[0] || null, B);
    },
    getElements: function(A, D){
        A = A.split(",");
        var C = [];
        var B = (A.length > 1);
        A.each(function(E){
            var F = this.getElementsByTagName(E.trim());
            (B) ? C.extend(F) : C = F;
        }, this);
        return new Elements(C, {
            ddup: B,
            cash: !D
        });
    }
});
Element.Storage = {
    get: function(A){
        return (this[A] = this[A] ||
        {});
    }
};
Element.Inserters = new Hash({
    before: function(B, A){
        if (A.parentNode) {
            A.parentNode.insertBefore(B, A);
        }
    },
    after: function(B, A){
        if (!A.parentNode) {
            return;
        }
        var C = A.nextSibling;
        (C) ? A.parentNode.insertBefore(B, C) : A.parentNode.appendChild(B);
    },
    bottom: function(B, A){
        A.appendChild(B);
    },
    top: function(B, A){
        var C = A.firstChild;
        (C) ? A.insertBefore(B, C) : A.appendChild(B);
    }
});
Element.Inserters.inside = Element.Inserters.bottom;
Element.implement({
    getElementById: function(D, C){
        var B = this.ownerDocument.getElementById(D);
        if (!B) {
            return null;
        }
        for (var A = B.parentNode; A != this; A = A.parentNode) {
            if (!A) {
                return null;
            }
        }
        return $.element(B, C);
    },
    set: function(D, B){
        switch ($type(D)) {
            case "object":
                for (var C in D) {
                    this.set(C, D[C]);
                }
                break;
            case "string":
                var A = Element.Properties.get(D);
                (A && A.set) ? A.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(D, B);
        }
        return this;
    },
    get: function(B){
        var A = Element.Properties.get(B);
        return (A && A.get) ? A.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(B);
    },
    erase: function(B){
        var A = Element.Properties.get(B);
        (A && A.erase) ? A.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(B);
        return this;
    },
    match: function(A){
        return (!A || Element.get(this, "tag") == A);
    },
    inject: function(B, A){
        Element.Inserters.get(A || "bottom")(this, $(B, true));
        return this;
    },
    wraps: function(B, A){
        B = $(B, true);
        return this.replaces(B).grab(B);
    },
    grab: function(B, A){
        Element.Inserters.get(A || "bottom")($(B, true), this);
        return this;
    },
    appendText: function(B, A){
        return this.grab(new TextNode(B, this.ownerDocument), A);
    },
    adopt: function(){
        Array.flatten(arguments).each(function(A){
            this.appendChild($(A, true));
        }, this);
        return this;
    },
    dispose: function(){
        return this.parentNode.removeChild(this);
    },
    clone: function(B){
        var A = new Element("div").grab(this.cloneNode(B !== false));
        Array.each(A.getElementsByTagName("*"), function(C){
            if (C.id) {
                C.removeAttribute("id");
            }
        });
        return new Element("div").set("html", A.innerHTML).getFirst();
    },
    replaces: function(A){
        A = $(A, true);
        A.parentNode.replaceChild(this, A);
        return this;
    },
    hasClass: function(A){
        return this.className.contains(A, " ");
    },
    addClass: function(A){
        if (!this.hasClass(A)) {
            this.className = (this.className + " " + A).clean();
        }
        return this;
    },
    removeClass: function(A){
        this.className = this.className.replace(new RegExp("(^|\\s)" + A + "(?:\\s|$)"), "$1").clean();
        return this;
    },
    toggleClass: function(A){
        return this.hasClass(A) ? this.removeClass(A) : this.addClass(A);
    },
    getComputedStyle: function(B){
        var A = false;
        if (this.currentStyle) {
            A = this.currentStyle[B.camelCase()];
        }
        else {
            A = this.ownerDocument.window.getComputedStyle(this, null).getPropertyValue([B.hyphenate()]);
        }
        return A;
    },
    empty: function(){
        var A = $A(this.getElementsByTagName("*"));
        A.each(function(B){
            $try(Element.prototype.dispose, B);
        });
        Garbage.trash(A);
        $try(Element.prototype.set, this, ["html", ""]);
        return this;
    },
    destroy: function(){
        Garbage.kill(this.empty().dispose());
        return null;
    },
    toQueryString: function(){
        var A = [];
        this.getElements("input, select, textarea", true).each(function(D){
            var B = D.name, C = D.type, E = Element.get(D, "value");
            if (E === false || !B || D.disabled) {
                return;
            }
            $splat(E).each(function(F){
                A.push(B + "=" + encodeURIComponent(F));
            });
        });
        return A.join("&");
    },
    getProperty: function(C){
        var B = Element.Attributes, A = B.Props[C];
        var D = (A) ? this[A] : this.getAttribute(C);
        return (B.Bools[C]) ? !!D : D;
    },
    getProperties: function(){
        var A = $A(arguments);
        return A.map(function(B){
            return this.getProperty(B);
        }, this).associate(A);
    },
    setProperty: function(D, E){
        var C = Element.Attributes, B = C.Props[D], A = $defined(E);
        if (B && C.Bools[D]) {
            E = (E || !A) ? true : false;
        }
        else {
            if (!A) {
                return this.removeProperty(D);
            }
        }
        (B) ? this[B] = E : this.setAttribute(D, E);
        return this;
    },
    setProperties: function(A){
        for (var B in A) {
            this.setProperty(B, A[B]);
        }
        return this;
    },
    removeProperty: function(D){
        var C = Element.Attributes, B = C.Props[D], A = (B && C.Bools[D]);
        (B) ? this[B] = (A) ? false : "" : this.removeAttribute(D);
        return this;
    },
    removeProperties: function(){
        Array.each(arguments, this.removeProperty, this);
        return this;
    }
});
(function(){
    var A = function(D, B, I, C, F, H){
        var E = D[I || B];
        var G = [];
        while (E) {
            if (E.nodeType == 1 && Element.match(E, C)) {
                G.push(E);
                if (!F) {
                    break;
                }
            }
            E = E[B];
        }
        return (F) ? new Elements(G, {
            ddup: false,
            cash: !H
        }) : $(G[0], H);
    };
    Element.implement({
        getPrevious: function(B, C){
            return A(this, "previousSibling", null, B, false, C);
        },
        getAllPrevious: function(B, C){
            return A(this, "previousSibling", null, B, true, C);
        },
        getNext: function(B, C){
            return A(this, "nextSibling", null, B, false, C);
        },
        getAllNext: function(B, C){
            return A(this, "nextSibling", null, B, true, C);
        },
        getFirst: function(B, C){
            return A(this, "nextSibling", "firstChild", B, false, C);
        },
        getLast: function(B, C){
            return A(this, "previousSibling", "lastChild", B, false, C);
        },
        getParent: function(B, C){
            return A(this, "parentNode", null, B, false, C);
        },
        getParents: function(B, C){
            return A(this, "parentNode", null, B, true, C);
        },
        getChildren: function(B, C){
            return A(this, "nextSibling", "firstChild", B, true, C);
        },
        hasChild: function(B){
            if (!(B = $(B, true))) {
                return false;
            }
            return Element.getParents(B, this.get("tag"), true).contains(this);
        }
    });
})();
TextNode.implement({
    inject: Element.prototype.inject,
    dispose: Element.prototype.dispose
});
Element.alias("dispose", "remove").alias("getLast", "getLastChild");
Element.Properties = new Hash;
Element.Properties.style = {
    set: function(A){
        this.style.cssText = A;
    },
    get: function(){
        return this.style.cssText;
    },
    erase: function(){
        this.style.cssText = "";
    }
};
Element.Properties.value = {
    get: function(){
        switch (Element.get(this, "tag")) {
            case "select":
                var A = [];
                Array.each(this.options, function(B){
                    if (B.selected) {
                        A.push(B.value);
                    }
                });
                return (this.multiple) ? A : A[0];
            case "input":
                if (["checkbox", "radio"].contains(this.type) && !this.checked) {
                    return false;
                }
            default:
                return $pick(this.value, false);
        }
    }
};
Element.Properties.tag = {
    get: function(){
        return this.tagName.toLowerCase();
    }
};
Element.Properties.html = {
    set: function(){
        return this.innerHTML = Array.flatten(arguments).join("");
    }
};
Native.implement([Element, Window, Document], {
    addListener: function(B, A){
        if (this.addEventListener) {
            this.addEventListener(B, A, false);
        }
        else {
            this.attachEvent("on" + B, A);
        }
        return this;
    },
    removeListener: function(B, A){
        if (this.removeEventListener) {
            this.removeEventListener(B, A, false);
        }
        else {
            this.detachEvent("on" + B, A);
        }
        return this;
    },
    retrieve: function(B, A){
        var D = Element.Storage.get(this.uid);
        var C = D[B];
        if ($defined(A) && !$defined(C)) {
            C = D[B] = A;
        }
        return $pick(C);
    },
    store: function(B, A){
        var C = Element.Storage.get(this.uid);
        C[B] = A;
        return this;
    },
    eliminate: function(A){
        var B = Element.Storage.get(this.uid);
        delete B[A];
        return this;
    }
});
Element.Attributes = new Hash({
    Props: {
        "html": "innerHTML",
        "class": "className",
        "for": "htmlFor",
        "text": (Browser.Engine.trident) ? "innerText" : "textContent"
    },
    Bools: ["compact", "nowrap", "ismap", "declare", "noshade", "checked", "disabled", "readonly", "multiple", "selected", "noresize", "defer"],
    Camels: ["value", "accessKey", "cellPadding", "cellSpacing", "colSpan", "frameBorder", "maxLength", "readOnly", "rowSpan", "tabIndex", "useMap"]
});
(function(B){
    var C = B.Bools, A = B.Camels;
    B.Bools = C = C.associate(C);
    Hash.extend(Hash.merge(B.Props, C), A.associate(A.map(function(D){
        return D.toLowerCase();
    })));
    B.remove("Camels");
})(Element.Attributes);
var Garbage = {
    Elements: {},
    ignored: {
        "object": 1,
        "embed": 1,
        "OBJECT": 1,
        "EMBED": 1
    },
    collect: function(A){
        if (A.$attributes) {
            return true;
        }
        if (Garbage.ignored[A.tagName]) {
            return false;
        }
        Garbage.Elements[A.uid] = A;
        A.$attributes = {};
        return true;
    },
    trash: function(C){
        for (var A = C.length, B; A--; A) {
            Garbage.kill(C[A]);
        }
    },
    kill: function(A){
        if (!A || !A.$attributes) {
            return;
        }
        delete Garbage.Elements[A.uid];
        if (A.retrieve("events")) {
            A.removeEvents();
        }
        for (var B in A.$attributes) {
            A.$attributes[B] = null;
        }
        if (Browser.Engine.trident) {
            for (var C in Element.Prototype) {
                A[C] = null;
            }
        }
        A.$attributes = A.uid = null;
    },
    empty: function(){
        for (var A in Garbage.Elements) {
            Garbage.kill(Garbage.Elements[A]);
        }
    }
};
window.addListener("beforeunload", function(){
    window.addListener("unload", Garbage.empty);
    if (Browser.Engine.trident) {
        window.addListener("unload", CollectGarbage);
    }
});
Element.extend = Element.implement;
Elements.extend = Elements.implement;
Element.implement({
    getFormElements: function(){
        return this.getElements("input, textarea, select");
    },
    getValue: function(){
        return this.get("value");
    },
    getText: function(){
        return this.get("text");
    },
    setText: function(A){
        return this.set("text", A);
    },
    setHTML: function(){
        return this.set("html", $A(arguments));
    },
    getTag: function(){
        return this.get("tag");
    },
    replaceWith: function(A){
        A = $(A);
        this.parentNode.replaceChild(A, this);
        return A;
    },
    removeElements: function(){
        return this.dispose();
    },
    remove: function(){
        return this.dispose();
    }
});
(function(){
    var A = {};
    Element.Inserters.each(function(C, B){
        A["inject" + B.capitalize()] = function(D){
            return Element.inject(this, D, B);
        };
    });
    Element.implement(A);
})();
var Event = new Native({
    name: "Event",
    initialize: function(D, G){
        G = G || window;
        D = D || G.event;
        if (D.$extended) {
            return D;
        }
        this.$extended = true;
        var C = D.type;
        var F = D.target || D.srcElement;
        while (F && F.nodeType == 3) {
            F = F.parentNode;
        }
        if (C.test(/DOMMouseScroll|mousewheel/)) {
            this.wheel = (D.wheelDelta) ? D.wheelDelta / 120 : -(D.detail || 0) / 3;
        }
        else {
            if (C.test(/key/)) {
                this.code = D.which || D.keyCode;
                var B = Event.Keys.keyOf(this.code);
                if (C == "keydown") {
                    var A = this.code - 111;
                    if (A > 0 && A < 13) {
                        B = "f" + A;
                    }
                }
                this.key = B || String.fromCharCode(this.code).toLowerCase();
            }
            else {
                if (C.test(/(click|mouse|menu)/)) {
                    this.page = {
                        x: D.pageX || D.clientX + G.document.documentElement.scrollLeft,
                        y: D.pageY || D.clientY + G.document.documentElement.scrollTop
                    };
                    this.client = {
                        x: D.pageX ? D.pageX - G.pageXOffset : D.clientX,
                        y: D.pageY ? D.pageY - G.pageYOffset : D.clientY
                    };
                    this.rightClick = (D.which == 3) || (D.button == 2);
                    var E = null;
                    if (C.test(/over|out/)) {
                        switch (C) {
                            case "mouseover":
                                E = D.relatedTarget || D.fromElement;
                                break;
                            case "mouseout":
                                E = D.relatedTarget || D.toElement;
                        }
                        if ((function(){
                            while (E && E.nodeType == 3) {
                                E = E.parentNode;
                            }
                        }).create({
                            attempt: Browser.Engine.gecko
                        })() ===
                        false) {
                            E = false;
                        }
                    }
                }
            }
        }
        return $extend(this, {
            event: D,
            type: C,
            relatedTarget: E,
            target: F,
            shift: D.shiftKey,
            control: D.ctrlKey,
            alt: D.altKey,
            meta: D.metaKey
        });
    }
});
Event.Keys = new Hash({
    "enter": 13,
    "up": 38,
    "down": 40,
    "left": 37,
    "right": 39,
    "esc": 27,
    "space": 32,
    "backspace": 8,
    "tab": 9,
    "delete": 46
});
Event.implement({
    stop: function(){
        return this.stopPropagation().preventDefault();
    },
    stopPropagation: function(){
        if (this.event.stopPropagation) {
            this.event.stopPropagation();
        }
        else {
            this.event.cancelBubble = true;
        }
        return this;
    },
    preventDefault: function(){
        if (this.event.preventDefault) {
            this.event.preventDefault();
        }
        else {
            this.event.returnValue = false;
        }
        return this;
    }
});
Element.Properties.events = {
    set: function(A){
        this.addEvents(A);
    }
};
Native.implement([Element, Window, Document], {
    addEvent: function(E, G){
        var H = this.retrieve("events", {});
        H[E] = H[E] ||
        {
            "keys": [],
            "values": []
        };
        if (H[E].keys.contains(G)) {
            return this;
        }
        H[E].keys.push(G);
        var F = E, A = Element.Events.get(E), C = G, I = this;
        if (A) {
            if (A.onAdd) {
                A.onAdd.call(this, G);
            }
            if (A.condition) {
                C = function(J){
                    if (A.condition.call(this, J)) {
                        return G.call(this, J);
                    }
                    return false;
                };
            }
            F = A.base || F;
        }
        var D = function(){
            return G.call(I);
        };
        var B = Element.NativeEvents[F] || 0;
        if (B) {
            if (B == 2) {
                D = function(J){
                    J = new Event(J, (I.ownerDocument || I).window);
                    if (C.call(I, J) === false) {
                        J.stop();
                    }
                };
            }
            this.addListener(F, D);
        }
        H[E].values.push(D);
        return this;
    },
    removeEvent: function(D, C){
        var B = this.retrieve("events");
        if (!B || !B[D]) {
            return this;
        }
        var G = B[D].keys.indexOf(C);
        if (G == -1) {
            return this;
        }
        var A = B[D].keys.splice(G, 1)[0];
        var F = B[D].values.splice(G, 1)[0];
        var E = Element.Events.get(D);
        if (E) {
            if (E.onRemove) {
                E.onRemove.call(this, C);
            }
            D = E.base || D;
        }
        return (Element.NativeEvents[D]) ? this.removeListener(D, F) : this;
    },
    addEvents: function(A){
        for (var B in A) {
            this.addEvent(B, A[B]);
        }
        return this;
    },
    removeEvents: function(B){
        var A = this.retrieve("events");
        if (!A) {
            return this;
        }
        if (!B) {
            for (var C in A) {
                this.removeEvents(C);
            }
            A = null;
        }
        else {
            if (A[B]) {
                while (A[B].keys[0]) {
                    this.removeEvent(B, A[B].keys[0]);
                }
                A[B] = null;
            }
        }
        return this;
    },
    fireEvent: function(D, B, A){
        var C = this.retrieve("events");
        if (!C || !C[D]) {
            return this;
        }
        C[D].keys.each(function(E){
            E.create({
                "bind": this,
                "delay": A,
                "arguments": B
            })();
        }, this);
        return this;
    },
    cloneEvents: function(D, A){
        D = $(D);
        var C = D.retrieve("events");
        if (!C) {
            return this;
        }
        if (!A) {
            for (var B in C) {
                this.cloneEvents(D, B);
            }
        }
        else {
            if (C[A]) {
                C[A].keys.each(function(E){
                    this.addEvent(A, E);
                }, this);
            }
        }
        return this;
    }
});
Element.NativeEvents = {
    "click": 2,
    "dblclick": 2,
    "mouseup": 2,
    "mousedown": 2,
    "contextmenu": 2,
    "mousewheel": 2,
    "DOMMouseScroll": 2,
    "mouseover": 2,
    "mouseout": 2,
    "mousemove": 2,
    "selectstart": 2,
    "selectend": 2,
    "keydown": 2,
    "keypress": 2,
    "keyup": 2,
    "focus": 2,
    "blur": 2,
    "change": 2,
    "reset": 2,
    "select": 2,
    "submit": 2,
    "load": 1,
    "unload": 1,
    "beforeunload": 1,
    "resize": 1,
    "move": 1,
    "DOMContentLoaded": 1,
    "readystatechange": 1,
    "error": 1,
    "abort": 1,
    "scroll": 1
};
(function(){
    var A = function(B){
        var C = B.relatedTarget;
        if (!C) {
            return true;
        }
        return ($type(this) != "document" && C != this && C.prefix != "xul" && !this.hasChild(C));
    };
    Element.Events = new Hash({
        mouseenter: {
            base: "mouseover",
            condition: A
        },
        mouseleave: {
            base: "mouseout",
            condition: A
        },
        mousewheel: {
            base: (Browser.Engine.gecko) ? "DOMMouseScroll" : "mousewheel"
        },
        domready: {
            onAdd: function(F){
                if ($type(this) == "element") {
                    return;
                }
                if (Browser.loaded) {
                    F.call(this);
                    return;
                }
                var D = this;
                var E = function(){
                    if (!arguments.callee.done) {
                        arguments.callee.done = true;
                        F.call(D);
                    }
                    return true;
                };
                var B = function(H){
                    if ((Browser.Engine.webkit ? ["loaded", "complete"] : "complete").contains(H.readyState)) {
                        return E();
                    }
                    return false;
                };
                if (this.document.readyState && Browser.Engine.webkit) {
                    (function(){
                        if (!B(D.document)) {
                            arguments.callee.delay(50);
                        }
                    })();
                }
                else {
                    if (this.document.readyState && Browser.Engine.trident) {
                        var C = $("ie_domready");
                        if (!C) {
                            var G = (this.location.protocol == "https:") ? "//:" : "javascript:void(0)";
                            this.document.write('<script id="ie_domready" defer src="' + G + '"><\/script>');
                            C = $("ie_domready");
                        }
                        if (!B(C)) {
                            C.addEvent("readystatechange", B.pass(C));
                        }
                    }
                    else {
                        this.addEvent("load", E);
                        this.document.addEvent("DOMContentLoaded", E);
                    }
                }
            }
        }
    });
})();
window.addEvent("domready", function(){
    Browser.loaded = true;
});
Event.keys = Event.Keys;
Element.Properties.styles = {
    set: function(A){
        this.setStyles(A);
    }
};
Element.Properties.opacity = {
    set: function(A){
        if (A == 0) {
            if (this.style.visibility != "hidden") {
                this.style.visibility = "hidden";
            }
        }
        else {
            if (this.style.visibility != "visible") {
                this.style.visibility = "visible";
            }
        }
        if (!this.currentStyle || !this.currentStyle.hasLayout) {
            this.style.zoom = 1;
        }
        if (Browser.Engine.trident) {
            this.style.filter = (A == 1) ? "" : "alpha(opacity=" + A * 100 + ")";
        }
        this.style.opacity = A;
        this.store("opacity", A);
    },
    get: function(){
        return this.retrieve("opacity", 1);
    }
};
Element.implement({
    setStyle: function(B, A){
        switch (B) {
            case "opacity":
                return this.set("opacity", parseFloat(A));
            case "float":
                B = (Browser.Engine.trident) ? "styleFloat" : "cssFloat";
        }
        B = B.camelCase();
        if ($type(A) != "string") {
            var C = (Element.Styles.get(B) || "@").split(" ");
            A = $splat(A).map(function(E, D){
                if (!C[D]) {
                    return "";
                }
                return ($type(E) == "number") ? C[D].replace("@", Math.round(E)) : E;
            }).join(" ");
        }
        else {
            if (A == String(Number(A))) {
                A = Math.round(A);
            }
        }
        this.style[B] = A;
        return this;
    },
    getStyle: function(G){
        switch (G) {
            case "opacity":
                return this.get("opacity");
            case "float":
                G = (Browser.Engine.trident) ? "styleFloat" : "cssFloat";
        }
        G = G.camelCase();
        var A = this.style[G];
        if (!$chk(A)) {
            A = [];
            for (var F in Element.ShortStyles) {
                if (G != F) {
                    continue;
                }
                for (var E in Element.ShortStyles[F]) {
                    A.push(this.getStyle(E));
                }
                return A.join(" ");
            }
            A = this.getComputedStyle(G);
        }
        if (A) {
            A = String(A);
            var C = A.match(/rgba?\([\d\s,]+\)/);
            if (C) {
                A = A.replace(C[0], C[0].rgbToHex());
            }
        }
        if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(A)))) {
            if (G.test(/^(height|width)$/)) {
                var B = (G == "width") ? ["left", "right"] : ["top", "bottom"], D = 0;
                B.each(function(H){
                    D += this.getStyle("border-" + H + "-width").toInt() + this.getStyle("padding-" + H).toInt();
                }, this);
                return this["offset" + G.capitalize()] - D + "px";
            }
            if (Browser.Engine.presto && String(A).test("px")) {
                return A;
            }
            if (G.test(/(border(.+)Width|margin|padding)/)) {
                return "0px";
            }
        }
        return A;
    },
    setStyles: function(B){
        for (var A in B) {
            this.setStyle(A, B[A]);
        }
        return this;
    },
    getStyles: function(){
        var A = {};
        Array.each(arguments, function(B){
            A[B] = this.getStyle(B);
        }, this);
        return A;
    }
});
Element.Styles = new Hash({
    "width": "@px",
    "height": "@px",
    "left": "@px",
    "top": "@px",
    "bottom": "@px",
    "right": "@px",
    "backgroundColor": "rgb(@, @, @)",
    "backgroundPosition": "@px @px",
    "color": "rgb(@, @, @)",
    "fontSize": "@px",
    "letterSpacing": "@px",
    "lineHeight": "@px",
    "clip": "rect(@px @px @px @px)",
    "margin": "@px @px @px @px",
    "padding": "@px @px @px @px",
    "border": "@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",
    "borderWidth": "@px @px @px @px",
    "borderStyle": "@ @ @ @",
    "borderColor": "rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",
    "zIndex": "@",
    "zoom": "@",
    "fontWeight": "@",
    "textIndent": "@px",
    "opacity": "@"
});
Element.ShortStyles = {
    "margin": {},
    "padding": {},
    "border": {},
    "borderWidth": {},
    "borderStyle": {},
    "borderColor": {}
};
["Top", "Right", "Bottom", "Left"].each(function(G){
    var F = Element.ShortStyles;
    var B = Element.Styles;
    ["margin", "padding"].each(function(H){
        var I = H + G;
        F[H][I] = B[I] = "@px";
    });
    var E = "border" + G;
    F.border[E] = B[E] = "@px @ rgb(@, @, @)";
    var D = E + "Width", A = E + "Style", C = E + "Color";
    F[E] = {};
    F.borderWidth[D] = F[E][D] = B[D] = "@px";
    F.borderStyle[A] = F[E][A] = B[A] = "@";
    F.borderColor[C] = F[E][C] = B[C] = "rgb(@, @, @)";
});
Element.implement({
    setOpacity: function(A){
        return this.set("opacity", A);
    }
});
Native.implement([Element, Document], {
    getElements: function(N, M){
        var J = {};
        N = N.split(",");
        var A = [], H = N.length;
        var B = (H > 1);
        for (var I = 0; I < H; I++) {
            var E = N[I], K = [], G = [];
            E = E.trim().replace(Selectors.sRegExp, function(P){
                if (P.charAt(2)) {
                    P = P.trim();
                }
                G.push(P.charAt(0));
                return ":)" + P.charAt(1);
            }).split(":)");
            for (var F = 0, D = E.length; F < D; F++) {
                var C = Selectors.parse(E[F]);
                if (!C) {
                    return [];
                }
                var O = Selectors.Method.getParam(K, G[F - 1] || false, this, C, J);
                if (!O) {
                    break;
                }
                K = O;
            }
            var L = Selectors.Method.getItems(K, this);
            A = (B) ? A.concat(L) : L;
        }
        return new Elements(A, {
            ddup: B,
            cash: !M
        });
    }
});
Window.implement({
    $E: function(A){
        return this.document.getElement(A);
    }
});
var Selectors = {
    "regExp": (/:([^-:(]+)[^:(]*(?:\((["']?)(.*?)\2\))?|\[(\w+)(?:([!*^$~|]?=)(["']?)(.*?)\6)?\]|\.[\w-]+|#[\w-]+|\w+|\*/g),
    "sRegExp": (/\s*([+>~\s])[a-zA-Z#.*\s]/g)
};
Selectors.parse = function(A){
    var B = {
        "tag": "*",
        "id": null,
        "classes": [],
        "attributes": [],
        "pseudos": []
    };
    A = A.replace(Selectors.regExp, function(E){
        switch (E.charAt(0)) {
            case ".":
                B.classes.push(E.slice(1));
                break;
            case "#":
                B.id = E.slice(1);
                break;
            case "[":
                B.attributes.push([arguments[4], arguments[5], arguments[7]]);
                break;
            case ":":
                var D = Selectors.Pseudo.get(arguments[1]);
                if (!D) {
                    B.attributes.push([arguments[1], arguments[3] ? "=" : "", arguments[3]]);
                    break;
                }
                var C = {
                    "name": arguments[1],
                    "parser": D,
                    "argument": (D.parser) ? D.parser(arguments[3]) : arguments[3]
                };
                B.pseudos.push(C);
                break;
            default:
                B.tag = E;
        }
        return "";
    });
    return B;
};
Selectors.Pseudo = new Hash;
Selectors.XPath = {
    getParam: function(B, G, D, H){
        var A = D.namespaceURI ? "xhtml:" : "";
        switch (G) {
            case " ":
                A += "//";
                break;
            case ">":
                A += "/";
                break;
            case "+":
                A += "/following-sibling::*[1]/self::";
                break;
            case "~":
                A += "/following-sibling::";
                break;
        }
        A += H.tag;
        var C;
        for (C = H.pseudos.length; C--; C) {
            var F = H.pseudos[C];
            if (F.parser && F.parser.xpath) {
                A += F.parser.xpath(F.argument);
            }
            else {
                A += ($chk(F.argument)) ? "[@" + F.name + '="' + F.argument + '"]' : "[@" + F.name + "]";
            }
        }
        if (H.id) {
            A += '[@id="' + H.id + '"]';
        }
        for (C = H.classes.length; C--; C) {
            A += '[contains(concat(" ", @class, " "), " ' + H.classes[C] + ' ")]';
        }
        for (C = H.attributes.length; C--; C) {
            var E = H.attributes[C];
            switch (E[1]) {
                case "=":
                    A += "[@" + E[0] + '="' + E[2] + '"]';
                    break;
                case "*=":
                    A += "[contains(@" + E[0] + ', "' + E[2] + '")]';
                    break;
                case "^=":
                    A += "[starts-with(@" + E[0] + ', "' + E[2] + '")]';
                    break;
                case "$=":
                    A += "[substring(@" + E[0] + ", string-length(@" + E[0] + ") - " + E[2].length + ' + 1) = "' + E[2] + '"]';
                    break;
                case "!=":
                    A += "[@" + E[0] + '!="' + E[2] + '"]';
                    break;
                case "~=":
                    A += '[contains(concat(" ", @' + E[0] + ', " "), " ' + E[2] + ' ")]';
                    break;
                case "|=":
                    A += '[contains(concat("-", @' + E[0] + ', "-"), "-' + E[2] + '-")]';
                    break;
                default:
                    A += "[@" + E[0] + "]";
            }
        }
        B.push(A);
        return B;
    },
    getItems: function(B, E){
        var F = [];
        var G = E.ownerDocument || E;
        var A = G.evaluate(".//" + B.join(""), E, Selectors.XPath.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var D = 0, C = A.snapshotLength; D < C; D++) {
            F[D] = A.snapshotItem(D);
        }
        return F;
    },
    resolver: function(A){
        return (A == "xhtml") ? "http://www.w3.org/1999/xhtml" : false;
    }
};
Selectors.Filter = {
    getParam: function(H, B, A, P, Q){
        var F = [];
        var R = P.tag;
        if (B) {
            var C = {}, E, D, O, L, K;
            var G = function(S){
                S.uid = S.uid || [Native.UID++];
                if (!C[S.uid] && Selectors.Filter.match(S, P, Q)) {
                    C[S.uid] = true;
                    F.push(S);
                    return true;
                }
                return false;
            };
            for (var N = 0, M = H.length; N < M; N++) {
                O = H[N];
                switch (B) {
                    case " ":
                        D = O.getElementsByTagName(R);
                        P.tag = false;
                        for (L = 0, K = D.length; L < K; L++) {
                            G(D[L]);
                        }
                        break;
                    case ">":
                        D = O.childNodes;
                        for (L = 0, K = D.length; L < K; L++) {
                            if (D[L].nodeType == 1) {
                                G(D[L]);
                            }
                        }
                        break;
                    case "+":
                        while ((O = O.nextSibling)) {
                            if (O.nodeType == 1) {
                                G(O);
                                break;
                            }
                        }
                        break;
                    case "~":
                        while ((O = O.nextSibling)) {
                            if (O.nodeType == 1 && G(O)) {
                                break;
                            }
                        }
                        break;
                }
            }
            return F;
        }
        if (P.id) {
            el = A.getElementById(P.id, true);
            P.id = false;
            return (el && Selectors.Filter.match(el, P, Q)) ? [el] : false;
        }
        else {
            H = A.getElementsByTagName(R);
            P.tag = false;
            for (var J = 0, I = H.length; J < I; J++) {
                if (Selectors.Filter.match(H[J], P, Q)) {
                    F.push(H[J]);
                }
            }
        }
        return F;
    },
    getItems: $arguments(0)
};
Selectors.Filter.match = function(C, E, G){
    G = G ||
    {};
    if (E.id && E.id != C.id) {
        return false;
    }
    if (E.tag && E.tag != "*" && E.tag != C.tagName.toLowerCase()) {
        return false;
    }
    var B;
    for (B = E.classes.length; B--; B) {
        if (!C.className || !C.className.contains(E.classes[B], " ")) {
            return false;
        }
    }
    for (B = E.attributes.length; B--; B) {
        var D = E.attributes[B];
        var A = Element.prototype.getProperty.call(C, D[0]);
        if (!A) {
            return false;
        }
        if (!D[1]) {
            continue;
        }
        var F;
        switch (D[1]) {
            case "=":
                F = (A == D[2]);
                break;
            case "*=":
                F = (A.contains(D[2]));
                break;
            case "^=":
                F = (A.substr(0, D[2].length) == D[2]);
                break;
            case "$=":
                F = (A.substr(A.length - D[2].length) == D[2]);
                break;
            case "!=":
                F = (A != D[2]);
                break;
            case "~=":
                F = A.contains(D[2], " ");
                break;
            case "|=":
                F = A.contains(D[2], "-");
        }
        if (!F) {
            return false;
        }
    }
    for (B = E.pseudos.length; B--; B) {
        if (!E.pseudos[B].parser.filter.call(C, E.pseudos[B].argument, G)) {
            return false;
        }
    }
    return true;
};
Selectors.Method = (Browser.Features.xpath) ? Selectors.XPath : Selectors.Filter;
Element.implement({
    match: function(A){
        return (!A || Selectors.Filter.match(this, Selectors.parse(A)));
    }
});
Native.implement([Element, Document], {
    getElementsByClassName: function(A){
        return this.getElements("." + A);
    },
    getElementsBySelector: function(A){
        return this.getElements(A);
    }
});
Elements.implement({
    filterByTag: function(A){
        return this.filterBy(A);
    },
    filterByClass: function(A){
        return this.filterBy("." + A);
    },
    filterById: function(A){
        return this.filterBy("#" + A);
    },
    filterByAttribute: function(B, A, C){
        return this.filterBy("[" + B + (A || "") + (C || "") + "]");
    }
});
$E = function(A, B){
    return ($(B) || document).getElement(A);
};
var $ES = function(A, B){
    return ($(B) || document).getElements(A);
};
var JSON = new Hash({
    encode: function(B){
        switch ($type(B)) {
            case "string":
                return '"' + B.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
            case "array":
                return "[" + String(B.map(JSON.encode).filter($defined)) + "]";
            case "object":
            case "hash":
                var A = [];
                Hash.each(B, function(E, D){
                    var C = JSON.encode(E);
                    if (C) {
                        A.push(JSON.encode(D) + ":" + C);
                    }
                });
                return "{" + String(A) + "}";
            case "number":
            case "boolean":
                return String(B);
            case false:
                return "null";
        }
        return null;
    },
    $specialChars: {
        "\b": "\\b",
        "\t": "\\t",
        "\n": "\\n",
        "\f": "\\f",
        "\r": "\\r",
        '"': '\\"',
        "\\": "\\\\"
    },
    $replaceChars: function(A){
        return JSON.$specialChars[A] || "\\u00" + Math.floor(A.charCodeAt() / 16).toString(16) + (A.charCodeAt() % 16).toString(16);
    },
    decode: function(string, secure){
        if ($type(string) != "string" || !string.length) {
            return null;
        }
        if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, "@").replace(/"[^"\\\n\r]*"/g, ""))) {
            return null;
        }
        return eval("(" + string + ")");
    }
});
Native.implement([Hash, Array, String, Number], {
    toJSON: function(){
        return JSON.encode(this);
    }
});
var Json = JSON;
JSON.toString = JSON.encode;
JSON.evaluate = JSON.decode;
var Cookie = {
    options: {
        path: false,
        domain: false,
        duration: false,
        secure: false
    },
    set: function(C, D, B){
        B = $merge(this.options, B);
        D = encodeURIComponent(D);
        if (B.domain) {
            D += "; domain=" + B.domain;
        }
        if (B.path) {
            D += "; path=" + B.path;
        }
        if (B.duration) {
            var A = new Date();
            A.setTime(A.getTime() + B.duration * 24 * 60 * 60 * 1000);
            D += "; expires=" + A.toGMTString();
        }
        if (B.secure) {
            D += "; secure";
        }
        document.cookie = C + "=" + D;
        return $extend(B, {
            "key": C,
            "value": D
        });
    },
    get: function(A){
        var B = document.cookie.match("(?:^|;)\\s*" + A.escapeRegExp() + "=([^;]*)");
        return B ? decodeURIComponent(B[1]) : false;
    },
    remove: function(B, A){
        if ($type(B) == "object") {
            this.set(B.key, "", $merge(B, {
                duration: -1
            }));
        }
        else {
            this.set(B, "", $merge(A, {
                duration: -1
            }));
        }
    }
};
(function(){
    var D = function(E){
        var G, F = true;
        switch ($type(E)) {
            case "window":
                G = E.document;
                break;
            case "document":
                G = E;
                break;
            case "element":
                G = E.ownerDocument;
                F = false;
        }
        return {
            doc: G,
            win: G.window,
            self: E,
            great: (F || E === G.body || E === G.html)
        };
    };
    var C = function(E){
        return D(E).great;
    };
    var B = {
        positioned: function(E){
            if (C(E)) {
                return true;
            }
            var F = E.style.position || (E.style.position = Element.getComputedStyle(E, "position"));
            return (F != "static");
        },
        getOffsetParent: function(E){
            if (!Browser.Engine.trident) {
                return E.offsetParent;
            }
            var F = E;
            while ((F = F.parentNode)) {
                if (B.positioned(F)) {
                    return F;
                }
            }
            return false;
        },
        getOffsetSize: function(E){
            var G = {}, I = {
                X: "Width",
                Y: "Height"
            }, H = D(E);
            for (var F in I) {
                G[F.toLowerCase()] = (function(){
                    if (H.great) {
                        if (Browser.Engine.webkit419) {
                            return H.win["inner" + I[F]];
                        }
                        if (Browser.Engine.presto) {
                            return H.doc.body["client" + I[F]];
                        }
                        return H.doc.documentElement["client" + I[F]];
                    }
                    else {
                        return E["offset" + I[F]];
                    }
                })();
            }
            return G;
        },
        getScrollSize: function(E){
            var G = {}, I = {
                X: "Width",
                Y: "Height"
            }, H = D(E);
            for (var F in I) {
                G[F.toLowerCase()] = (function(){
                    if (H.great) {
                        if (Browser.Engine.trident) {
                            return Math.max(H.doc.documentElement["offset" + I[F]], H.doc.documentElement["scroll" + I[F]]);
                        }
                        if (Browser.Engine.webkit) {
                            return H.doc.body["scroll" + I[F]];
                        }
                        return H.doc.documentElement["scroll" + I[F]];
                    }
                    else {
                        return E["scroll" + I[F]];
                    }
                })();
            }
            return G;
        },
        getScroll: function(E){
            var G = {}, I = {
                X: "Left",
                Y: "Top"
            }, H = D(E);
            for (var F in I) {
                G[F.toLowerCase()] = (function(){
                    return (H.great) ? H.win["page" + F + "Offset"] || H.doc.documentElement["scroll" + I[F]] : E["scroll" + I[F]];
                })();
            }
            return G;
        },
        getPosition: function(F, I){
            if (C(F) || I == F) {
                return {
                    x: 0,
                    y: 0
                };
            }
            var G = F, K = 0, J = 0, E;
            while (G) {
                var H = B.getOffsetParent(G);
                if (!H) {
                    break;
                }
                E = B.getRelativePosition(G, !C(H));
                K += E.x;
                J += E.y;
                G = H;
            }
            var L = (I) ? B.getPosition($(I, true)) : {
                x: 0,
                y: 0
            };
            return {
                x: K - L.x,
                y: J - L.y
            };
        },
        getRelativePosition: function(L, H){
            if (C(L)) {
                return {
                    x: 0,
                    y: 0
                };
            }
            var E = L, G = L.offsetLeft, J = L.offsetTop;
            if (Browser.Engine.trident) {
                while ((E = E.offsetParent) && !B.positioned(E)) {
                    G += E.offsetLeft;
                    J += E.offsetTop;
                }
                E = L;
            }
            var I = {
                x: G,
                y: J
            }, M = B.positioned(L);
            while ((E = E.parentNode)) {
                var F = B.positioned(E);
                if ((!F || H) && ((!M || F) || Browser.Engine.presto)) {
                    var K = B.getScroll(E);
                    I.x -= K.x;
                    I.y -= K.y;
                }
                if (F) {
                    break;
                }
            }
            return I;
        },
        getCoordinates: function(F, H){
            var E = B.getPosition(F, H), G = B.getOffsetSize(F);
            var I = {
                "top": E.y,
                "left": E.x,
                "width": G.x,
                "height": G.y
            };
            I.right = I.left + I.width;
            I.bottom = I.top + I.height;
            return I;
        }
    };
    var A = {};
    Hash.each(B, function(F, E){
        A[E] = function(G){
            return F(this, G);
        };
    });
    Native.implement([Element, Document], A);
    Document.implement({
        scrollTo: function(E, F){
            this.window.scrollTo(E, F);
        }
    });
    Element.implement({
        scrollTo: function(E, F){
            this.scrollLeft = E;
            this.scrollTop = F;
        },
        computePosition: function(I, G){
            var F, H = this;
            var E = {
                left: I.x - this.getComputedStyle("margin-left").toInt() || 0,
                top: I.y - this.getComputedStyle("margin-top").toInt() || 0
            };
            if (G) {
                F = B.getScroll(B.getOffsetParent(this));
                E.left += F.x;
                E.top += F.y;
            }
            if (Browser.Engine.presto) {
                while ((H = H.parentNode) && H != this.offsetParent) {
                    F = B.getScroll(H);
                    E.left += F.x;
                    E.top += F.y;
                }
            }
            return E;
        },
        position: function(F, E){
            return this.setStyles(this.computePosition(F, E));
        }
    });
})();
Window.implement({
    getSize: function(){
        return {
            size: this.document.getOffsetSize(),
            scroll: this.document.getScroll(),
            scrollSize: this.document.getScrollSize()
        };
    },
    getHeight: function(){
        return this.document.getOffsetSize().y;
    },
    getWidth: function(){
        return this.document.getOffsetSize().x;
    },
    getScrollTop: function(){
        return this.document.getScroll().y;
    },
    getScrollLeft: function(){
        return this.document.getScroll().x;
    },
    getScrollHeight: function(){
        return this.document.getScrollSize().y;
    },
    getScrollWidth: function(){
        return this.document.getScrollSize().x;
    }
});
Element.implement({
    getSize: function(){
        return {
            size: this.getOffsetSize(),
            scroll: this.getScroll(),
            scrollSize: this.getScrollSize()
        };
    },
    getTop: function(){
        return this.getPosition().y;
    },
    getLeft: function(){
        return this.getPosition().x;
    }
});
var Color = new Native({
    name: "Color",
    protect: false,
    initialize: function(B, D){
        D = D || ($type(B) == "array") ? "rgb" : "hex";
        var C, A;
        switch (D) {
            case "rgb":
                C = B;
                A = C.rgbToHsb();
                break;
            case "hsb":
                C = B.hsbToRgb();
                A = B;
                break;
            default:
                C = B.hexToRgb(true);
                A = C.rgbToHsb();
        }
        C.hsb = A;
        C.hex = C.rgbToHex();
        return $extend(C, this);
    }
});
Color.implement({
    mix: function(){
        var A = $A(arguments);
        var C = ($type(A.getLast()) == "number") ? A.pop() : 50;
        var B = this.slice();
        A.each(function(D){
            D = new Color(D);
            for (var E = 0; E < 3; E++) {
                B[E] = Math.round((B[E] / 100 * (100 - C)) + (D[E] / 100 * C));
            }
        });
        return new Color(B, "rgb");
    },
    invert: function(){
        return new Color(this.map(function(A){
            return 255 - A;
        }));
    },
    setHue: function(A){
        return new Color([A, this.hsb[1], this.hsb[2]], "hsb");
    },
    setSaturation: function(A){
        return new Color([this.hsb[0], A, this.hsb[2]], "hsb");
    },
    setBrightness: function(A){
        return new Color([this.hsb[0], this.hsb[1], A], "hsb");
    }
});
function $RGB(C, B, A){
    return new Color([C, B, A], "rgb");
}

function $HSB(C, B, A){
    return new Color([C, B, A], "hsb");
}

Array.implement({
    rgbToHsb: function(){
        var B = this[0], C = this[1], J = this[2];
        var G, F, H;
        var I = Math.max(B, C, J), E = Math.min(B, C, J);
        var K = I - E;
        H = I / 255;
        F = (I != 0) ? K / I : 0;
        if (F == 0) {
            G = 0;
        }
        else {
            var D = (I - B) / K;
            var A = (I - C) / K;
            var L = (I - J) / K;
            if (B == I) {
                G = L - A;
            }
            else {
                if (C == I) {
                    G = 2 + D - L;
                }
                else {
                    G = 4 + A - D;
                }
            }
            G /= 6;
            if (G < 0) {
                G++;
            }
        }
        return [Math.round(G * 360), Math.round(F * 100), Math.round(H * 100)];
    },
    hsbToRgb: function(){
        var C = Math.round(this[2] / 100 * 255);
        if (this[1] == 0) {
            return [C, C, C];
        }
        else {
            var A = this[0] % 360;
            var E = A % 60;
            var F = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
            var D = Math.round((this[2] * (6000 - this[1] * E)) / 600000 * 255);
            var B = Math.round((this[2] * (6000 - this[1] * (60 - E))) / 600000 * 255);
            switch (Math.floor(A / 60)) {
                case 0:
                    return [C, B, F];
                case 1:
                    return [D, C, F];
                case 2:
                    return [F, C, B];
                case 3:
                    return [F, D, C];
                case 4:
                    return [B, F, C];
                case 5:
                    return [C, F, D];
            }
        }
        return false;
    }
});
var Swiff = function(J, K){
    if (!Swiff.fixed) {
        Swiff.fix();
    }
    var I = "Swiff_" + Native.UID++;
    K = $merge({
        id: I,
        height: 1,
        width: 1,
        container: null,
        properties: {},
        params: {
            quality: "high",
            allowScriptAccess: "always",
            wMode: "transparent",
            swLiveConnect: true
        },
        events: {},
        vars: {}
    }, K);
    var D = K.params, E = K.vars, B = K.id;
    var F = $extend({
        height: K.height,
        width: K.width
    }, K.properties);
    Swiff.Events[I] = {};
    for (var A in K.events) {
        Swiff.Events[I][A] = function(){
            K.events[A].call($(K.id));
        };
        E[A] = "Swiff.Events." + I + "." + A;
    }
    D.flashVars = Hash.toQueryString(E);
    if (Browser.Engine.trident) {
        F.classid = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
        D.movie = J;
    }
    else {
        F.type = "application/x-shockwave-flash";
        F.data = J;
    }
    var H = '<object id="' + K.id + '"';
    for (var G in F) {
        H += " " + G + '="' + F[G] + '"';
    }
    H += ">";
    for (var C in D) {
        H += '<param name="' + C + '" value="' + D[C] + '" />';
    }
    H += "</object>";
    return ($(K.container) || new Element("div")).set("html", H).firstChild;
};
Swiff.extend({
    Events: {},
    remote: function(obj, fn){
        var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + "</invoke>");
        return eval(rs);
    },
    getVersion: function(){
        if (!$defined(Swiff.pluginVersion)) {
            var A;
            if (navigator.plugins && navigator.mimeTypes.length) {
                A = navigator.plugins["Shockwave Flash"];
                if (A && A.description) {
                    A = A.description;
                }
            }
            else {
                if (Browser.Engine.trident) {
                    A = $try(function(){
                        return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");
                    });
                }
            }
            Swiff.pluginVersion = ($type(A) == "string") ? parseInt(A.match(/\d+/)[0]) : 0;
        }
        return Swiff.pluginVersion;
    },
    fix: function(){
        Swiff.fixed = true;
        window.addEvent("beforeunload", function(){
            __flash_unloadHandler = __flash_savedUnloadHandler = $empty;
        });
        if (!Browser.Engine.trident) {
            return;
        }
        window.addEvent("unload", function(){
            Array.each(document.getElementsByTagName("object"), function(B){
                B.style.display = "none";
                for (var A in B) {
                    if (typeof B[A] == "function") {
                        B[A] = $empty;
                    }
                }
            });
        });
    }
});
var Group = new Class({
    initialize: function(){
        this.instances = Array.flatten(arguments);
        this.events = {};
        this.checker = {};
    },
    addEvent: function(B, A){
        this.checker[B] = this.checker[B] ||
        {};
        this.events[B] = this.events[B] || [];
        if (this.events[B].contains(A)) {
            return false;
        }
        else {
            this.events[B].push(A);
        }
        this.instances.each(function(C, D){
            C.addEvent(B, this.check.bind(this, [B, C, D]));
        }, this);
        return this;
    },
    check: function(C, A, B){
        this.checker[C][B] = true;
        var D = this.instances.every(function(F, E){
            return this.checker[C][E] || false;
        }, this);
        if (!D) {
            return;
        }
        this.checker[C] = {};
        this.events[C].each(function(E){
            E.call(this, this.instances, A);
        }, this);
    }
});
var Fx = new Class({
    Implements: [Chain, Events, Options],
    options: {
        fps: 50,
        unit: false,
        duration: 500,
        link: "ignore",
        transition: function(A){
            return -(Math.cos(Math.PI * A) - 1) / 2;
        }
    },
    initialize: function(A){
        this.pass = this.pass || this;
        this.setOptions(A);
        this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt();
        if (this.options.wait === false) {
            this.options.link = "cancel";
        }
    },
    step: function(){
        var A = $time();
        if (A < this.time + this.options.duration) {
            var B = this.options.transition((A - this.time) / this.options.duration);
            this.set(this.compute(this.from, this.to, B));
        }
        else {
            this.set(this.compute(this.from, this.to, 1));
            this.complete();
        }
    },
    set: function(A){
        return A;
    },
    compute: function(C, B, A){
        return Fx.compute(C, B, A);
    },
    check: function(){
        if (!this.timer) {
            return true;
        }
        switch (this.options.link) {
            case "cancel":
                this.cancel();
                return true;
            case "chain":
                this.chain(this.start.bind(this, arguments));
                return false;
        }
        return false;
    },
    start: function(B, A){
        if (!this.check(B, A)) {
            return this;
        }
        this.from = B;
        this.to = A;
        this.time = 0;
        this.startTimer();
        this.onStart();
        return this;
    },
    complete: function(){
        return (!this.stopTimer()) ? this : this.onComplete();
    },
    cancel: function(){
        return (!this.stopTimer()) ? this : this.onCancel();
    },
    onStart: function(){
        return this.fireEvent("onStart", this.pass);
    },
    onComplete: function(){
        return this.fireEvent("onComplete", this.pass).callChain();
    },
    onCancel: function(){
        return this.fireEvent("onCancel", this.pass).clearChain();
    },
    pause: function(){
        this.stopTimer();
        return this;
    },
    resume: function(){
        this.startTimer();
        return this;
    },
    stopTimer: function(){
        if (!this.timer) {
            return false;
        }
        this.time = $time() - this.time;
        this.timer = $clear(this.timer);
        return true;
    },
    startTimer: function(){
        if (this.timer) {
            return false;
        }
        this.time = $time() - this.time;
        this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
        return true;
    }
});
Fx.compute = function(C, B, A){
    return (B - C) * A + C;
};
Fx.Durations = {
    "short": 250,
    "normal": 500,
    "long": 1000
};
Fx.implement({
    custom: function(B, A){
        return this.start(B, A);
    },
    clearTimer: function(){
        return this.cancel();
    }
});
Fx.Base = Fx;
Fx.CSS = new Class({
    Extends: Fx,
    prepare: function(D, E, B){
        B = $splat(B);
        var C = B[1];
        if (!$chk(C)) {
            B[1] = B[0];
            B[0] = D.getStyle(E);
        }
        var A = B.map(this.parse);
        return {
            from: A[0],
            to: A[1]
        };
    },
    parse: function(A){
        A = $lambda(A)();
        A = ($type(A) == "string") ? A.split(" ") : $splat(A);
        return A.map(function(C){
            C = String(C);
            var B = false;
            Fx.CSS.Parsers.each(function(F, E){
                if (B) {
                    return;
                }
                var D = F.parse(C);
                if ($chk(D)) {
                    B = {
                        "value": D,
                        "parser": F
                    };
                }
            });
            B = B ||
            {
                value: C,
                parser: Fx.CSS.Parsers.String
            };
            return B;
        });
    },
    compute: function(D, C, B){
        var A = [];
        (Math.min(D.length, C.length)).times(function(E){
            A.push({
                "value": D[E].parser.compute(D[E].value, C[E].value, B),
                "parser": D[E].parser
            });
        });
        A.$family = {
            name: "fx:css:value"
        };
        return A;
    },
    serve: function(C, B){
        if ($type(C) != "fx:css:value") {
            C = this.parse(C);
        }
        var A = [];
        C.each(function(D){
            A = A.concat(D.parser.serve(D.value, B));
        });
        return A;
    },
    render: function(A, C, B){
        A.setStyle(C, this.serve(B, this.options.unit));
    },
    search: function(A){
        var B = {};
        Array.each(document.styleSheets, function(D, C){
            var E = D.rules || D.cssRules;
            Array.each(E, function(G, F){
                if (!G.style || !G.selectorText || !G.selectorText.test("^" + A + "$")) {
                    return;
                }
                Element.Styles.each(function(I, H){
                    if (!G.style[H] || Element.ShortStyles[H]) {
                        return;
                    }
                    I = G.style[H];
                    B[H] = (I.test(/^rgb/)) ? I.rgbToHex() : I;
                });
            });
        });
        return B;
    }
});
Fx.CSS.Parsers = new Hash({
    Color: {
        parse: function(A){
            if (A.match(/^#[0-9a-f]{3,6}$/i)) {
                return A.hexToRgb(true);
            }
            return ((A = A.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [A[1], A[2], A[3]] : false;
        },
        compute: function(C, B, A){
            return C.map(function(E, D){
                return Math.round(Fx.compute(C[D], B[D], A));
            });
        },
        serve: function(A){
            return A.map(Number);
        }
    },
    Number: {
        parse: function(A){
            return parseFloat(A);
        },
        compute: function(C, B, A){
            return Fx.compute(C, B, A);
        },
        serve: function(B, A){
            return (A) ? B + A : B;
        }
    },
    String: {
        parse: $lambda(false),
        compute: $arguments(1),
        serve: $arguments(0)
    }
});
Fx.Tween = new Class({
    Extends: Fx.CSS,
    initialize: function(B, C, A){
        this.element = this.pass = $(B);
        this.property = C;
        arguments.callee.parent(A);
    },
    set: function(A){
        this.render(this.element, this.property, A);
        return this;
    },
    start: function(){
        var A = Array.flatten(arguments);
        if (!this.check(A)) {
            return this;
        }
        var B = this.prepare(this.element, this.property, A);
        return arguments.callee.parent(B.from, B.to);
    }
});
Element.Properties.tween = {
    set: function(A){
        var B = this.retrieve("tween");
        if (B) {
            B.cancel();
        }
        return this.store("tween", new Fx.Tween(this, null, $extend({
            link: "cancel"
        }, A)));
    },
    get: function(C, A){
        if (A || !this.retrieve("tween")) {
            this.set("tween", A);
        }
        var B = this.retrieve("tween");
        B.property = C;
        return B;
    }
};
Element.implement({
    tween: function(B, A){
        this.get("tween", B).start(A);
        return this;
    },
    fade: function(A){
        var B = this.get("tween", "opacity");
        A = $pick(A, "toggle");
        switch (A) {
            case "in":
                B.start(1);
                break;
            case "out":
                B.start(0);
                break;
            case "show":
                B.set(1);
                break;
            case "hide":
                B.set(0);
                break;
            case "toggle":
                B.start((function(){
                    return (this.getStyle("visibility") == "hidden") ? 1 : 0;
                }).bind(this));
                break;
            default:
                B.start(A);
        }
        return this;
    },
    highlight: function(A){
        this.get("tween", "background-color").start(A || "#ffff88", function(){
            var B = this.getStyle("background-color");
            return (B == "transparent") ? "#ffffff" : B;
        }
.bind(this));
        return this;
    },
    effect: function(B, A){
        return new Fx.Tween(this, B, A);
    }
});
Fx.Style = Fx.Tween;
Fx.Morph = new Class({
    Extends: Fx.CSS,
    initialize: function(B, A){
        this.element = this.pass = $(B);
        arguments.callee.parent(A);
    },
    set: function(A){
        for (var B in A) {
            this.render(this.element, B, A[B]);
        }
        return this;
    },
    compute: function(E, D, C){
        var A = {};
        for (var B in E) {
            A[B] = arguments.callee.parent(E[B], D[B], C);
        }
        return A;
    },
    start: function(B){
        if (!this.check(B)) {
            return this;
        }
        if ($type(B) == "string") {
            B = this.search(B);
        }
        var E = {}, D = {};
        for (var C in B) {
            var A = this.prepare(this.element, C, B[C]);
            E[C] = A.from;
            D[C] = A.to;
        }
        return arguments.callee.parent(E, D);
    }
});
Element.Properties.morph = {
    set: function(A){
        var B = this.retrieve("morph");
        if (B) {
            B.cancel();
        }
        return this.store("morph", new Fx.Morph(this, $extend({
            link: "cancel"
        }, A)));
    },
    get: function(A){
        if (A || !this.retrieve("morph")) {
            this.set("morph", A);
        }
        return this.retrieve("morph");
    }
};
Element.implement({
    morph: function(A){
        this.get("morph").start(A);
        return this;
    },
    effects: function(A){
        return new Fx.Morph(this, A);
    }
});
Fx.Styles = Fx.Morph;
Fx.Slide = new Class({
    Extends: Fx,
    options: {
        mode: "vertical"
    },
    initialize: function(B, A){
        this.addEvent("onComplete", function(){
            this.open = (this.wrapper["offset" + this.layout.capitalize()] != 0);
            if (this.open) {
                this.wrapper.setStyle(this.layout, "auto");
                if (Browser.Engine.webkit419) {
                    this.element.dispose().inject(this.wrapper);
                }
            }
        }, true);
        this.element = this.pass = $(B);
        arguments.callee.parent(A);
        var C = this.element.retrieve("wrapper");
        this.wrapper = C || new Element("div", {
            styles: $extend(this.element.getStyles("margin", "position"), {
                "overflow": "hidden"
            })
        }).wraps(this.element);
        this.element.store("wrapper", this.wrapper).setStyle("margin", 0);
        this.now = [];
        this.open = true;
    },
    vertical: function(){
        this.margin = "margin-top";
        this.layout = "height";
        this.offset = this.element.offsetHeight;
    },
    horizontal: function(){
        this.margin = "margin-left";
        this.layout = "width";
        this.offset = this.element.offsetWidth;
    },
    set: function(A){
        this.element.setStyle(this.margin, A[0]);
        this.wrapper.setStyle(this.layout, A[1]);
        return this;
    },
    compute: function(D, C, B){
        var A = [];
        (2).times(function(E){
            A[E] = Fx.compute(D[E], C[E], B);
        });
        return A;
    },
    start: function(B, E){
        if (!this.check(B, E)) {
            return this;
        }
        this[E || this.options.mode]();
        var D = this.element.getStyle(this.margin).toInt();
        var C = this.wrapper.getStyle(this.layout).toInt();
        var A = [[D, C], [0, this.offset]];
        var G = [[D, C], [-this.offset, 0]];
        var F;
        switch (B) {
            case "in":
                F = A;
                break;
            case "out":
                F = G;
                break;
            case "toggle":
                F = (this.wrapper["offset" + this.layout.capitalize()] == 0) ? A : G;
        }
        return arguments.callee.parent(F[0], F[1]);
    },
    slideIn: function(A){
        return this.start("in", A);
    },
    slideOut: function(A){
        return this.start("out", A);
    },
    hide: function(A){
        this[A || this.options.mode]();
        this.open = false;
        return this.set([-this.offset, 0]);
    },
    show: function(A){
        this[A || this.options.mode]();
        this.open = true;
        return this.set([0, this.offset]);
    },
    toggle: function(A){
        return this.start("toggle", A);
    }
});
Element.Properties.slide = {
    set: function(B){
        var A = this.retrieve("slide");
        if (A) {
            A.cancel();
        }
        return this.store("slide", new Fx.Slide(this, $extend({
            link: "cancel"
        }, B)));
    },
    get: function(A){
        if (A || !this.retrieve("slide")) {
            this.set("slide", A);
        }
        return this.retrieve("slide");
    }
};
Element.implement({
    slide: function(B){
        B = B || "toggle";
        var A = this.get("slide");
        switch (B) {
            case "hide":
                A.hide();
                break;
            case "show":
                A.show();
                break;
            default:
                A.start(B);
        }
        return this;
    }
});
Fx.Scroll = new Class({
    Extends: Fx,
    options: {
        offset: {
            "x": 0,
            "y": 0
        },
        wheelStops: true
    },
    initialize: function(B, A){
        this.element = this.pass = $(B);
        arguments.callee.parent(A);
        var D = this.cancel.bind(this, false);
        switch ($type(this.element)) {
            case "window":
                this.element = this.element.document;
                break;
            case "element":
                if (this.element.get("tag") == "body") {
                    this.element = this.element.ownerDocument;
                }
        }
        var C = this.element;
        if (this.options.wheelStops) {
            this.addEvent("onStart", function(){
                C.addEvent("mousewheel", D);
            }, true);
            this.addEvent("onComplete", function(){
                C.removeEvent("mousewheel", D);
            }, true);
        }
    },
    set: function(){
        var A = Array.flatten(arguments);
        this.element.scrollTo(A[0], A[1]);
    },
    compute: function(D, C, B){
        var A = [];
        (2).times(function(E){
            A.push(Fx.compute(D[E], C[E], B));
        });
        return A;
    },
    start: function(C, H){
        if (!this.check(C, H)) {
            return this;
        }
        var E = this.element.getOffsetSize(), F = this.element.getScrollSize(), B = this.element.getScroll(), D = {
            "x": C,
            "y": H
        };
        for (var G in D) {
            var A = F[G] - E[G];
            if ($chk(D[G])) {
                D[G] = ($type(D[G]) == "number") ? D[G].limit(0, A) : A;
            }
            else {
                D[G] = B[G];
            }
            D[G] += this.options.offset[G];
        }
        return arguments.callee.parent([B.x, B.y], [D.x, D.y]);
    },
    toTop: function(){
        return this.start(false, 0);
    },
    toLeft: function(){
        return this.start(0, false);
    },
    toRight: function(){
        return this.start("right", false);
    },
    toBottom: function(){
        return this.start(false, "bottom");
    },
    toElement: function(C){
        var B = Element.getPosition($(C, true), this.element);
        var A = ($type(this.element) == "element") ? this.element.getScroll() : {
            x: 0,
            y: 0
        };
        return this.start(B.x + A.x, B.y + A.y);
    }
});
Fx.Scroll.implement({
    scrollTo: function(B, A){
        return this.start(B, A);
    }
});
(function(){
    var A = Fx.prototype.initialize;
    Fx.prototype.initialize = function(B){
        A.call(this, B);
        var C = this.options.transition;
        if ($type(C) == "string" && (C = C.split(":"))) {
            var D = Fx.Transitions;
            D = D[C[0]] || D[C[0].capitalize()];
            if (C[1]) {
                D = D["ease" + C[1].capitalize() + (C[2] ? C[2].capitalize() : "")];
            }
            this.options.transition = D;
        }
    };
})();
Fx.Transition = function(B, A){
    A = $splat(A);
    return $extend(B, {
        easeIn: function(C){
            return B(C, A);
        },
        easeOut: function(C){
            return 1 - B(1 - C, A);
        },
        easeInOut: function(C){
            return (C <= 0.5) ? B(2 * C, A) / 2 : (2 - B(2 * (1 - C), A)) / 2;
        }
    });
};
Fx.Transitions = new Hash({
    linear: $arguments(0)
});
Fx.Transitions.extend = function(A){
    for (var B in A) {
        Fx.Transitions[B] = new Fx.Transition(A[B]);
    }
};
Fx.Transitions.extend({
    Pow: function(B, A){
        return Math.pow(B, A[0] || 6);
    },
    Expo: function(A){
        return Math.pow(2, 8 * (A - 1));
    },
    Circ: function(A){
        return 1 - Math.sin(Math.acos(A));
    },
    Sine: function(A){
        return 1 - Math.sin((1 - A) * Math.PI / 2);
    },
    Back: function(B, A){
        A = A[0] || 1.618;
        return Math.pow(B, 2) * ((A + 1) * B - A);
    },
    Bounce: function(D){
        var C;
        for (var B = 0, A = 1; 1; B += A, A /= 2) {
            if (D >= (7 - 4 * B) / 11) {
                C = -Math.pow((11 - 6 * B - 11 * D) / 4, 2) + A * A;
                break;
            }
        }
        return C;
    },
    Elastic: function(B, A){
        return Math.pow(2, 10 * --B) * Math.cos(20 * B * Math.PI * (A[0] || 1) / 3);
    }
});
["Quad", "Cubic", "Quart", "Quint"].each(function(B, A){
    Fx.Transitions[B] = new Fx.Transition(function(C){
        return Math.pow(C, [A + 2]);
    });
});
var Request = new Class({
    Implements: [Chain, Events, Options],
    options: {
        url: "",
        data: "",
        headers: {},
        async: true,
        method: "post",
        link: "ignore",
        isSuccess: null,
        emulation: true,
        urlEncoded: true,
        encoding: "utf-8",
        evalScripts: false,
        evalResponse: false
    },
    getXHR: function(){
        return (window.XMLHttpRequest) ? new XMLHttpRequest() : ((window.ActiveXObject) ? new ActiveXObject("Microsoft.XMLHTTP") : false);
    },
    initialize: function(A){
        if (!(this.xhr = this.getXHR())) {
            return;
        }
        this.setOptions(A);
        this.options.isSuccess = this.options.isSuccess || this.isSuccess;
        this.headers = new Hash(this.options.headers).extend({
            "X-Requested-With": "XMLHttpRequest",
            "Accept": "text/javascript, text/html, application/xml, text/xml, */*"
        });
    },
    onStateChange: function(){
        if (this.xhr.readyState != 4 || !this.running) {
            return;
        }
        this.running = false;
        this.status = 0;
        $try(function(){
            this.status = this.xhr.status;
        }, this);
        if (this.options.isSuccess.call(this, this.status)) {
            this.response = {
                text: this.xhr.responseText,
                xml: this.xhr.responseXML
            };
            this.onSuccess(this.response.text, true);
        }
        else {
            this.response = {
                text: null,
                xml: null
            };
            this.onFailure();
        }
        this.xhr.onreadystatechange = $empty;
    },
    isSuccess: function(){
        return ((this.status >= 200) && (this.status < 300));
    },
    processScripts: function(A){
        if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader("Content-type"))) {
            return $exec(A);
        }
        return A.stripScripts(this.options.evalScripts);
    },
    onSuccess: function(A, B){
        if (B && $type(A) == "string") {
            A = this.processScripts(A);
        }
        this.fireEvent("onComplete", A).fireEvent("onSuccess", A).callChain();
    },
    onFailure: function(){
        this.fireEvent("onComplete", arguments).fireEvent("onFailure", arguments);
    },
    setHeader: function(A, B){
        this.headers.set(A, B);
        return this;
    },
    getHeader: function(A){
        return $try(function(){
            return this.getResponseHeader(A);
        }, this.xhr) || null;
    },
    check: function(){
        if (!this.running) {
            return true;
        }
        switch (this.options.link) {
            case "cancel":
                this.cancel();
                return true;
            case "chain":
                this.chain(this.send.bind(this, arguments));
                return false;
        }
        return false;
    },
    send: function(D){
        if (!this.check(D)) {
            return this;
        }
        this.running = true;
        var E = $type(D);
        if (E == "string" || E == "element") {
            D = {
                data: D
            };
        }
        var A = this.options;
        D = $extend({
            data: A.data,
            url: A.url,
            method: A.method
        }, D);
        var G = D.data, C = D.url, H = D.method;
        switch ($type(G)) {
            case "element":
                G = $(G).toQueryString();
                break;
            case "object":
            case "hash":
                G = Hash.toQueryString(G);
        }
        if (this.options.emulation &&["put","delete"] .contains(H)) {
            var B = "_method=" + H;
            G = (G) ? B + "&" + G : B;
            H = "post";
        }
        if (this.options.urlEncoded && H == "post") {
            var F = (this.options.encoding) ? "; charset=" + this.options.encoding : "";
            this.headers.set("Content-type", "application/x-www-form-urlencoded" + F);
        }
        if (G && H == "get") {
            C = C + (C.contains("?") ? "&" : "?") + G;
            G = null;
        }
        this.xhr.open(H.toUpperCase(), C, this.options.async);
        this.xhr.onreadystatechange = this.onStateChange.bind(this);
        this.headers.each(function(J, I){
            try {
                this.xhr.setRequestHeader(I, J);
            } 
            catch (K) {
                this.fireEvent("onException", [K, I, J]);
            }
        }, this);
        this.fireEvent("onRequest");
        this.xhr.send(G);
        if (!this.options.async) {
            this.onStateChange();
        }
        return this;
    },
    cancel: function(){
        if (!this.running) {
            return this;
        }
        this.running = false;
        this.xhr.abort();
        this.xhr.onreadystatechange = $empty;
        this.xhr = this.getXHR();
        this.fireEvent("onCancel");
        return this;
    }
});
(function(){
    var A = {};
    ["get", "post", "GET", "POST", "PUT", "DELETE"].each(function(B){
        A[B] = function(){
            var C = Array.link(arguments, {
                url: String.type,
                data: $defined
            });
            return this.send($extend(C, {
                method: B.toLowerCase()
            }));
        };
    });
    Request.implement(A);
})();
Element.Properties.send = {
    get: function(A){
        if (A || !this.retrieve("send")) {
            this.set("send", A);
        }
        return this.retrieve("send");
    },
    set: function(A){
        var B = this.retrieve("send");
        if (B) {
            B.cancel();
        }
        return this.store("send", new Request($extend({
            data: this,
            link: "cancel",
            method: this.get("method") || "post",
            url: this.get("action")
        }, A)));
    }
};
Element.implement({
    send: function(A){
        var B = this.get("send");
        B.send({
            data: this,
            url: A || B.options.url
        });
        return this;
    }
});
Object.toQueryString = Hash.toQueryString;
var XHR = new Class({
    Extends: Request,
    options: {
        update: false
    },
    initialize: function(B, A){
        arguments.callee.parent(A);
        this.onComplete = $empty;
        this.url = B;
    },
    request: function(A){
        return this.send(this.url, A);
    },
    send: function(A, B){
        if (!this.check(A, B)) {
            return this;
        }
        return arguments.callee.parent({
            url: A,
            data: B
        });
    },
    onSuccess: function(B, A){
        if (this.options.update) {
            $(this.options.update).empty().set("html", B);
        }
        arguments.callee.parent(B, A);
        this.fireEvent("onComplete", [B, A]);
    }
});
var Ajax = XHR;
Request.HTML = new Class({
    Extends: Request,
    options: {
        update: false,
        evalScripts: true,
        filter: false
    },
    processHTML: function(B){
        var A = B.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
        return (A) ? A[1] : B;
    },
    onSuccess: function(D){
        var C = this.options, A = this.response;
        A.html = this.processScripts(this.processHTML(D));
        var B = new Element("div", {
            html: A.html
        });
        A.elements = B.getElements("*");
        A.tree = (C.filter) ? A.elements.filterBy(C.filter) : $A(B.childNodes).filter(function(E){
            return ($type(E) != "whitespace");
        });
        if (C.update) {
            $(C.update).empty().adopt(A.tree);
        }
        arguments.callee.parent([A.tree, A.elements, A.html], false);
    }
});
Element.Properties.load = {
    get: function(A){
        if (A || !this.retrieve("load")) {
            this.set("load", A);
        }
        return this.retrieve("load");
    },
    set: function(A){
        var B = this.retrieve("load");
        if (B) {
            B.cancel();
        }
        return this.store("load", new Request.HTML($extend({
            link: "cancel",
            update: this,
            method: "get"
        }, A)));
    }
};
Element.implement({
    load: function(){
        this.get("load").send(Array.link(arguments, {
            data: Object.type,
            url: String.type
        }));
        return this;
    }
});
Request.JSON = new Class({
    Extends: Request,
    options: {
        secure: true
    },
    initialize: function(A){
        arguments.callee.parent(A);
        this.headers.extend({
            "Accept": "application/json",
            "X-Request": "JSON"
        });
    },
    onSuccess: function(A){
        this.response.json = JSON.decode(A, this.options.secure);
        arguments.callee.parent([this.response.json], false);
    }
});
JSON.Remote = new Class({
    options: {
        key: "json"
    },
    Extends: Request.JSON,
    initialize: function(B, A){
        arguments.callee.parent(A);
        this.onComplete = $empty;
        this.url = B;
    },
    send: function(A){
        if (!this.check(A)) {
            return this;
        }
        return arguments.callee.parent({
            url: this.url,
            data: {
                json: Json.encode(A)
            }
        });
    },
    onSuccess: function(A){
        arguments.callee.parent(A);
        this.fireEvent("onComplete", [this.response.json]);
    }
});
var Drag = new Class({
    Implements: [Events, Options],
    options: {
        snap: 6,
        unit: "px",
        grid: false,
        limit: false,
        handle: false,
        modifiers: {
            x: "left",
            y: "top"
        }
    },
    initialize: function(){
        var A = Array.link(arguments, {
            "options": Object.type,
            "element": $defined
        });
        this.element = $(A.element);
        this.document = this.element.ownerDocument;
        this.setOptions(A.options ||
        {});
        this.handle = $(this.options.handle) || this.element;
        this.mouse = {
            "now": {},
            "pos": {}
        };
        this.value = {
            "start": {},
            "now": {}
        };
        this.bound = {
            "start": this.start.bind(this),
            "check": this.check.bind(this),
            "drag": this.drag.bind(this),
            "stop": this.stop.bind(this),
            "cancel": this.cancel.bind(this)
        };
        this.attach();
    },
    attach: function(){
        this.handle.addEvent("mousedown", this.bound.start);
        return this;
    },
    detach: function(){
        this.handle.removeEvent("mousedown", this.bound.start);
        return this;
    },
    start: function(C){
        this.fireEvent("onBeforeStart", this.element);
        this.mouse.start = C.page;
        var A = this.options.limit;
        this.limit = {
            "x": [],
            "y": []
        };
        for (var D in this.options.modifiers) {
            if (!this.options.modifiers[D]) {
                continue;
            }
            this.value.now[D] = this.element.getStyle(this.options.modifiers[D]).toInt();
            this.mouse.pos[D] = C.page[D] - this.value.now[D];
            if (A && A[D]) {
                for (var B = 2; B--; B) {
                    if ($chk(A[D][B])) {
                        this.limit[D][B] = $lambda(A[D][B])();
                    }
                }
            }
        }
        if ($type(this.options.grid) == "number") {
            this.options.grid = {
                "x": this.options.grid,
                "y": this.options.grid
            };
        }
        this.document.addEvent("mousemove", this.bound.check);
        this.document.addEvent("mouseup", this.bound.cancel);
        C.stop();
    },
    check: function(A){
        var B = Math.round(Math.sqrt(Math.pow(A.page.x - this.mouse.start.x, 2) + Math.pow(A.page.y - this.mouse.start.y, 2)));
        if (B > this.options.snap) {
            this.cancel();
            this.document.addEvent("mousemove", this.bound.drag);
            this.document.addEvent("mouseup", this.bound.stop);
            this.fireEvent("onStart", this.element);
            this.fireEvent("onSnap", this.element);
        }
        A.stop();
    },
    drag: function(A){
        this.mouse.now = A.page;
        for (var B in this.options.modifiers) {
            if (!this.options.modifiers[B]) {
                continue;
            }
            this.value.now[B] = this.mouse.now[B] - this.mouse.pos[B];
            if (this.options.limit && this.limit[B]) {
                if ($chk(this.limit[B][1]) && (this.value.now[B] > this.limit[B][1])) {
                    this.value.now[B] = this.limit[B][1];
                }
                else {
                    if ($chk(this.limit[B][0]) && (this.value.now[B] < this.limit[B][0])) {
                        this.value.now[B] = this.limit[B][0];
                    }
                }
            }
            if (this.options.grid[B]) {
                this.value.now[B] -= (this.value.now[B] % this.options.grid[B]);
            }
            this.element.setStyle(this.options.modifiers[B], this.value.now[B] + this.options.unit);
        }
        this.fireEvent("onDrag", this.element);
        A.stop();
    },
    cancel: function(A){
        this.document.removeEvent("mousemove", this.bound.check);
        this.document.removeEvent("mouseup", this.bound.cancel);
        if (A) {
            this.fireEvent("onCancel", this.element);
        }
    },
    stop: function(A){
        this.document.removeEvent("mousemove", this.bound.drag);
        this.document.removeEvent("mouseup", this.bound.stop);
        if (A) {
            this.fireEvent("onComplete", this.element);
        }
    }
});
Element.implement({
    makeResizable: function(A){
        return new Drag(this, $merge({
            modifiers: {
                "x": "width",
                "y": "height"
            }
        }, A));
    }
});
Drag.Base = Drag;
Drag.Move = new Class({
    Extends: Drag,
    options: {
        droppables: [],
        container: false
    },
    initialize: function(C, B){
        arguments.callee.parent(C, B);
        this.droppables = $$(this.options.droppables);
        this.container = $(this.options.container);
        var A = (this.element.positioned()) ? this.element.getStyle("position") : "absolute";
        this.element.position(this.element.getRelativePosition()).setStyle("position", A);
    },
    start: function(B){
        if (this.overed) {
            this.overed.fireEvent("leave", [this.element, this]);
            this.overed = null;
        }
        if (this.container) {
            var D = this.element, J = this.container, E = J.getCoordinates(D.getOffsetParent()), F = {}, A = {};
            ["top", "right", "bottom", "left"].each(function(K){
                F[K] = J.getStyle("padding-" + K).toInt();
                A[K] = D.getStyle("margin-" + K).toInt();
            }, this);
            var C = D.offsetWidth + A.left + A.right, I = D.offsetHeight + A.top + A.bottom;
            var H = [E.left + F.left, E.right - F.right - C];
            var G = [E.top + F.top, E.bottom - F.bottom - I];
            this.options.limit = {
                x: H,
                y: G
            };
        }
        arguments.callee.parent(B);
    },
    checkAgainst: function(B){
        B = B.getCoordinates();
        var A = this.mouse.now;
        return (A.x > B.left && A.x < B.right && A.y < B.bottom && A.y > B.top);
    },
    checkDroppables: function(){
        var A = this.droppables.filter(this.checkAgainst, this).getLast();
        if (this.overed != A) {
            if (this.overed) {
                this.overed.fireEvent("leave", [this.element, this]);
            }
            this.overed = A ? A.fireEvent("over", [this.element, this]) : null;
        }
    },
    drag: function(A){
        arguments.callee.parent(A);
        if (this.droppables.length) {
            this.checkDroppables();
        }
    },
    stop: function(A){
        this.checkDroppables();
        if (this.overed) {
            this.overed.fireEvent("drop", [this.element, this]);
        }
        else {
            this.element.fireEvent("emptydrop", this);
        }
        return arguments.callee.parent(A);
    }
});
Element.implement({
    makeDraggable: function(A){
        return new Drag.Move(this, A);
    }
});
Selectors.Pseudo.children = {
    parser: function(A){
        A = (A) ? A.match(/^([-+]?\d*)?([\-+:])?([-+]?\d*)?$/) : [null, 0, false, 0];
        if (!A) {
            return false;
        }
        A[1] = parseInt(A[1]) || 0;
        var B = parseInt(A[3]);
        A[3] = ($chk(B)) ? B : 0;
        switch (A[2]) {
            case "-":
            case "+":
            case ":":
                return {
                    "a": A[1],
                    "b": A[3],
                    "special": A[2]
                };
            default:
                return {
                    "a": A[1],
                    "b": 0,
                    "special": "index"
                };
        }
    },
    xpath: function(E){
        var C = "";
        var B = "count(../child::*)";
        var D = E.a + " + " + ((E.a < 0) ? B : 0);
        var A = E.b + " + " + ((E.b < 0) ? B : 0);
        var F = "position()";
        switch (E.special) {
            case "-":
                A = "((" + D + " - " + A + ") mod (" + B + "))";
                D += " + 1";
                A += " + 1";
                C = "(" + A + " < 1 and (" + F + " <= " + D + " or " + F + " >= (" + A + " + " + B + "))) or (" + F + " <= " + D + " and " + F + " >= " + A + ")";
                break;
            case "+":
                A = "((" + D + " + " + A + ") mod ( " + B + "))";
            case ":":
                D += " + 1";
                A += " + 1";
                C = "(" + A + " < " + D + " and (" + F + " >= " + D + " or " + F + " <= " + A + ")) or (" + F + " >= " + D + " and " + F + " <= " + A + ")";
                break;
            default:
                C = (D + " + 1");
        }
        return "[" + C + "]";
    },
    filter: function(G, H, E, F){
        var C = false;
        var B = F.length;
        var D = H.a + ((H.a < 0) ? B : 0);
        var A = H.b + ((H.b < 0) ? B : 0);
        switch (H.special) {
            case "-":
                A = (D - A) % B;
                C = (A < 0) ? (E <= (D - 1) || E >= (A + B)) : (E <= D && E >= A);
                break;
            case "+":
                A = (A + D) % B;
            case ":":
                C = (A < D) ? (E >= D || E <= A) : (E >= D && E <= A);
                break;
            default:
                C = (F[D] == G);
        }
        return C;
    }
};
Hash.Cookie = new Class({
    Implements: Options,
    options: {
        autoSave: true
    },
    initialize: function(B, A){
        this.name = B;
        this.setOptions(A);
        this.load();
    },
    save: function(){
        var A = JSON.encode(this.hash);
        if (A.length > 4096) {
            return false;
        }
        if (A.length == 2) {
            Cookie.remove(this.name, this.options);
        }
        else {
            Cookie.set(this.name, A, this.options);
        }
        return true;
    },
    load: function(){
        this.hash = new Hash(JSON.decode(Cookie.get(this.name), true));
        return this;
    }
});
(function(){
    var A = {};
    Hash.getKeys(Hash.prototype).each(function(B){
        A[B] = function(){
            var C = Hash.prototype[B].apply(this.hash, arguments);
            if (this.options.autoSave) {
                this.save();
            }
            return C;
        };
    });
    Hash.Cookie.implement(A);
})();
var Sortables = new Class({
    Implements: [Events, Options],
    options: {
        snap: 4,
        handle: false,
        revert: false,
        constrain: false,
        cloneOpacity: 0.7,
        elementOpacity: 0.3
    },
    initialize: function(A, B){
        this.setOptions(B);
        this.elements = [];
        this.lists = [];
        this.idle = true;
        this.addLists($$($(A) || A));
        if (this.options.revert) {
            this.effect = new Fx.Morph(null, $merge({
                duration: 250,
                link: "cancel"
            }, this.options.revert));
        }
    },
    attach: function(){
        this.addLists(this.lists);
        return this;
    },
    detach: function(){
        this.lists = this.removeLists(this.lists);
        return this;
    },
    addItems: function(){
        Array.flatten(arguments).each(function(A){
            this.elements.push(A);
            var C = A.retrieve("sortables:start", this.start.bindWithEvent(this, A));
            var B = A.retrieve("sortables:insert", this.insert.bind(this, A));
            (this.options.handle ? A.getElement(this.options.handle) || A : A).addEvent("mousedown", C);
            A.addEvent("over", B);
        }, this);
        return this;
    },
    addLists: function(){
        Array.flatten(arguments).each(function(A){
            this.lists.push(A);
            this.addItems(A.getChildren());
            A.addEvent("over", A.retrieve("sortables:insert", this.insert.bind(this, [A, "inside"])));
        }, this);
        return this;
    },
    removeItems: function(){
        var A = [];
        Array.flatten(arguments).each(function(B){
            A.push(B);
            this.elements.remove(B);
            var D = B.retrieve("sortables:start");
            var C = B.retrieve("sortables:insert");
            (this.options.handle ? B.getElement(this.options.handle) || B : B).removeEvent("mousedown", D);
            B.removeEvent("over", C);
        }, this);
        return A;
    },
    removeLists: function(){
        var A = [];
        Array.flatten(arguments).each(function(B){
            A.push(B);
            this.lists.remove(B);
            this.removeItems(B.getChildren());
            B.removeEvent("over", B.retrieve("sortables:insert"));
        }, this);
        return A;
    },
    getClone: function(A){
        return A.clone(true).setStyles({
            "margin": "0px",
            "position": "absolute",
            "visibility": "hidden"
        }).inject(this.list).position(A.getRelativePosition());
    },
    getDroppables: function(){
        var A = this.list.getChildren();
        if (!this.options.constrain) {
            A = this.lists.concat(A).remove(this.list);
        }
        return A.remove(this.clone).remove(this.element);
    },
    insert: function(B, A){
        if (A) {
            this.list = B;
            this.drag.droppables = this.getDroppables();
        }
        A = A || (this.element.getAllPrevious().contains(B) ? "before" : "after");
        this.element.inject(B, A);
        this.fireEvent("onSort", [this.element, this.clone]);
    },
    start: function(B, A){
        if (!this.idle) {
            return;
        }
        this.idle = false;
        this.element = A;
        this.opacity = A.get("opacity");
        this.list = A.getParent();
        this.clone = this.getClone(A);
        this.drag = this.clone.makeDraggable({
            snap: this.options.snap,
            container: this.options.constrain && this.clone.getParent(),
            droppables: this.getDroppables(),
            onStart: function(){
                B.stop();
                this.clone.set("opacity", this.options.cloneOpacity);
                this.element.set("opacity", this.options.elementOpacity);
                this.fireEvent("onStart", [this.element, this.clone]);
            }
.bind(this)            ,
            onCancel: this.reset.bind(this),
            onComplete: this.end.bind(this)
        });
        this.drag.start(B);
    },
    end: function(){
        this.element.set("opacity", this.opacity);
        this.drag.detach();
        if (this.effect) {
            var A = this.element.getStyles("width", "height");
            var B = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent), this.clone.getParent().positioned());
            this.effect.element = this.clone;
            this.effect.start({
                "top": B.top,
                "left": B.left,
                "width": A.width,
                "height": A.height,
                "opacity": 0.25
            }).chain(this.reset.bind(this));
        }
        else {
            this.reset();
        }
    },
    reset: function(){
        this.idle = true;
        this.clone.destroy();
        this.fireEvent("onComplete", this.element);
    },
    serialize: function(C, A){
        var B = this.lists.map(function(D){
            return D.getChildren().map(A ||
            function(F, E){
                return F.get("id");
            }, this);
        }, this);
        if (this.lists.length == 1) {
            C = 0;
        }
        return $chk(C) && C >= 0 && C < this.lists.length ? B[C] : B;
    }
});
var Tips = new Class({
    Implements: [Events, Options],
    options: {
        onShow: function(A){
            A.setStyle("visibility", "visible");
        },
        onHide: function(A){
            A.setStyle("visibility", "hidden");
        },
        maxTitleChars: 30,
        showDelay: 100,
        hideDelay: 100,
        className: "tool",
        offsets: {
            "x": 16,
            "y": 16
        },
        fixed: false
    },
    initialize: function(B, A){
        this.setOptions(A);
        B = $$(B);
        this.document = (B.length) ? B[0].ownerDocument : document;
        this.toolTip = new Element("div", {
            "class": this.options.className + "-tip",
            "styles": {
                "position": "absolute",
                "top": "0",
                "left": "0",
                "visibility": "hidden"
            }
        }, this.document).inject(this.document.body);
        this.wrapper = new Element("div").inject(this.toolTip);
        B.each(this.build, this);
    },
    build: function(B){
        B.$attributes.myTitle = (B.href && B.get("tag") == "a") ? B.href.replace("http://", "") : (B.rel || false);
        if (B.title) {
            var C = B.title.split("::");
            if (C.length > 1) {
                B.$attributes.myTitle = C[0].trim();
                B.$attributes.myText = C[1].trim();
            }
            else {
                B.$attributes.myText = B.title;
            }
            B.removeProperty("title");
        }
        else {
            B.$attributes.myText = false;
        }
        if (B.$attributes.myTitle && B.$attributes.myTitle.length > this.options.maxTitleChars) {
            B.$attributes.myTitle = B.$attributes.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
        }
        B.addEvent("mouseenter", function(D){
            this.start(B);
            if (!this.options.fixed) {
                this.locate(D);
            }
            else {
                this.position(B);
            }
        }
.bind(this));
        if (!this.options.fixed) {
            B.addEvent("mousemove", this.locate.bind(this));
        }
        var A = this.end.bind(this);
        B.addEvent("mouseleave", A);
    },
    start: function(A){
        this.wrapper.empty();
        if (A.$attributes.myTitle) {
            this.title = new Element("span").inject(new Element("div", {
                "class": this.options.className + "-title"
            }).inject(this.wrapper)).set("html", A.$attributes.myTitle);
        }
        if (A.$attributes.myText) {
            this.text = new Element("span").inject(new Element("div", {
                "class": this.options.className + "-text"
            }).inject(this.wrapper)).set("html", A.$attributes.myText);
        }
        $clear(this.timer);
        this.timer = this.show.delay(this.options.showDelay, this);
    },
    end: function(A){
        $clear(this.timer);
        this.timer = this.hide.delay(this.options.hideDelay, this);
    },
    position: function(A){
        var B = A.getPosition();
        this.toolTip.setStyles({
            "left": B.x + this.options.offsets.x,
            "top": B.y + this.options.offsets.y
        });
    },
    locate: function(B){
        var D = this.document.getOffsetSize();
        var A = this.document.getScroll();
        var C = {
            "x": this.toolTip.offsetWidth,
            "y": this.toolTip.offsetHeight
        };
        var G = {
            "x": "left",
            "y": "top"
        };
        for (var E in G) {
            var F = B.page[E] + this.options.offsets[E];
            if ((F + C[E] - A[E]) > D[E]) {
                F = B.page[E] - this.options.offsets[E] - C[E];
            }
            this.toolTip.setStyle(G[E], F);
        }
    },
    show: function(){
        if (this.options.timeout) {
            this.timer = this.hide.delay(this.options.timeout, this);
        }
        this.fireEvent("onShow", [this.toolTip]);
    },
    hide: function(){
        this.fireEvent("onHide", [this.toolTip]);
    }
});
var SmoothScroll = new Class({
    Extends: Fx.Scroll,
    initialize: function(B, C){
        arguments.callee.parent(C || window, B);
        this.links = (this.options.links) ? $$(this.options.links) : $$(this.element.document.links);
        var A = this.element.location.href.match(/^[^#]*/)[0] + "#";
        this.links.each(function(E){
            if (E.href.indexOf(A) != 0) {
                return;
            }
            var D = E.href.substr(A.length);
            if (D && $(D)) {
                this.useLink(E, D);
            }
        }, this);
        if (!Browser.Engine.webkit419) {
            this.addEvent("onComplete", function(){
                this.element.location.hash = this.anchor;
            }, true);
        }
    },
    useLink: function(B, A){
        B.addEvent("click", function(C){
            this.anchor = A;
            this.toElement(A);
            C.stop();
        }
.bind(this));
    }
});
var Slider = new Class({
    Implements: [Events, Options],
    options: {
        onTick: function(A){
            this.knob.setStyle(this.property, A);
        },
        offset: 0,
        steps: 100,
        mode: "horizontal"
    },
    initialize: function(E, A, D){
        this.setOptions(D);
        this.element = $(E);
        this.knob = $(A);
        this.previousChange = this.previousEnd = this.step = -1;
        this.element.addEvent("mousedown", this.clickedElement.bind(this));
        var F, B = {}, C = {
            "x": false,
            "y": false
        };
        switch (this.options.mode) {
            case "vertical":
                this.axis = "y";
                this.property = "top";
                F = "offsetHeight";
                break;
            case "horizontal":
                this.axis = "x";
                this.property = "left";
                F = "offsetWidth";
        }
        this.half = this.knob[F] / 2;
        this.max = this.element[F] - this.knob[F] + (this.options.offset * 2);
        this.knob.setStyle("position", "relative").setStyle(this.property, -this.options.offset);
        C[this.axis] = this.property;
        B[this.axis] = [-this.options.offset, this.max - this.options.offset];
        this.drag = new Drag(this.knob, {
            snap: 0,
            limit: B,
            modifiers: C,
            onDrag: this.draggedKnob.bind(this),
            onStart: this.draggedKnob.bind(this),
            onComplete: function(){
                this.draggedKnob();
                this.end();
            }
.bind(this)
        });
    },
    set: function(A){
        this.step = A.limit(0, this.options.steps);
        this.checkStep();
        this.end();
        this.fireEvent("onTick", this.toPosition(this.step));
        return this;
    },
    clickedElement: function(B){
        var A = B.page[this.axis] - this.element.getRelativePosition()[this.axis] - this.half;
        A = A.limit(-this.options.offset, this.max - this.options.offset);
        this.step = this.toStep(A);
        this.checkStep();
        this.end();
        this.fireEvent("onTick", A);
    },
    draggedKnob: function(){
        this.step = this.toStep(this.drag.value.now[this.axis]);
        this.checkStep();
    },
    checkStep: function(){
        if (this.previousChange != this.step) {
            this.previousChange = this.step;
            this.fireEvent("onChange", this.step);
        }
    },
    end: function(){
        if (this.previousEnd !== this.step) {
            this.previousEnd = this.step;
            this.fireEvent("onComplete", this.step + "");
        }
    },
    toStep: function(A){
        return Math.round((A + this.options.offset) / this.max * this.options.steps);
    },
    toPosition: function(A){
        return this.max * A / this.options.steps;
    }
});
var Scroller = new Class({
    Implements: [Events, Options],
    options: {
        area: 20,
        velocity: 1,
        onChange: function(A, B){
            this.element.scrollTo(A, B);
        }
    },
    initialize: function(B, A){
        this.setOptions(A);
        this.element = $(B);
        switch ($type(this.element)) {
            case "window":
                this.element = this.element.document;
                this.listener = $(this.element.body);
                break;
            case "document":
                this.listener = $(this.element.body);
                break;
            case "element":
                this.listener = this.element;
        }
        this.timer = null;
    },
    start: function(){
        this.coord = this.getCoords.bind(this);
        this.listener.addEvent("mousemove", this.coord);
    },
    stop: function(){
        this.listener.removeEvent("mousemove", this.coord);
        this.timer = $clear(this.timer);
    },
    getCoords: function(A){
        this.page = ($type(this.element) == "document") ? A.client : A.page;
        if (!this.timer) {
            this.timer = this.scroll.periodical(50, this);
        }
    },
    scroll: function(){
        var B = this.element.getOffsetSize(), A = this.element.getScroll(), E = this.element.getPosition(), D = {
            "x": 0,
            "y": 0
        };
        for (var C in this.page) {
            if (this.page[C] < (this.options.area + E[C]) && A[C] != 0) {
                D[C] = (this.page[C] - this.options.area - E[C]) * this.options.velocity;
            }
            else {
                if (this.page[C] + this.options.area > (B[C] + E[C]) && B[C] + B[C] != A[C]) {
                    D[C] = (this.page[C] - B[C] + this.options.area - E[C]) * this.options.velocity;
                }
            }
        }
        if (D.y || D.x) {
            this.fireEvent("onChange", [A.x + D.x, A.y + D.y]);
        }
    }
});
var Asset = new Hash({
    javascript: function(C, B){
        B = $merge({
            "onload": $empty
        }, B);
        var A = new Element("script", {
            "src": C,
            "type": "text/javascript"
        }).addEvents({
            "load": B.onload,
            "readystatechange": function(){
                if (this.readyState == "complete") {
                    this.fireEvent("load");
                }
            }
        });
        delete B.onload;
        return A.setProperties(B).inject(document.head);
    },
    css: function(B, A){
        return new Element("link", $merge({
            "rel": "stylesheet",
            "media": "screen",
            "type": "text/css",
            "href": B
        }, A)).inject(document.head);
    },
    image: function(C, B){
        B = $merge({
            "onload": $empty,
            "onabort": $empty,
            "onerror": $empty
        }, B);
        var D = new Image();
        var A = $(D) || new Element("img");
        ["load", "abort", "error"].each(function(E){
            var F = "on" + E;
            var G = B[F];
            delete B[F];
            D[F] = function(){
                if (!D) {
                    return;
                }
                if (!A.parentNode) {
                    A.width = D.width;
                    A.height = D.height;
                }
                D = D.onload = D.onabort = D.onerror = null;
                G.delay(1, A, A);
                A.fireEvent(E, A, 1);
            };
        });
        D.src = A.src = C;
        if (D && D.complete) {
            D.onload.delay(1);
        }
        return A.setProperties(B);
    },
    images: function(D, C){
        C = $merge({
            onComplete: $empty,
            onProgress: $empty
        }, C);
        if (!D.push) {
            D = [D];
        }
        var A = [];
        var B = 0;
        D.each(function(F){
            var E = new Asset.image(F, {
                "onload": function(){
                    C.onProgress.call(this, B, D.indexOf(F));
                    B++;
                    if (B == D.length) {
                        C.onComplete();
                    }
                }
            });
            A.push(E);
        });
        return new Elements(A);
    }
});
Fx.Elements = new Class({
    Extends: Fx.CSS,
    initialize: function(B, A){
        this.elements = this.pass = $$(B);
        arguments.callee.parent(A);
    },
    compute: function(G, H, I){
        var C = {};
        for (var D in G) {
            var A = G[D], E = H[D], F = C[D] = {};
            for (var B in A) {
                F[B] = arguments.callee.parent(A[B], E[B], I);
            }
        }
        return C;
    },
    set: function(B){
        for (var C in B) {
            var A = B[C];
            for (var D in A) {
                this.render(this.elements[C], D, A[D]);
            }
        }
        return this;
    },
    start: function(C){
        if (!this.check(C)) {
            return this;
        }
        var H = {}, I = {};
        for (var D in C) {
            var F = C[D], A = H[D] = {}, G = I[D] = {};
            for (var B in F) {
                var E = this.prepare(this.elements[D], B, F[B]);
                A[B] = E.from;
                G[B] = E.to;
            }
        }
        return arguments.callee.parent(H, I);
    }
});
var Accordion = new Class({
    Extends: Fx.Elements,
    options: {
        display: 0,
        show: false,
        height: true,
        width: false,
        opacity: true,
        fixedHeight: false,
        fixedWidth: false,
        wait: false,
        alwaysHide: false
    },
    initialize: function(){
        var C = Array.link(arguments, {
            "container": Element.type,
            "options": Object.type,
            "togglers": $defined,
            "elements": $defined
        });
        arguments.callee.parent(C.elements, C.options);
        this.togglers = $$(C.togglers);
        this.container = $(C.container);
        this.previous = -1;
        if (this.options.alwaysHide) {
            this.options.wait = true;
        }
        if ($chk(this.options.show)) {
            this.options.display = false;
            this.previous = this.options.show;
        }
        if (this.options.start) {
            this.options.display = false;
            this.options.show = false;
        }
        this.effects = {};
        if (this.options.opacity) {
            this.effects.opacity = "fullOpacity";
        }
        if (this.options.width) {
            this.effects.width = this.options.fixedWidth ? "fullWidth" : "offsetWidth";
        }
        if (this.options.height) {
            this.effects.height = this.options.fixedHeight ? "fullHeight" : "scrollHeight";
        }
        for (var B = 0, A = this.togglers.length; B < A; B++) {
            this.addSection(this.togglers[B], this.elements[B]);
        }
        this.elements.each(function(E, D){
            if (this.options.show === D) {
                this.fireEvent("onActive", [this.togglers[D], E]);
            }
            else {
                for (var F in this.effects) {
                    E.setStyle(F, 0);
                }
            }
        }, this);
        if ($chk(this.options.display)) {
            this.display(this.options.display);
        }
    },
    addSection: function(E, C, G){
        E = $(E);
        C = $(C);
        var F = this.togglers.contains(E);
        var B = this.togglers.length;
        this.togglers.include(E);
        this.elements.include(C);
        if (B && (!F || G)) {
            G = $pick(G, B - 1);
            E.inject(this.togglers[G], "before");
            C.inject(E, "after");
        }
        else {
            if (this.container && !F) {
                E.inject(this.container);
                C.inject(this.container);
            }
        }
        var A = this.togglers.indexOf(E);
        E.addEvent("click", this.display.bind(this, A));
        if (this.options.height) {
            C.setStyles({
                "padding-top": 0,
                "border-top": "none",
                "padding-bottom": 0,
                "border-bottom": "none"
            });
        }
        if (this.options.width) {
            C.setStyles({
                "padding-left": 0,
                "border-left": "none",
                "padding-right": 0,
                "border-right": "none"
            });
        }
        C.fullOpacity = 1;
        if (this.options.fixedWidth) {
            C.fullWidth = this.options.fixedWidth;
        }
        if (this.options.fixedHeight) {
            C.fullHeight = this.options.fixedHeight;
        }
        C.setStyle("overflow", "hidden");
        if (!F) {
            for (var D in this.effects) {
                C.setStyle(D, 0);
            }
        }
        return this;
    },
    display: function(A){
        A = ($type(A) == "element") ? this.elements.indexOf(A) : A;
        if ((this.timer && this.options.wait) || (A === this.previous && !this.options.alwaysHide)) {
            return this;
        }
        this.previous = A;
        var B = {};
        this.elements.each(function(E, D){
            B[D] = {};
            var C = (D != A) || (this.options.alwaysHide && (E.offsetHeight > 0));
            this.fireEvent(C ? "onBackground" : "onActive", [this.togglers[D], E]);
            for (var F in this.effects) {
                B[D][F] = C ? 0 : E[this.effects[F]];
            }
        }, this);
        return this.start(B);
    }
});

